]> git.lizzy.rs Git - rust.git/commitdiff
Emit feature gate suggestion
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Mon, 5 Nov 2018 17:06:26 +0000 (18:06 +0100)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Tue, 4 Dec 2018 09:17:36 +0000 (10:17 +0100)
src/librustc/ich/impls_mir.rs
src/librustc/mir/mod.rs
src/librustc_mir/transform/check_unsafety.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr

index d98bb82aabad1268a0232e1aa90f0b8b2ae90627..3b9c8ae2d3c507b3a25f1b0df5dd2565f4ae9172 100644 (file)
@@ -46,7 +46,8 @@
 
 impl_stable_hash_for!(enum mir::UnsafetyViolationKind {
     General,
-    MinConstFn,
+    GeneralAndConstFn,
+    GatedConstFnCall,
     ExternStatic(lint_node_id),
     BorrowPacked(lint_node_id),
 });
index 549e13bad642afbe542540365d5791810d61cf63..09b344cd38d258f2fb72453c88461c116a553594 100644 (file)
@@ -2770,9 +2770,11 @@ pub fn dominates(&self, other: Location, dominators: &Dominators<BasicBlock>) ->
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub enum UnsafetyViolationKind {
     General,
-    /// Right now function calls to `const unsafe fn` are the only permitted unsafe operation in
-    /// const fn. Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations
-    MinConstFn,
+    /// Right now function calls to `const unsafe fn` are only permitted behind a feature gate
+    /// Also, even `const unsafe fn` need an `unsafe` block to do the allowed operations.
+    GatedConstFnCall,
+    /// Permitted in const fn and regular fns
+    GeneralAndConstFn,
     ExternStatic(ast::NodeId),
     BorrowPacked(ast::NodeId),
 }
index 671ca355dbfc1ae3914d908dfec6bd6c4d63724e..25dbd160d19f4cb95b8e4d0eb6dd619a7d54836f 100644 (file)
@@ -23,6 +23,7 @@
 
 use syntax::ast;
 use syntax::symbol::Symbol;
+use syntax::feature_gate::{emit_feature_err, GateIssue};
 
 use std::ops::Bound;
 
@@ -96,7 +97,7 @@ fn visit_terminator(&mut self,
                 if let hir::Unsafety::Unsafe = sig.unsafety() {
                     self.require_unsafe("call to unsafe function",
                         "consult the function's documentation for information on how to avoid \
-                         undefined behavior", UnsafetyViolationKind::MinConstFn)
+                         undefined behavior", UnsafetyViolationKind::GatedConstFnCall)
                 }
             }
         }
@@ -146,7 +147,7 @@ fn visit_rvalue(&mut self,
                             "initializing type with `rustc_layout_scalar_valid_range` attr",
                             "initializing a layout restricted type's field with a value outside \
                             the valid range is undefined behavior",
-                            UnsafetyViolationKind::MinConstFn,
+                            UnsafetyViolationKind::GeneralAndConstFn,
                         ),
                     }
                 }
