Skip to content

Commit b0d7157

Browse files
committed
Auto merge of #142390 - cjgillot:mir-liveness, r=<try>
Perform unused assignment and unused variables lints on MIR. Rebase of #101500 Fixes #51003. The first commit moves detection of uninhabited types from the current liveness pass to MIR building. In order to keep the same level of diagnostics, I had to instrument MIR a little more: - keep for which original local a guard local is created; - store in the `VarBindingForm` the list of introducer places and whether this was a shorthand pattern. I am not very proud of the handling of self-assignments. The proposed scheme is in two parts: first detect probable self-assignments, by pattern matching on MIR, and second treat them specially during dataflow analysis. I welcome ideas. Please review carefully the changes in tests. There are many small changes to behaviour, and I'm not sure all of them are desirable.
2 parents 573a015 + 1d8df21 commit b0d7157

File tree

104 files changed

+2637
-2627
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+2637
-2627
lines changed

compiler/rustc_borrowck/src/diagnostics/move_errors.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
140140
// whether or not the right-hand side is a place expression
141141
if let LocalInfo::User(BindingForm::Var(VarBindingForm {
142142
opt_match_place: Some((opt_match_place, match_span)),
143-
binding_mode: _,
144-
opt_ty_info: _,
145-
pat_span: _,
143+
..
146144
})) = *local_decl.local_info()
147145
{
148146
let stmt_source_info = self.body.source_info(location);

compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -307,8 +307,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
307307
LocalInfo::User(BindingForm::Var(mir::VarBindingForm {
308308
binding_mode: BindingMode(ByRef::No, Mutability::Not),
309309
opt_ty_info: Some(sp),
310-
opt_match_place: _,
311-
pat_span: _,
310+
..
312311
})) => {
313312
if suggest {
314313
err.span_note(sp, "the binding is already a mutable borrow");
@@ -738,6 +737,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
738737
opt_ty_info: _,
739738
opt_match_place: _,
740739
pat_span,
740+
introductions: _,
741741
})) => pat_span,
742742
_ => local_decl.source_info.span,
743743
};

compiler/rustc_interface/src/passes.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,7 @@ fn run_required_analyses(tcx: TyCtxt<'_>) {
990990
tcx.ensure_ok().mir_borrowck(def_id)
991991
}
992992
tcx.ensure_ok().has_ffi_unwind_calls(def_id);
993+
tcx.ensure_ok().check_liveness(def_id);
993994

994995
// If we need to codegen, ensure that we emit all errors from
995996
// `mir_drops_elaborated_and_const_checked` now, to avoid discovering

compiler/rustc_middle/src/mir/mod.rs

Lines changed: 9 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,8 @@ pub struct VarBindingForm<'tcx> {
926926
pub opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
927927
/// The span of the pattern in which this variable was bound.
928928
pub pat_span: Span,
929+
/// For each introduction place, record here the span and whether this was a shorthand pattern.
930+
pub introductions: Vec<(Span, /* is_shorthand */ bool)>,
929931
}
930932

931933
#[derive(Clone, Debug, TyEncodable, TyDecodable)]
@@ -935,7 +937,7 @@ pub enum BindingForm<'tcx> {
935937
/// Binding for a `self`/`&self`/`&mut self` binding where the type is implicit.
936938
ImplicitSelf(ImplicitSelfKind),
937939
/// Reference used in a guard expression to ensure immutability.
938-
RefForGuard,
940+
RefForGuard(Local),
939941
}
940942

