]> git.lizzy.rs Git - rust.git/commitdiff
Intrinsic checks are just needed for `qualify_min_const_fn`
authorOliver Scherer <github35764891676564198441@oli-obk.de>
Sat, 1 Dec 2018 13:09:30 +0000 (14:09 +0100)
committerOliver Scherer <github35764891676564198441@oli-obk.de>
Tue, 4 Dec 2018 09:17:37 +0000 (10:17 +0100)
src/librustc/ty/constness.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/transform/check_unsafety.rs
src/librustc_mir/transform/qualify_min_const_fn.rs
src/test/ui/consts/min_const_fn/min_const_fn_unsafe.stderr
src/test/ui/consts/min_const_fn/min_const_fn_unsafe_feature_gate.stderr

index d86170b24f239ec886c302c4be7f9d0a45b1866b..bc06167399533cb2055ba69de2e51ebb05b13d3a 100644 (file)
@@ -5,7 +5,6 @@
 use syntax_pos::symbol::Symbol;
 use hir::map::blocks::FnLikeNode;
 use syntax::attr;
-use rustc_target::spec::abi;
 
 impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     /// Whether the `def_id` counts as const fn in your current crate, considering all active
@@ -40,18 +39,6 @@ pub fn is_unstable_const_fn(self, def_id: DefId) -> Option<Symbol> {
 
     /// Returns true if this function must conform to `min_const_fn`
     pub fn is_min_const_fn(self, def_id: DefId) -> bool {
-        // some intrinsics are waved through if called inside the
-        // standard library. Users never need to call them directly
-        if let abi::Abi::RustIntrinsic = self.fn_sig(def_id).abi() {
-            match &self.item_name(def_id).as_str()[..] {
-                | "size_of"
-                | "min_align_of"
-                | "needs_drop"
-                => return true,
-                _ => {},
-            }
-        }
-
         // Bail out if the signature doesn't contain `const`
         if !self.is_const_fn_raw(def_id) {
             return false;
@@ -60,7 +47,7 @@ pub fn is_min_const_fn(self, def_id: DefId) -> bool {
         if self.features().staged_api {
             // in order for a libstd function to be considered min_const_fn
             // it needs to be stable and have no `rustc_const_unstable` attribute
-            self.is_const_fn_raw(def_id) && match self.lookup_stability(def_id) {
+            match self.lookup_stability(def_id) {
                 // stable functions with unstable const fn aren't `min_const_fn`
                 Some(&attr::Stability { const_stability: Some(_), .. }) => false,
                 // unstable functions don't need to conform
index 1538c070f373a5e96948740ccdcf758e371abd21..90a204ce00d5384394c4fd668a81c3a4a871a3bb 100644 (file)
@@ -115,7 +115,7 @@ pub fn mir_build<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Mir<'t
                     // As specified in #55607, a `const unsafe fn` differs
                     // from an `unsafe fn` in that its body is still considered
                     // safe code by default.
-                    assert!(!implicit_argument.is_none());
+                    assert!(implicit_argument.is_none());
                     Safety::Safe
                 },
                 hir::Unsafety::Unsafe => Safety::FnUnsafe,
index b47f1957ab4c9505087f33ee1979a939998a1599..75f8045cfae99cad514b4b294527ce4dbcd136fc 100644 (file)
@@ -514,7 +514,7 @@ fn unsafety_check_result<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
 
     let param_env = tcx.param_env(def_id);
     let mut checker = UnsafetyChecker::new(
-        tcx.is_const_fn(def_id) && tcx.is_min_const_fn(def_id),
+        tcx.is_min_const_fn(def_id),
         mir, source_scope_local_data, tcx, param_env);
     checker.visit_mir(mir);
 
@@ -617,13 +617,19 @@ pub fn check_unsafety<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) {
         // Report an error.
         match kind {
             UnsafetyViolationKind::General if tcx.is_min_const_fn(def_id) => {
-                tcx.sess.struct_span_err(
+                let mut err = 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();
+                            are not allowed in const fn", description));
+                err.span_label(source_info.span, &description.as_str()[..])
+                    .note(&details.as_str()[..]);
+                if tcx.fn_sig(def_id).unsafety() == hir::Unsafety::Unsafe {
+                    err.note(
+                        "unsafe action within a `const unsafe fn` still require an `unsafe` \
+                        block in contrast to regular `unsafe fn`."
+                    );
+                }
+                err.emit();
             }
             UnsafetyViolationKind::GeneralAndConstFn |
             UnsafetyViolationKind::General => {
index 13e134ba8592850b437b5d440b9702e9e5dfbdbb..3c1b9dbd91fa80e60548fbe54ab1ddc9012659a5 100644 (file)
@@ -2,6 +2,7 @@
 use rustc::hir;
 use rustc::mir::*;
 use rustc::ty::{self, Predicate, TyCtxt};
+use rustc_target::spec::abi;
 use std::borrow::Cow;
 use syntax_pos::Span;
 
@@ -338,19 +339,40 @@ fn check_terminator(
         } => {
             let fn_ty = func.ty(mir, tcx);
             if let ty::FnDef(def_id, _) = fn_ty.sty {
-                if tcx.is_min_const_fn(def_id) {
-                    check_operand(tcx, mir, func, span)?;
 
-                    for arg in args {
-                        check_operand(tcx, mir, arg, span)?;
-                    }
-                    Ok(())
-                } else {
-                    Err((
+                // some intrinsics are waved through if called inside the
+                // standard library. Users never need to call them directly
+                match tcx.fn_sig(def_id).abi() {
+                    abi::Abi::RustIntrinsic => match &tcx.item_name(def_id).as_str()[..] {
+                        | "size_of"
+                        | "min_align_of"
+                        | "needs_drop"
+                        => {},
+                        _ => return Err((
+                            span,
+                            "can only call a curated list of intrinsics in `min_const_fn`".into(),
+                        )),
+                    },
+                    abi::Abi::Rust if tcx.is_min_const_fn(def_id) => {},
+                    abi::Abi::Rust => return Err((
                         span,
                         "can only call other `min_const_fn` within a `min_const_fn`".into(),
-                    ))
+                    )),
+                    abi => return Err((
+                        span,
+                        format!(
+                            "cannot call functions with `{}` abi in `min_const_fn`",
+                            abi,
+                        ).into(),
+                    )),
+                }
+
+                check_operand(tcx, mir, func, span)?;
+
+                for arg in args {
+                    check_operand(tcx, mir, arg, span)?;
                 }
+                Ok(())
             } else {
                 Err((span, "can only call other const fns within const fn".into()))
             }
index 8d885545cde563913b0ada2222a6e0a3dc617a09..922a7883b9f2d3b4e933c2a8ae9efdedbd910d7b 100644 (file)
@@ -45,6 +45,7 @@ LL | const unsafe fn deref_forbidden(x: *mut usize) -> usize { *x } //~ ERROR no
    |                                                           ^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: access to union field is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe.rs:38:5
@@ -53,6 +54,7 @@ LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
    |     ^^^^^^^^^^^^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: aborting due to 7 previous errors
 
index 4336db65813b3e95753803e623fe8705bf3ccb7f..20c75afbe638b81478c0cb9dfb3ab6b00e9fd363 100644 (file)
@@ -37,6 +37,7 @@ LL |     foo4() //~ ERROR not allowed in const fn
    |     ^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe_feature_gate.rs:42:5
@@ -45,6 +46,7 @@ LL |     foo5::<String>() //~ ERROR not allowed in const fn
    |     ^^^^^^^^^^^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: call to unsafe function is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe_feature_gate.rs:45:5
@@ -53,6 +55,7 @@ LL |     foo6::<Vec<std::cell::Cell<u32>>>() //~ ERROR not allowed in const fn
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
    |
    = note: consult the function's documentation for information on how to avoid undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe_feature_gate.rs:47:51
@@ -61,6 +64,7 @@ LL | const unsafe fn foo30_3(x: *mut usize) -> usize { *x } //~ ERROR not allowe
    |                                                   ^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe_feature_gate.rs:50:60
@@ -69,6 +73,7 @@ LL | const unsafe fn foo30_4(x: *mut usize) -> &'static usize { &*x } //~ ERROR
    |                                                            ^^^ dereference of raw pointer
    |
    = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: dereference of raw pointer is unsafe and unsafe operations are not allowed in const fn
   --> $DIR/min_const_fn_unsafe_feature_gate.rs:53:62
@@ -85,6 +90,7 @@ LL |     Foo { x: () }.y //~ ERROR not allowed in const fn
    |     ^^^^^^^^^^^^^^^ access to union field
    |
    = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior
+   = note: unsafe action within a `const unsafe fn` still require an `unsafe` block in contrast to regular `unsafe fn`.
 
 error: aborting due to 11 previous errors