Skip to content

Commit

Permalink
Make the THIR unsafeck use the thir_body query
Browse files Browse the repository at this point in the history
  • Loading branch information
LeSeulArtichaut committed May 22, 2021
1 parent 6f64eb1 commit 6dfdea9
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 54 deletions.
12 changes: 12 additions & 0 deletions compiler/rustc_mir_build/src/build/mod.rs
Expand Up @@ -46,6 +46,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> 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, _, _), .. }) => {
Expand Down
32 changes: 9 additions & 23 deletions 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;
Expand Down Expand Up @@ -328,26 +328,23 @@ 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<LocalDefId>) {
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)
} else {
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 {
Expand All @@ -362,28 +359,17 @@ pub fn check_unsafety<'tcx>(
visitor.visit_expr(&thir[expr]);
}

crate fn thir_check_unsafety_inner<'tcx>(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
) {
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))
}
}

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) })
}
3 changes: 2 additions & 1 deletion 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>;
Expand Down
Expand Up @@ -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
|
Expand All @@ -68,49 +76,41 @@ 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[E0658]: `transmute` is not allowed in constant functions
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: see issue #53605 <https://github.com/rust-lang/rust/issues/53605> for more information
= help: add `#![feature(const_fn_transmute)]` to the crate attributes to enable
= note: `transmute` is only allowed in constants and statics for now
= 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
--> $DIR/feature-gate-const_fn_transmute.rs:33:49
|
LL | const fn safe_transmute_fn_core_intrinsic() -> u32 { core::intrinsics::transmute(Foo(3)) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | const fn safe_transmute_fn_intrinsic() -> u32 { std::intrinsics::transmute(Foo(3)) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #53605 <https://github.com/rust-lang/rust/issues/53605> for more information
= 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
--> $DIR/feature-gate-const_fn_transmute.rs:37:54
|
LL | const fn safe_transmute_fn_intrinsic() -> u32 { std::intrinsics::transmute(Foo(3)) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ call to unsafe function
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[E0133]: call to unsafe function is unsafe and requires unsafe function or block
error[E0658]: `transmute` is not allowed in constant functions
--> $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
= note: see issue #53605 <https://github.com/rust-lang/rust/issues/53605> for more information
= help: add `#![feature(const_fn_transmute)]` to the crate attributes to enable
= note: `transmute` is only allowed in constants and statics for now

error: aborting due to 12 previous errors

Expand Down
16 changes: 8 additions & 8 deletions 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
|
Expand All @@ -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.
Expand Down

0 comments on commit 6dfdea9

Please sign in to comment.