Skip to content

Commit 851c929

Browse files
committed
Make THIR unused_unsafe lint consistent with MIR
Updates THIR behavior to match the changes from rust-lang#93678
1 parent 39275c1 commit 851c929

13 files changed

+1683
-395
lines changed

compiler/rustc_mir_build/messages.ftl

-1
Original file line numberDiff line numberDiff line change
@@ -379,6 +379,5 @@ mir_build_unused_unsafe = unnecessary `unsafe` block
379379
.label = unnecessary `unsafe` block
380380
381381
mir_build_unused_unsafe_enclosing_block_label = because it's nested under this `unsafe` block
382-
mir_build_unused_unsafe_enclosing_fn_label = because it's nested under this `unsafe` fn
383382
384383
mir_build_variant_defined_here = not covered

compiler/rustc_mir_build/src/check_unsafety.rs

+85-67
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use rustc_span::def_id::{DefId, LocalDefId};
1313
use rustc_span::symbol::Symbol;
1414
use rustc_span::Span;
1515

16+
use std::mem;
1617
use std::ops::Bound;
1718

1819
struct UnsafetyVisitor<'a, 'tcx> {
@@ -24,7 +25,6 @@ struct UnsafetyVisitor<'a, 'tcx> {
2425
/// The current "safety context". This notably tracks whether we are in an
2526
/// `unsafe` block, and whether it has been used.
2627
safety_context: SafetyContext,
27-
body_unsafety: BodyUnsafety,
2828
/// The `#[target_feature]` attributes of the body. Used for checking
2929
/// calls to functions with `#[target_feature]` (RFC 2396).
3030
body_target_features: &'tcx [Symbol],
@@ -34,43 +34,50 @@ struct UnsafetyVisitor<'a, 'tcx> {
3434
in_union_destructure: bool,
3535
param_env: ParamEnv<'tcx>,
3636
inside_adt: bool,
37+
warnings: &'a mut Vec<UnusedUnsafeWarning>,
3738
}
3839

3940
impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
4041
fn in_safety_context(&mut self, safety_context: SafetyContext, f: impl FnOnce(&mut Self)) {
41-
if let (
42-
SafetyContext::UnsafeBlock { span: enclosing_span, .. },
43-
SafetyContext::UnsafeBlock { span: block_span, hir_id, .. },
44-
) = (self.safety_context, safety_context)
42+
let prev_context = mem::replace(&mut self.safety_context, safety_context);
43+
44+
f(self);
45+
46+
let safety_context = mem::replace(&mut self.safety_context, prev_context);
47+
if let SafetyContext::UnsafeBlock { used, span, hir_id, nested_used_blocks } =
48+
safety_context
4549
{
46-
self.warn_unused_unsafe(
47-
hir_id,
48-
block_span,
49-
Some(UnusedUnsafeEnclosing::Block {
50-
span: self.tcx.sess.source_map().guess_head_span(enclosing_span),
51-
}),
52-
);
53-
f(self);
54-
} else {
55-
let prev_context = self.safety_context;
56-
self.safety_context = safety_context;
50+
if !used {
51+
self.warn_unused_unsafe(hir_id, span, None);
5752

58-
f(self);
53+
if let SafetyContext::UnsafeBlock {
54+
nested_used_blocks: ref mut prev_nested_used_blocks,
55+
..
56+
} = self.safety_context
57+
{
58+
prev_nested_used_blocks.extend(nested_used_blocks);
59+
}
60+
} else {
61+
for block in nested_used_blocks {
62+
self.warn_unused_unsafe(
63+
block.hir_id,
64+
block.span,
65+
Some(UnusedUnsafeEnclosing::Block {
66+
span: self.tcx.sess.source_map().guess_head_span(span),
67+
}),
68+
);
69+
}
5970

60-
if let SafetyContext::UnsafeBlock { used: false, span, hir_id } = self.safety_context {
61-
self.warn_unused_unsafe(
62-
hir_id,
63-
span,
64-
if self.unsafe_op_in_unsafe_fn_allowed() {
65-
self.body_unsafety
66-
.unsafe_fn_sig_span()
67-
.map(|span| UnusedUnsafeEnclosing::Function { span })
68-
} else {
69-
None
70-
},
71-
);
71+
match self.safety_context {
72+
SafetyContext::UnsafeBlock {
73+
nested_used_blocks: ref mut prev_nested_used_blocks,
74+
..
75+
} => {
76+
prev_nested_used_blocks.push(NestedUsedBlock { hir_id, span });
77+
}
78+
_ => (),
79+
}
7280
}
73-
self.safety_context = prev_context;
7481
}
7582
}
7683

@@ -102,18 +109,12 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
102109
}
103110

104111
fn warn_unused_unsafe(
105-
&self,
112+
&mut self,
106113
hir_id: hir::HirId,
107114
block_span: Span,
108115
enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
109116
) {
110-
let block_span = self.tcx.sess.source_map().guess_head_span(block_span);
111-
self.tcx.emit_spanned_lint(
112-
UNUSED_UNSAFE,
113-
hir_id,
114-
block_span,
115-
UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe },
116-
);
117+
self.warnings.push(UnusedUnsafeWarning { hir_id, block_span, enclosing_unsafe });
117118
}
118119

119120
/// Whether the `unsafe_op_in_unsafe_fn` lint is `allow`ed at the current HIR node.
@@ -128,7 +129,14 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
128129
self.tcx.ensure_with_value().mir_built(def);
129130
let inner_thir = &inner_thir.steal();
130131
let hir_context = self.tcx.hir().local_def_id_to_hir_id(def);
131-
let mut inner_visitor = UnsafetyVisitor { thir: inner_thir, hir_context, ..*self };
132+
let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe);
133+
let mut inner_visitor = UnsafetyVisitor {
134+
thir: inner_thir,
135+
hir_context,
136+
safety_context,
137+
warnings: self.warnings,
138+
..*self
139+
};
132140
inner_visitor.visit_expr(&inner_thir[expr]);
133141
// Unsafe blocks can be used in the inner body, make sure to take it into account
134142
self.safety_context = inner_visitor.safety_context;
@@ -195,8 +203,15 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
195203
});
196204
}
197205
BlockSafety::ExplicitUnsafe(hir_id) => {
206+
let used =
207+
matches!(self.tcx.lint_level_at_node(UNUSED_UNSAFE, hir_id), (Level::Allow, _));
198208
self.in_safety_context(
199-
SafetyContext::UnsafeBlock { span: block.span, hir_id, used: false },
209+
SafetyContext::UnsafeBlock {
210+
span: block.span,
211+
hir_id,
212+
used,
213+
nested_used_blocks: Vec::new(),
214+
},
200215
|this| visit::walk_block(this, block),
201216
);
202217
}
@@ -483,36 +498,29 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
483498
}
484499
}
485500

