Skip to content

Commit 3a9560a

Browse files
committed
Point to enclosing block/fn on nested unsafe
When declaring nested unsafe blocks (`unsafe {unsafe {}}`) that trigger the "unnecessary `unsafe` block" error, point out the enclosing `unsafe block` or `unsafe fn` that makes it unnecessary.
1 parent b1e3176 commit 3a9560a

File tree

3 files changed

+144
-1
lines changed

3 files changed

+144
-1
lines changed

src/librustc_lint/unused.rs

+28-1
Original file line numberDiff line numberDiff line change
@@ -189,11 +189,38 @@ impl LintPass for UnusedUnsafe {
189189

190190
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedUnsafe {
191191
fn check_expr(&mut self, cx: &LateContext, e: &hir::Expr) {
192+
/// Return the NodeId for an enclosing scope that is also `unsafe`
193+
fn is_enclosed(cx: &LateContext, id: ast::NodeId) -> Option<(String, ast::NodeId)> {
194+
let parent_id = cx.tcx.hir.get_parent_node(id);
195+
if parent_id != id {
196+
if cx.tcx.used_unsafe.borrow().contains(&parent_id) {
197+
Some(("block".to_string(), parent_id))
198+
} else if let Some(hir::map::NodeItem(&hir::Item {
199+
node: hir::ItemFn(_, hir::Unsafety::Unsafe, _, _, _, _),
200+
..
201+
})) = cx.tcx.hir.find(parent_id) {
202+
Some(("fn".to_string(), parent_id))
203+
} else {
204+
is_enclosed(cx, parent_id)
205+
}
206+
} else {
207+
None
208+
}
209+
}
192210
if let hir::ExprBlock(ref blk) = e.node {
193211
// Don't warn about generated blocks, that'll just pollute the output.
194212
if blk.rules == hir::UnsafeBlock(hir::UserProvided) &&
195213
!cx.tcx.used_unsafe.borrow().contains(&blk.id) {
196-
cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
214+
215+
let mut db = cx.struct_span_lint(UNUSED_UNSAFE, blk.span,
216+
"unnecessary `unsafe` block");
217+
218+
db.span_label(blk.span, &"unnecessary `unsafe` block");
219+
if let Some((kind, id)) = is_enclosed(cx, blk.id) {
220+
db.span_note(cx.tcx.hir.span(id),
221+
&format!("because it's nested under this `unsafe` {}", kind));
222+
}
223+
db.emit();
197224
}
198225
}
199226
}
+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
error: unnecessary `unsafe` block
2+
--> $DIR/lint-unused-unsafe.rs:26:13
3+
|
4+
26 | fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
5+
| ^^^^^^^^^ unnecessary `unsafe` block
6+
|
7+
note: lint level defined here
8+
--> $DIR/lint-unused-unsafe.rs:14:9
9+
|
10+
14 | #![deny(unused_unsafe)]
11+
| ^^^^^^^^^^^^^
12+
13+
error: unnecessary `unsafe` block
14+
--> $DIR/lint-unused-unsafe.rs:27:13
15+
|
16+
27 | fn bad2() { unsafe { bad1() } } //~ ERROR: unnecessary `unsafe` block
17+
| ^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
18+
19+
error: unnecessary `unsafe` block
20+
--> $DIR/lint-unused-unsafe.rs:28:20
21+
|
22+
28 | unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
23+
| ^^^^^^^^^ unnecessary `unsafe` block
24+
|
25+
note: because it's nested under this `unsafe` fn
26+
--> $DIR/lint-unused-unsafe.rs:28:1
27+
|
28+
28 | unsafe fn bad3() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
31+
error: unnecessary `unsafe` block
32+
--> $DIR/lint-unused-unsafe.rs:29:13
33+
|
34+
29 | fn bad4() { unsafe { callback(||{}) } } //~ ERROR: unnecessary `unsafe` block
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
36+
37+
error: unnecessary `unsafe` block
38+
--> $DIR/lint-unused-unsafe.rs:30:20
39+
|
40+
30 | unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block
41+
| ^^^^^^^^^^^^^^^^^ unnecessary `unsafe` block
42+
|
43+
note: because it's nested under this `unsafe` fn
44+
--> $DIR/lint-unused-unsafe.rs:30:1
45+
|
46+
30 | unsafe fn bad5() { unsafe { unsf() } } //~ ERROR: unnecessary `unsafe` block
47+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
48+
49+
error: unnecessary `unsafe` block
50+
--> $DIR/lint-unused-unsafe.rs:33:9
51+
|
52+
33 | unsafe { //~ ERROR: unnecessary `unsafe` block
53+
| _________^ starting here...
54+
34 | | unsf()
55+
35 | | }
56+
| |_________^ ...ending here: unnecessary `unsafe` block
57+
|
58+
note: because it's nested under this `unsafe` block
59+
--> $DIR/lint-unused-unsafe.rs:32:5
60+
|
61+
32 | unsafe { // don't put the warning here
62+
| _____^ starting here...
63+
33 | | unsafe { //~ ERROR: unnecessary `unsafe` block
64+
34 | | unsf()
65+
35 | | }
66+
36 | | }
67+
| |_____^ ...ending here
68+
69+
error: unnecessary `unsafe` block
70+
--> $DIR/lint-unused-unsafe.rs:39:5
71+
|
72+
39 | unsafe { //~ ERROR: unnecessary `unsafe` block
73+
| _____^ starting here...
74+
40 | | unsafe { //~ ERROR: unnecessary `unsafe` block
75+
41 | | unsf()
76+
42 | | }
77+
43 | | }
78+
| |_____^ ...ending here: unnecessary `unsafe` block
79+
|
80+
note: because it's nested under this `unsafe` fn
81+
--> $DIR/lint-unused-unsafe.rs:38:1
82+
|
83+
38 | unsafe fn bad7() {
84+
| _^ starting here...
85+
39 | | unsafe { //~ ERROR: unnecessary `unsafe` block
86+
40 | | unsafe { //~ ERROR: unnecessary `unsafe` block
87+
41 | | unsf()
88+
42 | | }
89+
43 | | }
90+
44 | | }
91+
| |_^ ...ending here
92+
93+
error: unnecessary `unsafe` block
94+
--> $DIR/lint-unused-unsafe.rs:40:9
95+
|
96+
40 | unsafe { //~ ERROR: unnecessary `unsafe` block
97+
| _________^ starting here...
98+
41 | | unsf()
99+
42 | | }
100+
| |_________^ ...ending here: unnecessary `unsafe` block
101+
|
102+
note: because it's nested under this `unsafe` fn
103+
--> $DIR/lint-unused-unsafe.rs:38:1
104+
|
105+
38 | unsafe fn bad7() {
106+
| _^ starting here...
107+
39 | | unsafe { //~ ERROR: unnecessary `unsafe` block
108+
40 | | unsafe { //~ ERROR: unnecessary `unsafe` block
109+
41 | | unsf()
110+
42 | | }
111+
43 | | }
112+
44 | | }
113+
| |_^ ...ending here
114+
115+
error: aborting due to 8 previous errors
116+

0 commit comments

Comments
 (0)