Intrinsic checks are just needed for qualify_min_const_fn
This commit is contained in:
parent
b77969466c
commit
f4115765c5
6 changed files with 53 additions and 30 deletions
|
|
@ -5,7 +5,6 @@ use ty::TyCtxt;
|
|||
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 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
|||
|
||||
/// 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 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
|
|||
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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 => {
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ use rustc::hir::def_id::DefId;
|
|||
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()))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue