Skip to content

Commit 4497ff3

Browse files
committed
Emit feature gate suggestion
1 parent e5d9065 commit 4497ff3

File tree

5 files changed

+75
-40
lines changed

5 files changed

+75
-40
lines changed

src/librustc/ich/impls_mir.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ impl_stable_hash_for!(enum mir::BorrowKind {
4646

4747
impl_stable_hash_for!(enum mir::UnsafetyViolationKind {
4848
General,
49-
MinConstFn,
49+
GeneralAndConstFn,
50+
GatedConstFnCall,
5051
ExternStatic(lint_node_id),
5152
BorrowPacked(lint_node_id),
5253
});

src/librustc/mir/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2770,9 +2770,11 @@ impl Location {
27702770
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
27712771
pub enum UnsafetyViolationKind {
27722772
General,
2773-
/// Right now function calls to `const unsafe fn` are the only permitted unsafe operation in
2774-
/// const fn. Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations
2775-
MinConstFn,
2773+
/// Right now function calls to `const unsafe fn` are only permitted behind a feature gate
2774+
/// Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations.
2775+
GatedConstFnCall,
2776+
/// Permitted in const fn and regular fns
2777+
GeneralAndConstFn,
27762778
ExternStatic(ast::NodeId),
27772779
BorrowPacked(ast::NodeId),
27782780
}

src/librustc_mir/transform/check_unsafety.rs

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use rustc::mir::visit::{PlaceContext, Visitor, MutatingUseContext};
2323

2424
use syntax::ast;
2525
use syntax::symbol::Symbol;
26+
use syntax::feature_gate::{emit_feature_err, GateIssue};
2627

2728
use std::ops::Bound;
2829

@@ -96,7 +97,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
9697
if let hir::Unsafety::Unsafe = sig.unsafety() {
9798
self.require_unsafe("call to unsafe function",
9899
"consult the function's documentation for information on how to avoid \
99-
undefined behavior", UnsafetyViolationKind::MinConstFn)
100+
undefined behavior", UnsafetyViolationKind::GatedConstFnCall)
100101
}
101102
}
102103
}
@@ -146,7 +147,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
146147
"initializing type with `rustc_layout_scalar_valid_range` attr",
147148
"initializing a layout restricted type's field with a value outside \
148149
the valid range is undefined behavior",
149-
UnsafetyViolationKind::MinConstFn,
150+
UnsafetyViolationKind::GeneralAndConstFn,
150151
),
151152
}
152153
}
@@ -319,12 +320,21 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
319320
(Safety::Safe, _) => {
320321
for violation in violations {
321322
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+
}
328338
}
329339
if !self.violations.contains(&violation) {
330340
self.violations.push(violation)
@@ -344,13 +354,24 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
344354
for violation in violations {
345355
match violation.kind {
346356
// these are allowed
347-
UnsafetyViolationKind::MinConstFn
357+
UnsafetyViolationKind::GatedConstFnCall => {
348358
// 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(_) => {
351370
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;
354375
if !self.violations.contains(&violation) {
355376
self.violations.push(violation)
356377
}
@@ -400,7 +421,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
400421
source_info,
401422
description: Symbol::intern(description).as_interned_str(),
402423
details: Symbol::intern(details).as_interned_str(),
403-
kind: UnsafetyViolationKind::MinConstFn,
424+
kind: UnsafetyViolationKind::GeneralAndConstFn,
404425
}], &[]);
405426
}
406427
},
@@ -592,6 +613,16 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
592613
} in violations.iter() {
593614
// Report an error.
594615
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 |
595626
UnsafetyViolationKind::General => {
596627
struct_span_err!(
597628
tcx.sess, source_info.span, E0133,
@@ -600,14 +631,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
600631
.note(&details.as_str()[..])
601632
.emit();
602633
}
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",
605638
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+
611643
}
612644
UnsafetyViolationKind::ExternStatic(lint_node_id) => {
613645
tcx.lint_node_note(SAFE_EXTERN_STATICS,

src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ const fn no_unsafe() { unsafe {} }
1818

1919
// not ok
2020
const fn foo8() -> i32 {
21-
unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
21+
unsafe { foo4() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
2222
}
2323
const fn foo9() -> *const String {
24-
unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
24+
unsafe { foo5::<String>() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
2525
}
2626
const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
27-
unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
27+
unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR calls to `const unsafe fn` in const fns
2828
}
2929
const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
3030
//~^ dereferencing raw pointers in constant functions

src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,29 @@ LL | Foo { x: () }.y //~ ERROR not allowed in const fn
1414
|
1515
= help: add #![feature(const_fn_union)] to the crate attributes to enable
1616

17-
error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
17+
error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
1818
--> $DIR/min_const_fn_unsafe.rs:21:14
1919
|
20-
LL | unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
21-
| ^^^^^^ call to unsafe function
20+
LL | unsafe { foo4() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
21+
| ^^^^^^
2222
|
23-
= note: consult the function's documentation for information on how to avoid undefined behavior
23+
= help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
2424

25-
error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
25+
error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
2626
--> $DIR/min_const_fn_unsafe.rs:24:14
2727
|
28-
LL | unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
29-
| ^^^^^^^^^^^^^^^^ call to unsafe function
28+
LL | unsafe { foo5::<String>() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
29+
| ^^^^^^^^^^^^^^^^
3030
|
31-
= note: consult the function's documentation for information on how to avoid undefined behavior
31+
= help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
3232

33-
error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
33+
error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
3434
--> $DIR/min_const_fn_unsafe.rs:27:14
3535
|
36-
LL | unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
37-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
36+
LL | unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR calls to `const unsafe fn` in const fns
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3838
|
39-
= note: consult the function's documentation for information on how to avoid undefined behavior
39+
= help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
4040

4141
error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
4242
--> $DIR/min_const_fn_unsafe.rs:29:51

0 commit comments

Comments
 (0)