Skip to content

Commit f58631b

Browse files
committed
Auto merge of #85607 - LeSeulArtichaut:thir-unsafeck-closures, r=nikomatsakis
Make closures inherit their parent's "safety context" Fixes rust-lang/project-thir-unsafeck#9, ~~blocked on #85273~~. r? `@nikomatsakis`
2 parents 0e44ca6 + d1f0e9f commit f58631b

18 files changed

+173
-17
lines changed

compiler/rustc_mir_build/src/check_unsafety.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,30 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
213213
self.requires_unsafe(expr.span, CastOfPointerToInt);
214214
}
215215
}
216+
ExprKind::Closure {
217+
closure_id,
218+
substs: _,
219+
upvars: _,
220+
movability: _,
221+
fake_reads: _,
222+
} => {
223+
let closure_id = closure_id.expect_local();
224+
let closure_def = if let Some((did, const_param_id)) =
225+
ty::WithOptConstParam::try_lookup(closure_id, self.tcx)
226+
{
227+
ty::WithOptConstParam { did, const_param_did: Some(const_param_id) }
228+
} else {
229+
ty::WithOptConstParam::unknown(closure_id)
230+
};
231+
let (closure_thir, expr) = self.tcx.thir_body(closure_def);
232+
let closure_thir = &closure_thir.borrow();
233+
let hir_context = self.tcx.hir().local_def_id_to_hir_id(closure_id);
234+
let mut closure_visitor =
235+
UnsafetyVisitor { thir: closure_thir, hir_context, ..*self };
236+
closure_visitor.visit_expr(&closure_thir[expr]);
237+
// Unsafe blocks can be used in closures, make sure to take it into account
238+
self.safety_context = closure_visitor.safety_context;
239+
}
216240
_ => {}
217241
}
218242

@@ -335,14 +359,18 @@ impl UnsafeOpKind {
335359
}
336360
}
337361

338-
// FIXME: checking unsafety for closures should be handled by their parent body,
339-
// as they inherit their "safety context" from their declaration site.
340362
pub fn check_unsafety<'tcx>(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) {
341363
// THIR unsafeck is gated under `-Z thir-unsafeck`
342364
if !tcx.sess.opts.debugging_opts.thir_unsafeck {
343365
return;
344366
}
345367

368+
// Closures are handled by their parent function
369+
if tcx.is_closure(def.did.to_def_id()) {
370+
tcx.ensure().thir_check_unsafety(tcx.hir().local_def_id_to_hir_id(def.did).owner);
371+
return;
372+
}
373+
346374
let (thir, expr) = tcx.thir_body(def);
347375
let thir = &thir.borrow();
348376
// If `thir` is empty, a type error occured, skip this body.

src/test/ui/async-await/async-await.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
// run-pass
22

3-
// revisions: default nomiropt
3+
// revisions: default nomiropt thirunsafeck
44
//[nomiropt]compile-flags: -Z mir-opt-level=0
5+
//[thirunsafeck]compile-flags: -Zthir-unsafeck
56

67
#![allow(unused)]
78

src/test/ui/command/command-pre-exec.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// run-pass
2+
// revisions: mir thir
3+
// [thir]compile-flags: -Zthir-unsafeck
24

35
#![allow(stable_features)]
46
// ignore-windows - this is a unix-specific test

src/test/ui/generator/static-mut-reference-across-yield.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// build-pass
2+
// revisions: mir thir
3+
// [thir]compile-flags: -Zthir-unsafeck
4+
25
#![feature(generators)]
36

47
static mut A: [i32; 5] = [1, 2, 3, 4, 5];

src/test/ui/intrinsics/panic-uninitialized-zeroed.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// run-pass
22
// ignore-wasm32-bare compiled with panic=abort by default
3+
// revisions: mir thir
4+
// [thir]compile-flags: -Zthir-unsafeck
35

46
// This test checks panic emitted from `mem::{uninitialized,zeroed}`.
57

src/test/ui/issues/issue-11740.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// check-pass
2+
// revisions: mir thir
3+
// [thir]compile-flags: -Zthir-unsafeck
24

