Skip to content

Commit 532080c

Browse files
committed
Stricter check for a use of locals without storage
1 parent b487775 commit 532080c

File tree

2 files changed

+48
-10
lines changed

2 files changed

+48
-10
lines changed

Diff for: compiler/rustc_mir_transform/src/lint.rs

+18-10
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,21 @@ use rustc_index::bit_set::BitSet;
55
use rustc_middle::mir::visit::{PlaceContext, Visitor};
66
use rustc_middle::mir::*;
77
use rustc_middle::ty::TyCtxt;
8-
use rustc_mir_dataflow::impls::MaybeStorageLive;
8+
use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive};
99
use rustc_mir_dataflow::storage::always_storage_live_locals;
1010
use rustc_mir_dataflow::{Analysis, ResultsCursor};
1111
use std::borrow::Cow;
1212

1313
pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
1414
let reachable_blocks = traversal::reachable_as_bitset(body);
1515
let always_live_locals = &always_storage_live_locals(body);
16-
let storage_liveness = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
16+
17+
let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
18+
.into_engine(tcx, body)
19+
.iterate_to_fixpoint()
20+
.into_results_cursor(body);
21+
22+
let maybe_storage_dead = MaybeStorageDead::new(Cow::Borrowed(always_live_locals))
1723
.into_engine(tcx, body)
1824
.iterate_to_fixpoint()
1925
.into_results_cursor(body);
@@ -25,7 +31,8 @@ pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
2531
is_fn_like: tcx.def_kind(body.source.def_id()).is_fn_like(),
2632
always_live_locals,
2733
reachable_blocks,
28-
storage_liveness,
34+
maybe_storage_live,
35+
maybe_storage_dead,
2936
}
3037
.visit_body(body);
3138
}
@@ -37,7 +44,8 @@ struct Lint<'a, 'tcx> {
3744
is_fn_like: bool,
3845
always_live_locals: &'a BitSet<Local>,
3946
reachable_blocks: BitSet<BasicBlock>,
40-
storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
47+
maybe_storage_live: ResultsCursor<'a, 'tcx, MaybeStorageLive<'a>>,
48+
maybe_storage_dead: ResultsCursor<'a, 'tcx, MaybeStorageDead<'a>>,
4149
}
4250

4351
impl<'a, 'tcx> Lint<'a, 'tcx> {
@@ -60,8 +68,8 @@ impl<'a, 'tcx> Lint<'a, 'tcx> {
6068
impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
6169
fn visit_local(&mut self, local: Local, context: PlaceContext, location: Location) {
6270
if self.reachable_blocks.contains(location.block) && context.is_use() {
63-
self.storage_liveness.seek_after_primary_effect(location);
64-
if !self.storage_liveness.get().contains(local) {
71+
self.maybe_storage_dead.seek_after_primary_effect(location);
72+
if self.maybe_storage_dead.get().contains(local) {
6573
self.fail(location, format!("use of local {local:?}, which has no storage here"));
6674
}
6775
}
@@ -71,8 +79,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
7179
match statement.kind {
7280
StatementKind::StorageLive(local) => {
7381
if self.reachable_blocks.contains(location.block) {
74-
self.storage_liveness.seek_before_primary_effect(location);
75-
if self.storage_liveness.get().contains(local) {
82+
self.maybe_storage_live.seek_before_primary_effect(location);
83+
if self.maybe_storage_live.get().contains(local) {
7684
self.fail(
7785
location,
7886
format!("StorageLive({local:?}) which already has storage here"),
@@ -90,8 +98,8 @@ impl<'a, 'tcx> Visitor<'tcx> for Lint<'a, 'tcx> {
9098
match terminator.kind {
9199
TerminatorKind::Return => {
92100
if self.is_fn_like && self.reachable_blocks.contains(location.block) {
93-
self.storage_liveness.seek_after_primary_effect(location);
94-
for local in self.storage_liveness.get().iter() {
101+
self.maybe_storage_live.seek_after_primary_effect(location);
102+
for local in self.maybe_storage_live.get().iter() {
95103
if !self.always_live_locals.contains(local) {
96104
self.fail(
97105
location,

Diff for: tests/ui/mir/lint/no-storage.rs

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// compile-flags: -Zlint-mir --crate-type=lib -Ztreat-err-as-bug
2+
// failure-status: 101
3+
// dont-check-compiler-stderr
4+
// regex-error-pattern: use of local .*, which has no storage here
5+
#![feature(custom_mir, core_intrinsics)]
6+
extern crate core;
7+
use core::intrinsics::mir::*;
8+
9+
#[custom_mir(dialect = "built")]
10+
pub fn f(a: bool) {
11+
mir!(
12+
let b: ();
13+
{
14+
match a { true => bb1, _ => bb2 }
15+
}
16+
bb1 = {
17+
StorageLive(b);
18+
Goto(bb3)
19+
}
20+
bb2 = {
21+
Goto(bb3)
22+
}
23+
bb3 = {
24+
b = ();
25+
RET = b;
26+
StorageDead(b);
27+
Return()
28+
}
29+
)
30+
}

0 commit comments

Comments
 (0)