486-
#[derive(Clone, Copy)]
501+
#[derive(Clone)]
487502
enum SafetyContext {
488503
Safe,
489504
BuiltinUnsafeBlock,
490505
UnsafeFn,
491-
UnsafeBlock { span: Span, hir_id: hir::HirId, used: bool },
506+
UnsafeBlock {
507+
span: Span,
508+
hir_id: hir::HirId,
509+
used: bool,
510+
nested_used_blocks: Vec<NestedUsedBlock>,
511+
},
492512
}
493513

494514
#[derive(Clone, Copy)]
495-
enum BodyUnsafety {
496-
/// The body is not unsafe.
497-
Safe,
498-
/// The body is an unsafe function. The span points to
499-
/// the signature of the function.
500-
Unsafe(Span),
515+
struct NestedUsedBlock {
516+
hir_id: hir::HirId,
517+
span: Span,
501518
}
502519

503-
impl BodyUnsafety {
504-
/// Returns whether the body is unsafe.
505-
fn is_unsafe(&self) -> bool {
506-
matches!(self, BodyUnsafety::Unsafe(_))
507-
}
508-
509-
/// If the body is unsafe, returns the `Span` of its signature.
510-
fn unsafe_fn_sig_span(self) -> Option<Span> {
511-
match self {
512-
BodyUnsafety::Unsafe(span) => Some(span),
513-
BodyUnsafety::Safe => None,
514-
}
515-
}
520+
struct UnusedUnsafeWarning {
521+
hir_id: hir::HirId,
522+
block_span: Span,
523+
enclosing_unsafe: Option<UnusedUnsafeEnclosing>,
516524
}
517525

518526
#[derive(Clone, Copy, PartialEq)]
@@ -805,27 +813,37 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
805813
}
806814

807815
let hir_id = tcx.hir().local_def_id_to_hir_id(def);
808-
let body_unsafety = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(BodyUnsafety::Safe, |fn_sig| {
816+
let safety_context = tcx.hir().fn_sig_by_hir_id(hir_id).map_or(SafetyContext::Safe, |fn_sig| {
809817
if fn_sig.header.unsafety == hir::Unsafety::Unsafe {
810-
BodyUnsafety::Unsafe(fn_sig.span)
818+
SafetyContext::UnsafeFn
811819
} else {
812-
BodyUnsafety::Safe
820+
SafetyContext::Safe
813821
}
814822
});
815823
let body_target_features = &tcx.body_codegen_attrs(def.to_def_id()).target_features;
816-
let safety_context =
817-
if body_unsafety.is_unsafe() { SafetyContext::UnsafeFn } else { SafetyContext::Safe };
824+
let mut warnings = Vec::new();
818825
let mut visitor = UnsafetyVisitor {
819826
tcx,
820827
thir,
821828
safety_context,
822829
hir_context: hir_id,
823-
body_unsafety,
824830
body_target_features,
825831
assignment_info: None,
826832
in_union_destructure: false,
827833
param_env: tcx.param_env(def),
828834
inside_adt: false,
835+
warnings: &mut warnings,
829836
};
830837
visitor.visit_expr(&thir[expr]);
838+
839+
warnings.sort_by_key(|w| w.block_span);
840+
for UnusedUnsafeWarning { hir_id, block_span, enclosing_unsafe } in warnings {
841+
let block_span = tcx.sess.source_map().guess_head_span(block_span);
842+
tcx.emit_spanned_lint(
843+
UNUSED_UNSAFE,
844+
hir_id,
845+
block_span,
846+
UnusedUnsafe { span: block_span, enclosing: enclosing_unsafe },
847+
);
848+
}
831849
}

compiler/rustc_mir_build/src/errors.rs

-5
Original file line numberDiff line numberDiff line change
@@ -392,11 +392,6 @@ pub enum UnusedUnsafeEnclosing {
392392
#[primary_span]
393393
span: Span,
394394
},
395-
#[label(mir_build_unused_unsafe_enclosing_fn_label)]
396-
Function {
397-
#[primary_span]
398-
span: Span,
399-
},
400395
}
401396

402397
pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'p, 'tcx, 'm> {

compiler/rustc_mir_build/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ mod build;
2020
mod check_unsafety;
2121
mod errors;
2222
pub mod lints;
23-
pub mod thir;
23+
mod thir;
2424

2525
use rustc_middle::query::Providers;
2626

tests/ui/inline-const/expr-unsafe.thir.stderr

-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
warning: unnecessary `unsafe` block
22
--> $DIR/expr-unsafe.rs:12:13
33
|
4-
LL | unsafe {
5-
| ------ because it's nested under this `unsafe` block
6-
...
74
LL | unsafe {}
85
| ^^^^^^ unnecessary `unsafe` block
96
|

tests/ui/inline-const/pat-unsafe.thir.stderr

-6
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
warning: unnecessary `unsafe` block
22
--> $DIR/pat-unsafe.rs:19:17
33
|
4-
LL | unsafe {
5-
| ------ because it's nested under this `unsafe` block
6-
...
74
LL | unsafe {}
85
| ^^^^^^ unnecessary `unsafe` block
96
|
@@ -16,9 +13,6 @@ LL | #![warn(unused_unsafe)]
1613
warning: unnecessary `unsafe` block
1714
--> $DIR/pat-unsafe.rs:26:17
1815
|
19-
LL | unsafe {
20-
| ------ because it's nested under this `unsafe` block
21-
...
2216
LL | unsafe {}
2317
| ^^^^^^ unnecessary `unsafe` block
2418

tests/ui/span/lint-unused-unsafe-thir.rs

-61
This file was deleted.

0 commit comments

Comments
 (0)