From d7787bbaeffefc4c89910b1aac2cd370c2c27955 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 14 May 2021 23:52:34 +0200 Subject: [PATCH] Check for calls to functions with `#[target_feature]` in THIR unsafeck --- .../rustc_mir_build/src/check_unsafety.rs | 31 ++++++- .../rfc-2396-target_feature-11/check-pass.rs | 2 + .../closures-inherit-target_feature.rs | 2 + .../{fn-ptr.stderr => fn-ptr.mir.stderr} | 2 +- .../rfcs/rfc-2396-target_feature-11/fn-ptr.rs | 2 + .../fn-ptr.thir.stderr | 18 ++++ ...afe-calls.stderr => safe-calls.mir.stderr} | 20 ++--- .../rfc-2396-target_feature-11/safe-calls.rs | 2 + .../safe-calls.thir.stderr | 83 +++++++++++++++++++ 9 files changed, 147 insertions(+), 15 deletions(-) rename src/test/ui/rfcs/rfc-2396-target_feature-11/{fn-ptr.stderr => fn-ptr.mir.stderr} (95%) create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr rename src/test/ui/rfcs/rfc-2396-target_feature-11/{safe-calls.stderr => safe-calls.mir.stderr} (92%) create mode 100644 src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index c1866b9a43791..3c2d770390d93 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -7,6 +7,7 @@ use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_session::lint::Level; use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_span::symbol::Symbol; use rustc_span::Span; struct UnsafetyVisitor<'a, 'tcx> { @@ -19,6 +20,9 @@ struct UnsafetyVisitor<'a, 'tcx> { /// `unsafe` block, and whether it has been used. safety_context: SafetyContext, body_unsafety: BodyUnsafety, + /// The `#[target_feature]` attributes of the body. Used for checking + /// calls to functions with `#[target_feature]` (RFC 2396). + body_target_features: &'tcx Vec, } impl<'tcx> UnsafetyVisitor<'_, 'tcx> { @@ -148,6 +152,18 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { ExprKind::Call { fun, ty: _, args: _, from_hir_call: _, fn_span: _ } => { if self.thir[fun].ty.fn_sig(self.tcx).unsafety() == hir::Unsafety::Unsafe { self.requires_unsafe(expr.span, CallToUnsafeFunction); + } else if let &ty::FnDef(func_did, _) = self.thir[fun].ty.kind() { + // If the called function has target features the calling function hasn't, + // the call requires `unsafe`. + if !self + .tcx + .codegen_fn_attrs(func_did) + .target_features + .iter() + .all(|feature| self.body_target_features.contains(feature)) + { + self.requires_unsafe(expr.span, CallToFunctionWith); + } } } ExprKind::InlineAsm { .. } | ExprKind::LlvmInlineAsm { .. } => { @@ -217,7 +233,6 @@ enum UnsafeOpKind { MutationOfLayoutConstrainedField, #[allow(dead_code)] // FIXME BorrowOfLayoutConstrainedField, - #[allow(dead_code)] // FIXME CallToFunctionWith, } @@ -291,6 +306,7 @@ pub fn check_unsafety<'tcx>( tcx: TyCtxt<'tcx>, thir: &Thir<'tcx>, expr: ExprId, + def_id: LocalDefId, hir_id: hir::HirId, ) { let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| { @@ -300,10 +316,17 @@ pub fn check_unsafety<'tcx>( BodyUnsafety::Safe } }); + let body_target_features = &tcx.codegen_fn_attrs(def_id).target_features; let safety_context = if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe }; - let mut visitor = - UnsafetyVisitor { tcx, thir, safety_context, hir_context: hir_id, body_unsafety }; + let mut visitor = UnsafetyVisitor { + tcx, + thir, + safety_context, + hir_context: hir_id, + body_unsafety, + body_target_features, + }; visitor.visit_expr(&thir[expr]); } @@ -315,7 +338,7 @@ crate fn thir_check_unsafety_inner<'tcx>( 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, hir_id); + check_unsafety(tcx, &thir, expr, def.did, hir_id); } crate fn thir_check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) { diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs index 58a2c271ecfbc..e0842bfa4cde4 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/check-pass.rs @@ -8,6 +8,8 @@ // check-pass // only-x86_64 +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck #![feature(target_feature_11)] diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs index af35bc2014bfe..a59d7c2d784c7 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/closures-inherit-target_feature.rs @@ -1,6 +1,8 @@ // Tests #73631: closures inherit `#[target_feature]` annotations // check-pass +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck // only-x86_64 #![feature(target_feature_11)] diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr similarity index 95% rename from src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr rename to src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr index 06cfdde3fb974..cf5815df56e1c 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.stderr +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.mir.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/fn-ptr.rs:9:21 + --> $DIR/fn-ptr.rs:11:21 | LL | #[target_feature(enable = "sse2")] | ---------------------------------- `#[target_feature]` added here diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs index 3ecea5c531390..c95d4a08e48bb 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.rs @@ -1,3 +1,5 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck // only-x86_64 #![feature(target_feature_11)] diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr new file mode 100644 index 0000000000000..cf5815df56e1c --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-ptr.thir.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/fn-ptr.rs:11:21 + | +LL | #[target_feature(enable = "sse2")] + | ---------------------------------- `#[target_feature]` added here +... +LL | let foo: fn() = foo; + | ---- ^^^ cannot coerce functions with `#[target_feature]` to safe function pointers + | | + | expected due to this + | + = note: expected fn pointer `fn()` + found fn item `fn() {foo}` + = note: functions with `#[target_feature]` can only be coerced to `unsafe` function pointers + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr similarity index 92% rename from src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr rename to src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr index b9f748640b558..79273a1dcbf88 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.stderr +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.mir.stderr @@ -1,5 +1,5 @@ error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:21:5 + --> $DIR/safe-calls.rs:23:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -7,7 +7,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:22:5 + --> $DIR/safe-calls.rs:24:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -15,7 +15,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:23:5 + --> $DIR/safe-calls.rs:25:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -23,7 +23,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:28:5 + --> $DIR/safe-calls.rs:30:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -31,7 +31,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:29:5 + --> $DIR/safe-calls.rs:31:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -39,7 +39,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:34:5 + --> $DIR/safe-calls.rs:36:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -47,7 +47,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:35:5 + --> $DIR/safe-calls.rs:37:5 | LL | avx_bmi2(); | ^^^^^^^^^^ call to function with `#[target_feature]` @@ -55,7 +55,7 @@ LL | avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:36:5 + --> $DIR/safe-calls.rs:38:5 | LL | Quux.avx_bmi2(); | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` @@ -63,7 +63,7 @@ LL | Quux.avx_bmi2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:42:5 + --> $DIR/safe-calls.rs:44:5 | LL | sse2(); | ^^^^^^ call to function with `#[target_feature]` @@ -71,7 +71,7 @@ LL | sse2(); = note: can only be called if the required target features are available error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block - --> $DIR/safe-calls.rs:45:18 + --> $DIR/safe-calls.rs:47:18 | LL | const name: () = sse2(); | ^^^^^^ call to function with `#[target_feature]` diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs index 8da3affc4477b..de0b89f46ba3f 100644 --- a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.rs @@ -1,3 +1,5 @@ +// revisions: mir thir +// [thir]compile-flags: -Z thir-unsafeck // only-x86_64 #![feature(target_feature_11)] diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr new file mode 100644 index 0000000000000..79273a1dcbf88 --- /dev/null +++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/safe-calls.thir.stderr @@ -0,0 +1,83 @@ +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:23:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:24:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:25:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:30:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:31:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:36:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:37:5 + | +LL | avx_bmi2(); + | ^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:38:5 + | +LL | Quux.avx_bmi2(); + | ^^^^^^^^^^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:44:5 + | +LL | sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error[E0133]: call to function with `#[target_feature]` is unsafe and requires unsafe function or block + --> $DIR/safe-calls.rs:47:18 + | +LL | const name: () = sse2(); + | ^^^^^^ call to function with `#[target_feature]` + | + = note: can only be called if the required target features are available + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0133`.