diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 971b6dd9e1c8..d1aaabe92eda 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -213,6 +213,30 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { self.requires_unsafe(expr.span, CastOfPointerToInt); } } + ExprKind::Closure { + closure_id, + substs: _, + upvars: _, + movability: _, + fake_reads: _, + } => { + let closure_id = closure_id.expect_local(); + let closure_def = if let Some((did, const_param_id)) = + ty::WithOptConstParam::try_lookup(closure_id, self.tcx) + { + ty::WithOptConstParam { did, const_param_did: Some(const_param_id) } + } else { + ty::WithOptConstParam::unknown(closure_id) + }; + let (closure_thir, expr) = self.tcx.thir_body(closure_def); + let closure_thir = &closure_thir.borrow(); + let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id); + let mut closure_visitor = + UnsafetyVisitor { thir: closure_thir, hir_context, ..*self }; + closure_visitor.visit_expr(&closure_thir[expr]); + // Unsafe blocks can be used in closures, make sure to take it into account + self.safety_context = closure_visitor.safety_context; + } _ => {} } @@ -335,14 +359,18 @@ 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>, def: ty::WithOptConstParam) { // THIR unsafeck is gated under `-Z thir-unsafeck` if !tcx.sess.opts.debugging_opts.thir_unsafeck { return; } + // Closures are handled by their parent function + if tcx.is_closure(def.did.to_def_id()) { + tcx.ensure().thir_check_unsafety(tcx.hir().local_def_id_to_hir_id(def.did).owner); + return; + } + let (thir, expr) = tcx.thir_body(def); let thir = &thir.borrow(); // If `thir` is empty, a type error occured, skip this body. diff --git a/src/test/ui/async-await/async-await.rs b/src/test/ui/async-await/async-await.rs index 0207752afe09..3d22025bf286 100644 --- a/src/test/ui/async-await/async-await.rs +++ b/src/test/ui/async-await/async-await.rs @@ -1,7 +1,8 @@ // run-pass -// revisions: default nomiropt +// revisions: default nomiropt thirunsafeck //[nomiropt]compile-flags: -Z mir-opt-level=0 +//[thirunsafeck]compile-flags: -Zthir-unsafeck #![allow(unused)] diff --git a/src/test/ui/command/command-pre-exec.rs b/src/test/ui/command/command-pre-exec.rs index 819ed0b2ddef..61914e229307 100644 --- a/src/test/ui/command/command-pre-exec.rs +++ b/src/test/ui/command/command-pre-exec.rs @@ -1,4 +1,6 @@ // run-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![allow(stable_features)] // ignore-windows - this is a unix-specific test diff --git a/src/test/ui/generator/static-mut-reference-across-yield.rs b/src/test/ui/generator/static-mut-reference-across-yield.rs index 2926bba99780..0fa6d9cdc77b 100644 --- a/src/test/ui/generator/static-mut-reference-across-yield.rs +++ b/src/test/ui/generator/static-mut-reference-across-yield.rs @@ -1,4 +1,7 @@ // build-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + #![feature(generators)] static mut A: [i32; 5] = [1, 2, 3, 4, 5]; diff --git a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs index 4a91198ab9f6..72c0d7913e52 100644 --- a/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs +++ b/src/test/ui/intrinsics/panic-uninitialized-zeroed.rs @@ -1,5 +1,7 @@ // run-pass // ignore-wasm32-bare compiled with panic=abort by default +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck // This test checks panic emitted from `mem::{uninitialized,zeroed}`. diff --git a/src/test/ui/issues/issue-11740.rs b/src/test/ui/issues/issue-11740.rs index dc10a205f241..9faeb7770a75 100644 --- a/src/test/ui/issues/issue-11740.rs +++ b/src/test/ui/issues/issue-11740.rs @@ -1,4 +1,6 @@ // check-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck struct Attr { name: String, diff --git a/src/test/ui/issues/issue-39367.rs b/src/test/ui/issues/issue-39367.rs index 8314be3d14cc..e7beb8a0392e 100644 --- a/src/test/ui/issues/issue-39367.rs +++ b/src/test/ui/issues/issue-39367.rs @@ -1,4 +1,7 @@ // run-pass +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + use std::ops::Deref; struct ArenaSet::Target>(U, &'static V) diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr similarity index 78% rename from src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr rename to src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr index 321698e76369..9e9cbcf33ae1 100644 --- a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr +++ b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr @@ -1,5 +1,5 @@ error: unnecessary `unsafe` block - --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:7:13 + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13 | LL | unsafe { | ------ because it's nested under this `unsafe` block @@ -8,13 +8,13 @@ LL | unsafe { | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:1:8 + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8 | LL | #[deny(unused_unsafe)] | ^^^^^^^^^^^^^ error: unnecessary `unsafe` block - --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:9:38 + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38 | LL | unsafe { | ------ because it's nested under this `unsafe` block @@ -23,7 +23,7 @@ LL | |w: &mut Vec| { unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:13:34 + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34 | LL | unsafe { | ------ because it's nested under this `unsafe` block diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs index de275ff701a6..ac1cfd62a056 100644 --- a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs +++ b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs @@ -1,3 +1,6 @@ +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + #[deny(unused_unsafe)] fn main() { let mut v = Vec::::with_capacity(24); diff --git a/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr new file mode 100644 index 000000000000..9e9cbcf33ae1 --- /dev/null +++ b/src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.thir.stderr @@ -0,0 +1,35 @@ +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | let f = |v: &mut Vec<_>| { +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8 + | +LL | #[deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | |w: &mut Vec| { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +... +LL | |x: &mut Vec| { unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 3 previous errors + diff --git a/src/test/ui/lto-still-runs-thread-dtors.rs b/src/test/ui/lto-still-runs-thread-dtors.rs index 635ad783b315..1c7368b36e13 100644 --- a/src/test/ui/lto-still-runs-thread-dtors.rs +++ b/src/test/ui/lto-still-runs-thread-dtors.rs @@ -2,6 +2,8 @@ // compile-flags: -C lto // no-prefer-dynamic // ignore-emscripten no threads support +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck use std::thread; diff --git a/src/test/ui/no-stdio.rs b/src/test/ui/no-stdio.rs index 68e6fa838b4e..24985386a97a 100644 --- a/src/test/ui/no-stdio.rs +++ b/src/test/ui/no-stdio.rs @@ -2,6 +2,8 @@ // ignore-android // ignore-emscripten no processes // ignore-sgx no processes +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![feature(rustc_private)] diff --git a/src/test/ui/running-with-no-runtime.rs b/src/test/ui/running-with-no-runtime.rs index c321e86dc182..c575a6bec8e9 100644 --- a/src/test/ui/running-with-no-runtime.rs +++ b/src/test/ui/running-with-no-runtime.rs @@ -1,6 +1,8 @@ // run-pass // ignore-emscripten spawning processes is not supported // ignore-sgx no processes +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![feature(start)] diff --git a/src/test/ui/simd/simd-intrinsic-generic-comparison.rs b/src/test/ui/simd/simd-intrinsic-generic-comparison.rs index 103132c18ae2..da5c42a1a988 100644 --- a/src/test/ui/simd/simd-intrinsic-generic-comparison.rs +++ b/src/test/ui/simd/simd-intrinsic-generic-comparison.rs @@ -1,5 +1,7 @@ // run-pass // ignore-emscripten FIXME(#45351) hits an LLVM assert +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck #![feature(repr_simd, platform_intrinsics, concat_idents)] #![allow(non_camel_case_types)] diff --git a/src/test/ui/span/lint-unused-unsafe.stderr b/src/test/ui/span/lint-unused-unsafe.mir.stderr similarity index 83% rename from src/test/ui/span/lint-unused-unsafe.stderr rename to src/test/ui/span/lint-unused-unsafe.mir.stderr index c35a3349121b..c2adb7be7a22 100644 --- a/src/test/ui/span/lint-unused-unsafe.stderr +++ b/src/test/ui/span/lint-unused-unsafe.mir.stderr @@ -1,23 +1,23 @@ error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:16:13 + --> $DIR/lint-unused-unsafe.rs:19:13 | LL | fn bad1() { unsafe {} } | ^^^^^^ unnecessary `unsafe` block | note: the lint level is defined here - --> $DIR/lint-unused-unsafe.rs:4:9 + --> $DIR/lint-unused-unsafe.rs:7:9 | LL | #![deny(unused_unsafe)] | ^^^^^^^^^^^^^ error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:17:13 + --> $DIR/lint-unused-unsafe.rs:20:13 | LL | fn bad2() { unsafe { bad1() } } | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:18:20 + --> $DIR/lint-unused-unsafe.rs:21:20 | LL | unsafe fn bad3() { unsafe {} } | ---------------- ^^^^^^ unnecessary `unsafe` block @@ -25,13 +25,13 @@ LL | unsafe fn bad3() { unsafe {} } | because it's nested under this `unsafe` fn error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:19:13 + --> $DIR/lint-unused-unsafe.rs:22:13 | LL | fn bad4() { unsafe { callback(||{}) } } | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:20:20 + --> $DIR/lint-unused-unsafe.rs:23:20 | LL | unsafe fn bad5() { unsafe { unsf() } } | ---------------- ^^^^^^ unnecessary `unsafe` block @@ -39,7 +39,7 @@ LL | unsafe fn bad5() { unsafe { unsf() } } | because it's nested under this `unsafe` fn error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:23:9 + --> $DIR/lint-unused-unsafe.rs:26:9 | LL | unsafe { // don't put the warning here | ------ because it's nested under this `unsafe` block @@ -47,7 +47,7 @@ LL | unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:29:5 + --> $DIR/lint-unused-unsafe.rs:32:5 | LL | unsafe fn bad7() { | ---------------- because it's nested under this `unsafe` fn @@ -55,7 +55,7 @@ LL | unsafe { | ^^^^^^ unnecessary `unsafe` block error: unnecessary `unsafe` block - --> $DIR/lint-unused-unsafe.rs:30:9 + --> $DIR/lint-unused-unsafe.rs:33:9 | LL | unsafe fn bad7() { | ---------------- because it's nested under this `unsafe` fn diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs index b6c4894d9180..b889cc981cad 100644 --- a/src/test/ui/span/lint-unused-unsafe.rs +++ b/src/test/ui/span/lint-unused-unsafe.rs @@ -1,5 +1,8 @@ // Exercise the unused_unsafe attribute in some positive and negative cases +// revisions: mir thir +// [thir]compile-flags: -Zthir-unsafeck + #![allow(dead_code)] #![deny(unused_unsafe)] diff --git a/src/test/ui/span/lint-unused-unsafe.thir.stderr b/src/test/ui/span/lint-unused-unsafe.thir.stderr new file mode 100644 index 000000000000..dda45c3679ab --- /dev/null +++ b/src/test/ui/span/lint-unused-unsafe.thir.stderr @@ -0,0 +1,66 @@ +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:19:13 + | +LL | fn bad1() { unsafe {} } + | ^^^^^^ unnecessary `unsafe` block + | +note: the lint level is defined here + --> $DIR/lint-unused-unsafe.rs:7:9 + | +LL | #![deny(unused_unsafe)] + | ^^^^^^^^^^^^^ + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:20:13 + | +LL | fn bad2() { unsafe { bad1() } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:21:20 + | +LL | unsafe fn bad3() { unsafe {} } + | ---------------- ^^^^^^ unnecessary `unsafe` block + | | + | because it's nested under this `unsafe` fn + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:22:13 + | +LL | fn bad4() { unsafe { callback(||{}) } } + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:23:20 + | +LL | unsafe fn bad5() { unsafe { unsf() } } + | ---------------- ^^^^^^ unnecessary `unsafe` block + | | + | because it's nested under this `unsafe` fn + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:26:9 + | +LL | unsafe { // don't put the warning here + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:33:9 + | +LL | unsafe { + | ------ because it's nested under this `unsafe` block +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: unnecessary `unsafe` block + --> $DIR/lint-unused-unsafe.rs:32:5 + | +LL | unsafe fn bad7() { + | ---------------- because it's nested under this `unsafe` fn +LL | unsafe { + | ^^^^^^ unnecessary `unsafe` block + +error: aborting due to 8 previous errors + diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 3f9838844600..f61295c88308 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -8,7 +8,7 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. const ROOT_ENTRY_LIMIT: usize = 1371; -const ISSUES_ENTRY_LIMIT: usize = 2558; +const ISSUES_ENTRY_LIMIT: usize = 2559; fn check_entries(path: &Path, bad: &mut bool) { let dirs = walkdir::WalkDir::new(&path.join("test/ui"))