941943
mod binding_form_impl {
@@ -950,7 +952,7 @@ mod binding_form_impl {
950952
match self {
951953
Var(binding) => binding.hash_stable(hcx, hasher),
952954
ImplicitSelf(kind) => kind.hash_stable(hcx, hasher),
953-
RefForGuard => (),
955+
RefForGuard(local) => local.hash_stable(hcx, hasher),
954956
}
955957
}
956958
}
@@ -1131,12 +1133,8 @@ impl<'tcx> LocalDecl<'tcx> {
11311133
matches!(
11321134
self.local_info(),
11331135
LocalInfo::User(
1134-
BindingForm::Var(VarBindingForm {
1135-
binding_mode: BindingMode(ByRef::No, _),
1136-
opt_ty_info: _,
1137-
opt_match_place: _,
1138-
pat_span: _,
1139-
}) | BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
1136+
BindingForm::Var(VarBindingForm { binding_mode: BindingMode(ByRef::No, _), .. })
1137+
| BindingForm::ImplicitSelf(ImplicitSelfKind::Imm),
11401138
)
11411139
)
11421140
}
@@ -1148,12 +1146,8 @@ impl<'tcx> LocalDecl<'tcx> {
11481146
matches!(
11491147
self.local_info(),
11501148
LocalInfo::User(
1151-
BindingForm::Var(VarBindingForm {
1152-
binding_mode: BindingMode(ByRef::No, _),
1153-
opt_ty_info: _,
1154-
opt_match_place: _,
1155-
pat_span: _,
1156-
}) | BindingForm::ImplicitSelf(_),
1149+
BindingForm::Var(VarBindingForm { binding_mode: BindingMode(ByRef::No, _), .. })
1150+
| BindingForm::ImplicitSelf(_),
11571151
)
11581152
)
11591153
}
@@ -1169,7 +1163,7 @@ impl<'tcx> LocalDecl<'tcx> {
11691163
/// expression that is used to access said variable for the guard of the
11701164
/// match arm.
11711165
pub fn is_ref_for_guard(&self) -> bool {
1172-
matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard))
1166+
matches!(self.local_info(), LocalInfo::User(BindingForm::RefForGuard(_)))
11731167
}
11741168

11751169
/// Returns `Some` if this is a reference to a static item that is used to

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ impl<'tcx> PlaceTy<'tcx> {
228228
impl<V, T> ProjectionElem<V, T> {
229229
/// Returns `true` if the target of this projection may refer to a different region of memory
230230
/// than the base.
231-
fn is_indirect(&self) -> bool {
231+
pub fn is_indirect(&self) -> bool {
232232
match self {
233233
Self::Deref => true,
234234

compiler/rustc_middle/src/query/mod.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,8 +1127,10 @@ rustc_queries! {
11271127
desc { |tcx| "checking privacy in {}", describe_as_module(key.to_local_def_id(), tcx) }
11281128
}
11291129

1130-
query check_liveness(key: LocalDefId) {
1131-
desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key) }
1130+
query check_liveness(key: LocalDefId) -> &'tcx rustc_index::bit_set::DenseBitSet<abi::FieldIdx> {
1131+
arena_cache
1132+
desc { |tcx| "checking liveness of variables in `{}`", tcx.def_path_str(key.to_def_id()) }
1133+
cache_on_disk_if(tcx) { tcx.is_typeck_child(key.to_def_id()) }
11321134
}
11331135

11341136
/// Return the live symbols in the crate for dead code check.

compiler/rustc_middle/src/thir.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -777,6 +777,7 @@ pub enum PatKind<'tcx> {
777777
/// (The same binding can occur multiple times in different branches of
778778
/// an or-pattern, but only one of them will be primary.)
779779
is_primary: bool,
780+
is_shorthand: bool,
780781
},
781782

782783
/// `Foo(...)` or `Foo{...}` or `Foo`, where `Foo` is a variant name from an ADT with

compiler/rustc_middle/src/ty/closure.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc
327327
)
328328
}
329329
},
330+
HirProjectionKind::UnwrapUnsafeBinder => {
331+
curr_string = format!("unwrap_binder!({curr_string})");
332+
}
333+
// Just change the type to the hidden type, so we can actually project.
334+
HirProjectionKind::OpaqueCast => {}
330335
proj => bug!("{:?} unexpected because it isn't captured", proj),
331336
}
332337
}

compiler/rustc_mir_build/messages.ftl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,11 @@ mir_build_union_field_requires_unsafe_unsafe_op_in_unsafe_fn_allowed =
346346
mir_build_union_pattern = cannot use unions in constant patterns
347347
.label = can't use a `union` here
348348
349+
mir_build_unreachable_due_to_uninhabited = unreachable {$descr}
350+
.label = unreachable {$descr}
351+
.label_orig = any code following this expression is unreachable
352+
.note = this expression has type `{$ty}`, which is uninhabited
353+
349354
mir_build_unreachable_making_this_unreachable = collectively making this unreachable
350355
351356
mir_build_unreachable_making_this_unreachable_n_more = ...and {$covered_by_many_n_more_count} other patterns collectively make this unreachable

compiler/rustc_mir_build/src/builder/block.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
204204
block,
205205
node,
206206
span,
207+
false,
207208
OutsideGuard,
208209
ScheduleDrops::Yes,
209210
);
@@ -296,6 +297,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
296297
block,
297298
node,
298299
span,
300+
false,
299301
OutsideGuard,
300302
ScheduleDrops::Yes,
301303
);

0 commit comments

Comments
 (0)