@@ -319,12 +320,21 @@ fn register_violations(&mut self,
             (Safety::Safe, _) => {
                 for violation in violations {
                     let mut violation = violation.clone();
-                    if self.min_const_fn {
-                        // overwrite unsafety violation in const fn with a single hard error kind
-                        violation.kind = UnsafetyViolationKind::MinConstFn;
-                    } else if let UnsafetyViolationKind::MinConstFn = violation.kind {
-                        // outside of const fns we treat `MinConstFn` and `General` the same
-                        violation.kind = UnsafetyViolationKind::General;
+                    match violation.kind {
+                        UnsafetyViolationKind::GeneralAndConstFn |
+                        UnsafetyViolationKind::General => {},
+                        UnsafetyViolationKind::BorrowPacked(_) |
+                        UnsafetyViolationKind::ExternStatic(_) => if self.min_const_fn {
+                            // const fns don't need to be backwards compatible and can
+                            // emit these violations as a hard error instead of a backwards
+                            // compat lint
+                            violation.kind = UnsafetyViolationKind::General;
+                        },
+                        UnsafetyViolationKind::GatedConstFnCall => {
+                            // safe code can't call unsafe const fns, this `UnsafetyViolationKind`
+                            // is only relevant for `Safety::ExplicitUnsafe` in `unsafe const fn`s
+                            violation.kind = UnsafetyViolationKind::General;
+                        }
                     }
                     if !self.violations.contains(&violation) {
                         self.violations.push(violation)
@@ -344,13 +354,24 @@ fn register_violations(&mut self,
                     for violation in violations {
                         match violation.kind {
                             // these are allowed
-                            UnsafetyViolationKind::MinConstFn
+                            UnsafetyViolationKind::GatedConstFnCall => {
                                 // if `#![feature(min_const_unsafe_fn)]` is active
-                                if self.tcx.sess.features_untracked().min_const_unsafe_fn => {},
-                            _ => {
+                                if !self.tcx.sess.features_untracked().min_const_unsafe_fn {
+                                    if !self.violations.contains(&violation) {
+                                        self.violations.push(violation.clone())
+                                    }
+                                }
+                            }
+                            // these unsafe things are stable in const fn
+                            UnsafetyViolationKind::GeneralAndConstFn => {},
+                            UnsafetyViolationKind::General |
+                            UnsafetyViolationKind::BorrowPacked(_) |
+                            UnsafetyViolationKind::ExternStatic(_) => {
                                 let mut violation = violation.clone();
-                                // overwrite unsafety violation in const fn with a hard error
-                                violation.kind = UnsafetyViolationKind::MinConstFn;
+                                // const fns don't need to be backwards compatible and can
+                                // emit these violations as a hard error instead of a backwards
+                                // compat lint
+                                violation.kind = UnsafetyViolationKind::General;
                                 if !self.violations.contains(&violation) {
                                     self.violations.push(violation)
                                 }
@@ -400,7 +421,7 @@ fn check_mut_borrowing_layout_constrained_field(
                                     source_info,
                                     description: Symbol::intern(description).as_interned_str(),
                                     details: Symbol::intern(details).as_interned_str(),
-                                    kind: UnsafetyViolationKind::MinConstFn,
+                                    kind: UnsafetyViolationKind::GeneralAndConstFn,
                                 }], &[]);
                             }
                         },
@@ -592,6 +613,16 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
     } in violations.iter() {
         // Report an error.
         match kind {
+            UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
+                tcx.sess.struct_span_err(
+                    source_info.span,
+                    &format!("{} is unsafe and unsafe operations \
+                            are not allowed in const fn", description))
+                    .span_label(source_info.span, &description.as_str()[..])
+                    .note(&details.as_str()[..])
+                    .emit();
+            }
+            UnsafetyViolationKind::GeneralAndConstFn |
             UnsafetyViolationKind::General => {
                 struct_span_err!(
                     tcx.sess, source_info.span, E0133,
@@ -600,14 +631,15 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
                     .note(&details.as_str()[..])
                     .emit();
             }
-            UnsafetyViolationKind::MinConstFn => {
-                tcx.sess.struct_span_err(
+            UnsafetyViolationKind::GatedConstFnCall => {
+                emit_feature_err(
+                    &tcx.sess.parse_sess,
+                    "min_const_unsafe_fn",
                     source_info.span,
-                    &format!("{} is unsafe and unsafe operations \
-                            are not allowed in const fn", description))
-                    .span_label(source_info.span, &description.as_str()[..])
-                    .note(&details.as_str()[..])
-                    .emit();
+                    GateIssue::Language,
+                    "calls to `const unsafe fn` in const fns are unstable",
+                );
+
             }
             UnsafetyViolationKind::ExternStatic(lint_node_id) => {
                 tcx.lint_node_note(SAFE_EXTERN_STATICS,
index 7a84992e14b36c7b520173fcfffe8e15f5afe7d1..02a357551df307a7a13c34a91e1d7496531441bb 100644 (file)
@@ -18,13 +18,13 @@ const fn no_unsafe() { unsafe {} }
 
 // not ok
 const fn foo8() -> i32 {
-    unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
+    unsafe { foo4() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
 }
 const fn foo9() -> *const String {
-    unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
+    unsafe { foo5::<String>() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
 }
 const fn foo10() -> *const Vec<std::cell::Cell<u32>> {
-    unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
+    unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR calls to `const unsafe fn` in const fns
 }
 const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowed in const fn
 //~^ dereferencing raw pointers in constant functions
index 17cba8569c148f8d7cd9bfeedd288c951924fa42..0b8ff4717c128427049b44c7496549c8dc404c94 100644 (file)
@@ -14,29 +14,29 @@ LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
    |
    = help: add #![feature(const_fn_union)] to the crate attributes to enable
 
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
   --> $DIR/min_const_fn_unsafe.rs:21:14
    |
-LL |     unsafe { foo4() } //~ ERROR unsafe operations are not allowed in const fn
-   |              ^^^^^^ call to unsafe function
+LL |     unsafe { foo4() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
+   |              ^^^^^^
    |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
 
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
   --> $DIR/min_const_fn_unsafe.rs:24:14
    |
-LL |     unsafe { foo5::<String>() } //~ ERROR unsafe operations are not allowed in const fn
-   |              ^^^^^^^^^^^^^^^^ call to unsafe function
+LL |     unsafe { foo5::<String>() } //~ ERROR calls to `const unsafe fn` in const fns are unstable
+   |              ^^^^^^^^^^^^^^^^
    |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
 
-error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
+error[E0658]: calls to `const unsafe fn` in const fns are unstable (see issue #55607)
   --> $DIR/min_const_fn_unsafe.rs:27:14
    |
-LL |     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR not allowed in const fn
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
+LL |     unsafe { foo6::<Vec<std::cell::Cell<u32>>>() } //~ ERROR calls to `const unsafe fn` in const fns
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: consult the function's documentation for information on how to avoid undefined behavior
+   = help: add #![feature(min_const_unsafe_fn)] to the crate attributes to enable
 
 error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe.rs:29:51