diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 153a1f6de5d..b5d26e81a51 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -46,6 +46,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ let body_owner_kind = tcx.hir().body_owner_kind(id); let typeck_results = tcx.typeck_opt_const_arg(def); + if tcx.sess.opts.debugging_opts.thir_unsafeck { + // Ensure unsafeck is ran before we steal the THIR. + match def { + ty::WithOptConstParam { did, const_param_did: Some(const_param_did) } => { + tcx.ensure().thir_check_unsafety_for_const_arg((did, const_param_did)) + } + ty::WithOptConstParam { did, const_param_did: None } => { + tcx.ensure().thir_check_unsafety(did) + } + } + } + // Figure out what primary body this item has. let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) { Node::Expr(hir::Expr { kind: hir::ExprKind::Closure(_, decl, body_id, _, _), .. }) => { diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index aa8193dab5d..d0d376bd3e3 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1,8 +1,8 @@ use crate::thir::visit::{self, Visitor}; -use crate::thir::*; use rustc_errors::struct_span_err; use rustc_hir as hir; +use rustc_middle::thir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; @@ -328,13 +328,10 @@ impl UnsafeOpKind { // FIXME: checking unsafety for closures should be handled by their parent body, // as they inherit their "safety context" from their declaration site. -pub fn check_unsafety<'tcx>( - tcx: TyCtxt<'tcx>, - thir: &Thir<'tcx>, - expr: ExprId, - def_id: LocalDefId, - hir_id: hir::HirId, -) { +pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam) { + let (thir, expr) = tcx.thir_body(def); + let thir = &thir.borrow(); + let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| { if fn_sig.header.unsafety == hir::Unsafety::Unsafe { BodyUnsafety::Unsafe(fn_sig.span) @@ -342,12 +339,12 @@ pub fn check_unsafety<'tcx>( BodyUnsafety::Safe } }); - let body_target_features = &tcx.codegen_fn_attrs(def_id).target_features; + let body_target_features = &tcx.codegen_fn_attrs(def.did).target_features; let safety_context = if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe }; let is_const = match tcx.hir().body_owner_kind(hir_id) { hir::BodyOwnerKind::Closure => false, - hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def_id.to_def_id()), + hir::BodyOwnerKind::Fn => tcx.is_const_fn_raw(def.did.to_def_id()), hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => true, }; let mut visitor = UnsafetyVisitor { @@ -362,22 +359,11 @@ pub fn check_unsafety<'tcx>( visitor.visit_expr(&thir[expr]); } -crate fn thir_check_unsafety_inner<'tcx>( - tcx: TyCtxt<'tcx>, - def: ty::WithOptConstParam, -) { - let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); - let body_id = tcx.hir().body_owned_by(hir_id); - let body = tcx.hir().body(body_id); - let (thir, expr) = cx::build_thir(tcx, def, &body.value); - check_unsafety(tcx, &thir, expr, def.did, hir_id); -} - crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) { tcx.thir_check_unsafety_for_const_arg(def) } else { - thir_check_unsafety_inner(tcx, ty::WithOptConstParam::unknown(def_id)) + check_unsafety(tcx, ty::WithOptConstParam::unknown(def_id)) } } @@ -385,5 +371,5 @@ crate fn thir_check_unsafety_for_const_arg<'tcx>( tcx: TyCtxt<'tcx>, (did, param_did): (LocalDefId, DefId), ) { - thir_check_unsafety_inner(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) }) + check_unsafety(tcx, ty::WithOptConstParam { did, const_param_did: Some(param_did) }) } diff --git a/compiler/rustc_mir_build/src/thir/visit.rs b/compiler/rustc_mir_build/src/thir/visit.rs index 671d1fe9b03..1a60b1de7fd 100644 --- a/compiler/rustc_mir_build/src/thir/visit.rs +++ b/compiler/rustc_mir_build/src/thir/visit.rs @@ -1,4 +1,5 @@ -use crate::thir::*; +use rustc_middle::thir::*; +use rustc_middle::ty::Const; pub trait Visitor<'a, 'tcx: 'a>: Sized { fn thir(&self) -> &'a Thir<'tcx>; diff --git a/src/test/ui/feature-gates/feature-gate-const_fn_transmute.thir.stderr b/src/test/ui/feature-gates/feature-gate-const_fn_transmute.thir.stderr index 04efea0b230..df0de7a9590 100644 --- a/src/test/ui/feature-gates/feature-gate-const_fn_transmute.thir.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_fn_transmute.thir.stderr @@ -58,6 +58,14 @@ LL | const unsafe fn unsafe_transmute_fn_core_intrinsic() -> u32 { core::intrins = help: add `#![feature(const_fn_transmute)]` to the crate attributes to enable = note: `transmute` is only allowed in constants and statics for now +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/feature-gate-const_fn_transmute.rs:29:39 + | +LL | const fn safe_transmute_fn() -> u32 { mem::transmute(Foo(3)) } + | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + error[E0658]: `transmute` is not allowed in constant functions --> $DIR/feature-gate-const_fn_transmute.rs:29:39 | @@ -68,6 +76,14 @@ LL | const fn safe_transmute_fn() -> u32 { mem::transmute(Foo(3)) } = help: add `#![feature(const_fn_transmute)]` to the crate attributes to enable = note: `transmute` is only allowed in constants and statics for now +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/feature-gate-const_fn_transmute.rs:33:49 + | +LL | const fn safe_transmute_fn_intrinsic() -> u32 { std::intrinsics::transmute(Foo(3)) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + error[E0658]: `transmute` is not allowed in constant functions --> $DIR/feature-gate-const_fn_transmute.rs:33:49 | @@ -78,6 +94,14 @@ LL | const fn safe_transmute_fn_intrinsic() -> u32 { std::intrinsics::transmute( = help: add `#![feature(const_fn_transmute)]` to the crate attributes to enable = note: `transmute` is only allowed in constants and statics for now +error[E0133]: call to unsafe function is unsafe and requires unsafe function or block + --> $DIR/feature-gate-const_fn_transmute.rs:37:54 + | +LL | const fn safe_transmute_fn_core_intrinsic() -> u32 { core::intrinsics::transmute(Foo(3)) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function + | + = note: consult the function's documentation for information on how to avoid undefined behavior + error[E0658]: `transmute` is not allowed in constant functions --> $DIR/feature-gate-const_fn_transmute.rs:37:54 | @@ -88,30 +112,6 @@ LL | const fn safe_transmute_fn_core_intrinsic() -> u32 { core::intrinsics::tran = help: add `#![feature(const_fn_transmute)]` to the crate attributes to enable = note: `transmute` is only allowed in constants and statics for now -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/feature-gate-const_fn_transmute.rs:29:39 - | -LL | const fn safe_transmute_fn() -> u32 { mem::transmute(Foo(3)) } - | ^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/feature-gate-const_fn_transmute.rs:33:49 - | -LL | const fn safe_transmute_fn_intrinsic() -> u32 { std::intrinsics::transmute(Foo(3)) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - -error[E0133]: call to unsafe function is unsafe and requires unsafe function or block - --> $DIR/feature-gate-const_fn_transmute.rs:37:54 - | -LL | const fn safe_transmute_fn_core_intrinsic() -> u32 { core::intrinsics::transmute(Foo(3)) } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function - | - = note: consult the function's documentation for information on how to avoid undefined behavior - error: aborting due to 12 previous errors Some errors have detailed explanations: E0133, E0658. diff --git a/src/test/ui/issues/issue-16538.thir.stderr b/src/test/ui/issues/issue-16538.thir.stderr index d7e8c08bb01..435334c3228 100644 --- a/src/test/ui/issues/issue-16538.thir.stderr +++ b/src/test/ui/issues/issue-16538.thir.stderr @@ -1,3 +1,11 @@ +error[E0133]: use of extern static is unsafe and requires unsafe function or block + --> $DIR/issue-16538.rs:14:34 + | +LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X); + | ^^^^ use of extern static + | + = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior + error[E0015]: calls in statics are limited to constant functions, tuple structs and tuple variants --> $DIR/issue-16538.rs:14:27 | @@ -13,14 +21,6 @@ LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X); = help: the trait `Sync` is not implemented for `*const usize` = note: shared static variables must have a type that implements `Sync` -error[E0133]: use of extern static is unsafe and requires unsafe function or block - --> $DIR/issue-16538.rs:14:34 - | -LL | static foo: *const Y::X = Y::foo(Y::x as *const Y::X); - | ^^^^ use of extern static - | - = note: extern statics are not controlled by the Rust type system: invalid data, aliasing violations or data races will cause undefined behavior - error: aborting due to 3 previous errors Some errors have detailed explanations: E0015, E0133, E0277.