35
struct Attr {
46
name: String,

src/test/ui/issues/issue-39367.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
// run-pass
2+
// revisions: mir thir
3+
// [thir]compile-flags: -Zthir-unsafeck
4+
25
use std::ops::Deref;
36

47
struct ArenaSet<U: Deref, V=<U as Deref>::Target>(U, &'static V)

src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.stderr src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.mir.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unnecessary `unsafe` block
2-
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:7:13
2+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
33
|
44
LL | unsafe {
55
| ------ because it's nested under this `unsafe` block
@@ -8,13 +8,13 @@ LL | unsafe {
88
| ^^^^^^ unnecessary `unsafe` block
99
|
1010
note: the lint level is defined here
11-
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:1:8
11+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
1212
|
1313
LL | #[deny(unused_unsafe)]
1414
| ^^^^^^^^^^^^^
1515

1616
error: unnecessary `unsafe` block
17-
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:9:38
17+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
1818
|
1919
LL | unsafe {
2020
| ------ because it's nested under this `unsafe` block
@@ -23,7 +23,7 @@ LL | |w: &mut Vec<u32>| { unsafe {
2323
| ^^^^^^ unnecessary `unsafe` block
2424

2525
error: unnecessary `unsafe` block
26-
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:13:34
26+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
2727
|
2828
LL | unsafe {
2929
| ------ because it's nested under this `unsafe` block

src/test/ui/issues/issue-45107-unnecessary-unsafe-in-closure.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// revisions: mir thir
2+
// [thir]compile-flags: -Zthir-unsafeck
3+
14
#[deny(unused_unsafe)]
25
fn main() {
36
let mut v = Vec::<i32>::with_capacity(24);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
error: unnecessary `unsafe` block
2+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:10:13
3+
|
4+
LL | unsafe {
5+
| ------ because it's nested under this `unsafe` block
6+
LL | let f = |v: &mut Vec<_>| {
7+
LL | unsafe {
8+
| ^^^^^^ unnecessary `unsafe` block
9+
|
10+
note: the lint level is defined here
11+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:4:8
12+
|
13+
LL | #[deny(unused_unsafe)]
14+
| ^^^^^^^^^^^^^
15+
16+
error: unnecessary `unsafe` block
17+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:12:38
18+
|
19+
LL | unsafe {
20+
| ------ because it's nested under this `unsafe` block
21+
...
22+
LL | |w: &mut Vec<u32>| { unsafe {
23+
| ^^^^^^ unnecessary `unsafe` block
24+
25+
error: unnecessary `unsafe` block
26+
--> $DIR/issue-45107-unnecessary-unsafe-in-closure.rs:16:34
27+
|
28+
LL | unsafe {
29+
| ------ because it's nested under this `unsafe` block
30+
...
31+
LL | |x: &mut Vec<u32>| { unsafe {
32+
| ^^^^^^ unnecessary `unsafe` block
33+
34+
error: aborting due to 3 previous errors
35+

src/test/ui/lto-still-runs-thread-dtors.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// compile-flags: -C lto
33
// no-prefer-dynamic
44
// ignore-emscripten no threads support
5+
// revisions: mir thir
6+
// [thir]compile-flags: -Zthir-unsafeck
57

68
use std::thread;
79

src/test/ui/no-stdio.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
// ignore-android
33
// ignore-emscripten no processes
44
// ignore-sgx no processes
5+
// revisions: mir thir
6+
// [thir]compile-flags: -Zthir-unsafeck
57

68
#![feature(rustc_private)]
79

src/test/ui/running-with-no-runtime.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
// run-pass
22
// ignore-emscripten spawning processes is not supported
33
// ignore-sgx no processes
4+
// revisions: mir thir
5+
// [thir]compile-flags: -Zthir-unsafeck
46

57
#![feature(start)]
68

src/test/ui/simd/simd-intrinsic-generic-comparison.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
// run-pass
22
// ignore-emscripten FIXME(#45351) hits an LLVM assert
3+
// revisions: mir thir
4+
// [thir]compile-flags: -Zthir-unsafeck
35

46
#![feature(repr_simd, platform_intrinsics, concat_idents)]
57
#![allow(non_camel_case_types)]

src/test/ui/span/lint-unused-unsafe.stderr src/test/ui/span/lint-unused-unsafe.mir.stderr

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,61 +1,61 @@
11
error: unnecessary `unsafe` block
2-
--> $DIR/lint-unused-unsafe.rs:16:13
2+
--> $DIR/lint-unused-unsafe.rs:19:13
33
|
44
LL | fn bad1() { unsafe {} }
55
| ^^^^^^ unnecessary `unsafe` block
66
|
77
note: the lint level is defined here
8-
--> $DIR/lint-unused-unsafe.rs:4:9
8+
--> $DIR/lint-unused-unsafe.rs:7:9
99
|
1010
LL | #![deny(unused_unsafe)]
1111
| ^^^^^^^^^^^^^
1212

1313
error: unnecessary `unsafe` block
14-
--> $DIR/lint-unused-unsafe.rs:17:13
14+
--> $DIR/lint-unused-unsafe.rs:20:13
1515
|
1616
LL | fn bad2() { unsafe { bad1() } }
1717
| ^^^^^^ unnecessary `unsafe` block
1818

1919
error: unnecessary `unsafe` block
20-
--> $DIR/lint-unused-unsafe.rs:18:20
20+
--> $DIR/lint-unused-unsafe.rs:21:20
2121
|
2222
LL | unsafe fn bad3() { unsafe {} }
2323
| ---------------- ^^^^^^ unnecessary `unsafe` block
2424
| |
2525
| because it's nested under this `unsafe` fn
2626

2727
error: unnecessary `unsafe` block
28-
--> $DIR/lint-unused-unsafe.rs:19:13
28+
--> $DIR/lint-unused-unsafe.rs:22:13
2929
|
3030
LL | fn bad4() { unsafe { callback(||{}) } }
3131
| ^^^^^^ unnecessary `unsafe` block
3232

3333
error: unnecessary `unsafe` block
34-
--> $DIR/lint-unused-unsafe.rs:20:20
34+
--> $DIR/lint-unused-unsafe.rs:23:20
3535
|
3636
LL | unsafe fn bad5() { unsafe { unsf() } }
3737
| ---------------- ^^^^^^ unnecessary `unsafe` block
3838
| |
3939
| because it's nested under this `unsafe` fn
4040

4141
error: unnecessary `unsafe` block
42-
--> $DIR/lint-unused-unsafe.rs:23:9
42+
--> $DIR/lint-unused-unsafe.rs:26:9
4343
|
4444
LL | unsafe { // don't put the warning here
4545
| ------ because it's nested under this `unsafe` block
4646
LL | unsafe {
4747
| ^^^^^^ unnecessary `unsafe` block
4848

4949
error: unnecessary `unsafe` block
50-
--> $DIR/lint-unused-unsafe.rs:29:5
50+
--> $DIR/lint-unused-unsafe.rs:32:5
5151
|
5252
LL | unsafe fn bad7() {
5353
| ---------------- because it's nested under this `unsafe` fn
5454
LL | unsafe {
5555
| ^^^^^^ unnecessary `unsafe` block
5656

5757
error: unnecessary `unsafe` block
58-
--> $DIR/lint-unused-unsafe.rs:30:9
58+
--> $DIR/lint-unused-unsafe.rs:33:9
5959
|
6060
LL | unsafe fn bad7() {
6161
| ---------------- because it's nested under this `unsafe` fn

src/test/ui/span/lint-unused-unsafe.rs

+3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// Exercise the unused_unsafe attribute in some positive and negative cases
22

3+
// revisions: mir thir
4+
// [thir]compile-flags: -Zthir-unsafeck
5+
36
#![allow(dead_code)]
47
#![deny(unused_unsafe)]
58

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
error: unnecessary `unsafe` block
2+
--> $DIR/lint-unused-unsafe.rs:19:13
3+
|
4+
LL | fn bad1() { unsafe {} }
5+
| ^^^^^^ unnecessary `unsafe` block
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/lint-unused-unsafe.rs:7:9
9+
|
10+
LL | #![deny(unused_unsafe)]
11+
| ^^^^^^^^^^^^^
12+
13+
error: unnecessary `unsafe` block
14+
--> $DIR/lint-unused-unsafe.rs:20:13
15+
|
16+
LL | fn bad2() { unsafe { bad1() } }
17+
| ^^^^^^ unnecessary `unsafe` block
18+
19+
error: unnecessary `unsafe` block
20+
--> $DIR/lint-unused-unsafe.rs:21:20
21+
|
22+
LL | unsafe fn bad3() { unsafe {} }
23+
| ---------------- ^^^^^^ unnecessary `unsafe` block
24+
| |
25+
| because it's nested under this `unsafe` fn
26+
27+
error: unnecessary `unsafe` block
28+
--> $DIR/lint-unused-unsafe.rs:22:13
29+
|
30+
LL | fn bad4() { unsafe { callback(||{}) } }
31+
| ^^^^^^ unnecessary `unsafe` block
32+
33+
error: unnecessary `unsafe` block
34+
--> $DIR/lint-unused-unsafe.rs:23:20
35+
|
36+
LL | unsafe fn bad5() { unsafe { unsf() } }
37+
| ---------------- ^^^^^^ unnecessary `unsafe` block
38+
| |
39+
| because it's nested under this `unsafe` fn
40+
41+
error: unnecessary `unsafe` block
42+
--> $DIR/lint-unused-unsafe.rs:26:9
43+
|
44+
LL | unsafe { // don't put the warning here
45+
| ------ because it's nested under this `unsafe` block
46+
LL | unsafe {
47+
| ^^^^^^ unnecessary `unsafe` block
48+
49+
error: unnecessary `unsafe` block
50+
--> $DIR/lint-unused-unsafe.rs:33:9
51+
|
52+
LL | unsafe {
53+
| ------ because it's nested under this `unsafe` block
54+
LL | unsafe {
55+
| ^^^^^^ unnecessary `unsafe` block
56+
57+
error: unnecessary `unsafe` block
58+
--> $DIR/lint-unused-unsafe.rs:32:5
59+
|
60+
LL | unsafe fn bad7() {
61+
| ---------------- because it's nested under this `unsafe` fn
62+
LL | unsafe {
63+
| ^^^^^^ unnecessary `unsafe` block
64+
65+
error: aborting due to 8 previous errors
66+

src/tools/tidy/src/ui_tests.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::path::Path;
88
const ENTRY_LIMIT: usize = 1000;
99
// FIXME: The following limits should be reduced eventually.
1010
const ROOT_ENTRY_LIMIT: usize = 1371;
11-
const ISSUES_ENTRY_LIMIT: usize = 2558;
11+
const ISSUES_ENTRY_LIMIT: usize = 2559;
1212

1313
fn check_entries(path: &Path, bad: &mut bool) {
1414
let dirs = walkdir::WalkDir::new(&path.join("test/ui"))

0 commit comments

Comments
 (0)