@@ -23,6 +23,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext};
23
23
24
24
use syntax:: ast;
25
25
use syntax:: symbol:: Symbol ;
26
+ use syntax:: feature_gate:: { emit_feature_err, GateIssue } ;
26
27
27
28
use std:: ops:: Bound ;
28
29
@@ -96,7 +97,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
96
97
if let hir:: Unsafety :: Unsafe = sig. unsafety ( ) {
97
98
self . require_unsafe ( "call to unsafe function" ,
98
99
"consult the function's documentation for information on how to avoid \
99
- undefined behavior", UnsafetyViolationKind :: MinConstFn )
100
+ undefined behavior", UnsafetyViolationKind :: GatedConstFnCall )
100
101
}
101
102
}
102
103
}
@@ -146,7 +147,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
146
147
"initializing type with `rustc_layout_scalar_valid_range` attr" ,
147
148
"initializing a layout restricted type's field with a value outside \
148
149
the valid range is undefined behavior",
149
- UnsafetyViolationKind :: MinConstFn ,
150
+ UnsafetyViolationKind :: GeneralAndConstFn ,
150
151
) ,
151
152
}
152
153
}
@@ -319,12 +320,21 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
319
320
( Safety :: Safe , _) => {
320
321
for violation in violations {
321
322
let mut violation = violation. clone ( ) ;
322
- if self . min_const_fn {
323
- // overwrite unsafety violation in const fn with a single hard error kind
324
- violation. kind = UnsafetyViolationKind :: MinConstFn ;
325
- } else if let UnsafetyViolationKind :: MinConstFn = violation. kind {
326
- // outside of const fns we treat `MinConstFn` and `General` the same
327
- violation. kind = UnsafetyViolationKind :: General ;
323
+ match violation. kind {
324
+ UnsafetyViolationKind :: GeneralAndConstFn |
325
+ UnsafetyViolationKind :: General => { } ,
326
+ UnsafetyViolationKind :: BorrowPacked ( _) |
327
+ UnsafetyViolationKind :: ExternStatic ( _) => if self . min_const_fn {
328
+ // const fns don't need to be backwards compatible and can
329
+ // emit these violations as a hard error instead of a backwards
330
+ // compat lint
331
+ violation. kind = UnsafetyViolationKind :: General ;
332
+ } ,
333
+ UnsafetyViolationKind :: GatedConstFnCall => {
334
+ // safe code can't call unsafe const fns, this `UnsafetyViolationKind`
335
+ // is only relevant for `Safety::ExplicitUnsafe` in `unsafe const fn`s
336
+ violation. kind = UnsafetyViolationKind :: General ;
337
+ }
328
338
}
329
339
if !self . violations . contains ( & violation) {
330
340
self . violations . push ( violation)
@@ -344,13 +354,24 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
344
354
for violation in violations {
345
355
match violation. kind {
346
356
// these are allowed
347
- UnsafetyViolationKind :: MinConstFn
357
+ UnsafetyViolationKind :: GatedConstFnCall => {
348
358
// if `#![feature(min_const_unsafe_fn)]` is active
349
- if self . tcx . sess . features_untracked ( ) . min_const_unsafe_fn => { } ,
350
- _ => {
359
+ if !self . tcx . sess . features_untracked ( ) . min_const_unsafe_fn {
360
+ if !self . violations . contains ( & violation) {
361
+ self . violations . push ( violation. clone ( ) )
362
+ }
363
+ }
364
+ }
365
+ // these unsafe things are stable in const fn
366
+ UnsafetyViolationKind :: GeneralAndConstFn => { } ,
367
+ UnsafetyViolationKind :: General |
368
+ UnsafetyViolationKind :: BorrowPacked ( _) |
369
+ UnsafetyViolationKind :: ExternStatic ( _) => {
351
370
let mut violation = violation. clone ( ) ;
352
- // overwrite unsafety violation in const fn with a hard error
353
- violation. kind = UnsafetyViolationKind :: MinConstFn ;
371
+ // const fns don't need to be backwards compatible and can
372
+ // emit these violations as a hard error instead of a backwards
373
+ // compat lint
374
+ violation. kind = UnsafetyViolationKind :: General ;
354
375
if !self . violations . contains ( & violation) {
355
376
self . violations . push ( violation)
356
377
}
@@ -400,7 +421,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
400
421
source_info,
401
422
description : Symbol :: intern ( description) . as_interned_str ( ) ,
402
423
details : Symbol :: intern ( details) . as_interned_str ( ) ,
403
- kind : UnsafetyViolationKind :: MinConstFn ,
424
+ kind : UnsafetyViolationKind :: GeneralAndConstFn ,
404
425
} ] , & [ ] ) ;
405
426
}
406
427
} ,
@@ -592,6 +613,16 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
592
613
} in violations. iter ( ) {
593
614
// Report an error.
594
615
match kind {
616
+ UnsafetyViolationKind :: General if tcx. is_min_const_fn ( def_id) => {
617
+ tcx. sess . struct_span_err (
618
+ source_info. span ,
619
+ & format ! ( "{} is unsafe and unsafe operations \
620
+ are not allowed in const fn", description) )
621
+ . span_label ( source_info. span , & description. as_str ( ) [ ..] )
622
+ . note ( & details. as_str ( ) [ ..] )
623
+ . emit ( ) ;
624
+ }
625
+ UnsafetyViolationKind :: GeneralAndConstFn |
595
626
UnsafetyViolationKind :: General => {
596
627
struct_span_err ! (
597
628
tcx. sess, source_info. span, E0133 ,
@@ -600,14 +631,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
600
631
. note ( & details. as_str ( ) [ ..] )
601
632
. emit ( ) ;
602
633
}
603
- UnsafetyViolationKind :: MinConstFn => {
604
- tcx. sess . struct_span_err (
634
+ UnsafetyViolationKind :: GatedConstFnCall => {
635
+ emit_feature_err (
636
+ & tcx. sess . parse_sess ,
637
+ "min_const_unsafe_fn" ,
605
638
source_info. span ,
606
- & format ! ( "{} is unsafe and unsafe operations \
607
- are not allowed in const fn", description) )
608
- . span_label ( source_info. span , & description. as_str ( ) [ ..] )
609
- . note ( & details. as_str ( ) [ ..] )
610
- . emit ( ) ;
639
+ GateIssue :: Language ,
640
+ "calls to `const unsafe fn` in const fns are unstable" ,
641
+ ) ;
642
+
611
643
}
612
644
UnsafetyViolationKind :: ExternStatic ( lint_node_id) => {
613
645
tcx. lint_node_note ( SAFE_EXTERN_STATICS ,
0 commit comments