diff options
| author | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2023-12-17 00:00:00 +0000 |
|---|---|---|
| committer | Tomasz Miąsko <tomasz.miasko@gmail.com> | 2023-12-21 12:58:39 +0100 |
| commit | 532080cfcccdfd853008c4452b283130b544c675 (patch) | |
| tree | fb69131b9a68a4533c64e89bce4e0c0895141b0a /compiler | |
| parent | b4877753c3934a17621dd102aacbd200efc27be7 (diff) | |
Stricter check for a use of locals without storage
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_mir_transform/src/lint.rs | 28 |
1 files changed, 18 insertions, 10 deletions
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs index d7380b4e04b..3940d0ddbf3 100644 --- a/compiler/rustc_mir_transform/src/lint.rs +++ b/compiler/rustc_mir_transform/src/lint.rs @@ -5,7 +5,7 @@ use rustc_index::bit_set::BitSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use rustc_mir_dataflow::impls::MaybeStorageLive; +use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive}; use rustc_mir_dataflow::storage::always_storage_live_locals; use rustc_mir_dataflow::{Analysis, ResultsCursor}; use std::borrow::Cow; @@ -13,7 +13,13 @@ use std::borrow::Cow; pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { let reachable_blocks = traversal::reachable_as_bitset(body); let always_live_locals = &always_storage_live_locals(body); - let storage_liveness = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) + + let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals)) + .into_engine(tcx, body) + .iterate_to_fixpoint() + .into_results_cursor(body); + + let maybe_storage_dead = MaybeStorageDead::new(Cow::Borrowed(always_live_locals)) .into_engine(tcx, body) .iterate_to_fixpoint() .into_results_cursor(body); @@ -25,7 +31,8 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) { is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(), always_live_locals, reachable_blocks, - storage_liveness, + maybe_storage_live, + maybe_storage_dead, } .visit_body(body); } @@ -37,7 +44,8 @@ struct Lint<'a, 'tcx> { is_fn_like: bool, always_live_locals: &'a BitSet<Local>, reachable_blocks: BitSet<BasicBlock>, - storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, + maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>, + maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>, } impl<'a, 'tcx> Lint<'a, 'tcx> { @@ -60,8 +68,8 @@ impl<'a, 'tcx> Lint<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) { if self.reachable_blocks.contains(location.block) && context.is_use() { - self.storage_liveness.seek_after_primary_effect(location); - if !self.storage_liveness.get().contains(local) { + self.maybe_storage_dead.seek_after_primary_effect(location); + if self.maybe_storage_dead.get().contains(local) { self.fail(location, format!("use of local {local:?}, which has no storage here")); } } @@ -71,8 +79,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { match statement.kind { StatementKind::StorageLive(local) => { if self.reachable_blocks.contains(location.block) { - self.storage_liveness.seek_before_primary_effect(location); - if self.storage_liveness.get().contains(local) { + self.maybe_storage_live.seek_before_primary_effect(location); + if self.maybe_storage_live.get().contains(local) { self.fail( location, format!("StorageLive({local:?}) which already has storage here"), @@ -90,8 +98,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> { match terminator.kind { TerminatorKind::Return => { if self.is_fn_like && self.reachable_blocks.contains(location.block) { - self.storage_liveness.seek_after_primary_effect(location); - for local in self.storage_liveness.get().iter() { + self.maybe_storage_live.seek_after_primary_effect(location); + for local in self.maybe_storage_live.get().iter() { if !self.always_live_locals.contains(local) { self.fail( location, |
