Skip to content

Commit 558c8a8

Browse files
Handle stores to projections correctly in liveness analysis
Previously, we were too conservative and `x.field = 4` was treated as a "use" of `x`.
1 parent 9672b5e commit 558c8a8

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

src/librustc_mir/dataflow/impls/liveness.rs

+25-2
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,27 @@ impl<'tcx, T> Visitor<'tcx> for TransferFunction<'_, T>
9292
where
9393
T: GenKill<Local>,
9494
{
95+
fn visit_place(&mut self, place: &mir::Place<'tcx>, context: PlaceContext, location: Location) {
96+
let mir::Place { projection, local } = *place;
97+
98+
// We purposefully do not call `super_place` here to avoid calling `visit_local` for this
99+
// place with one of the `Projection` variants of `PlaceContext`.
100+
self.visit_projection(local, projection, context, location);
101+
102+
match DefUse::for_place(context) {
103+
// Treat derefs as a use of the base local. `*p = 4` is not a def of `p` but a use.
104+
Some(_) if place.is_indirect() => self.0.gen(local),
105+
106+
Some(DefUse::Def) if projection.is_empty() => self.0.kill(local),
107+
Some(DefUse::Use) => self.0.gen(local),
108+
_ => {}
109+
}
110+
}
111+
95112
fn visit_local(&mut self, &local: &Local, context: PlaceContext, _: Location) {
113+
// Because we do not call `super_place` above, `visit_local` is only called for locals that
114+
// do not appear as part of a `Place` in the MIR. This handles cases like the implicit use
115+
// of the return place in a `Return` terminator or the index in an `Index` projection.
96116
match DefUse::for_place(context) {
97117
Some(DefUse::Def) => self.0.kill(local),
98118
Some(DefUse::Use) => self.0.gen(local),
@@ -126,19 +146,22 @@ impl DefUse {
126146
| MutatingUseContext::AsmOutput
127147
| MutatingUseContext::Borrow
128148
| MutatingUseContext::Drop
129-
| MutatingUseContext::Projection
130149
| MutatingUseContext::Retag,
131150
)
132151
| PlaceContext::NonMutatingUse(
133152
NonMutatingUseContext::AddressOf
134153
| NonMutatingUseContext::Copy
135154
| NonMutatingUseContext::Inspect
136155
| NonMutatingUseContext::Move
137-
| NonMutatingUseContext::Projection
138156
| NonMutatingUseContext::ShallowBorrow
139157
| NonMutatingUseContext::SharedBorrow
140158
| NonMutatingUseContext::UniqueBorrow,
141159
) => Some(DefUse::Use),
160+
161+
PlaceContext::MutatingUse(MutatingUseContext::Projection)
162+
| PlaceContext::NonMutatingUse(NonMutatingUseContext::Projection) => {
163+
unreachable!("A projection could be a def or a use and must be handled separately")
164+
}
142165
}
143166
}
144167
}

0 commit comments

Comments
 (0)