Skip to content

Commit 32baa2e

Browse files
committed
Introduce ProjectionElem::try_map.
1 parent 498ae9f commit 32baa2e

File tree

2 files changed

+44
-48
lines changed

2 files changed

+44
-48
lines changed

compiler/rustc_middle/src/mir/statement.rs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,11 @@ impl<'tcx> PlaceTy<'tcx> {
160160
/// Convenience wrapper around `projection_ty_core` for `PlaceElem`,
161161
/// where we can just use the `Ty` that is already stored inline on
162162
/// field projection elems.
163-
pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> {
163+
pub fn projection_ty<V: ::std::fmt::Debug>(
164+
self,
165+
tcx: TyCtxt<'tcx>,
166+
elem: ProjectionElem<V, Ty<'tcx>>,
167+
) -> PlaceTy<'tcx> {
164168
self.projection_ty_core(tcx, &elem, |ty| ty, |_, _, _, ty| ty, |ty| ty)
165169
}
166170

@@ -290,6 +294,30 @@ impl<V, T> ProjectionElem<V, T> {
290294
Self::UnwrapUnsafeBinder(..) => false,
291295
}
292296
}
297+
298+
pub fn try_map<V2, T2>(
299+
self,
300+
v: impl FnOnce(V) -> Option<V2>,
301+
t: impl FnOnce(T) -> T2,
302+
) -> Option<ProjectionElem<V2, T2>> {
303+
Some(match self {
304+
ProjectionElem::Deref => ProjectionElem::Deref,
305+
ProjectionElem::Downcast(name, read_variant) => {
306+
ProjectionElem::Downcast(name, read_variant)
307+
}
308+
ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, t(ty)),
309+
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
310+
ProjectionElem::ConstantIndex { offset, min_length, from_end }
311+
}
312+
ProjectionElem::Subslice { from, to, from_end } => {
313+
ProjectionElem::Subslice { from, to, from_end }
314+
}
315+
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(t(ty)),
316+
ProjectionElem::Subtype(ty) => ProjectionElem::Subtype(t(ty)),
317+
ProjectionElem::UnwrapUnsafeBinder(ty) => ProjectionElem::UnwrapUnsafeBinder(t(ty)),
318+
ProjectionElem::Index(val) => ProjectionElem::Index(v(val)?),
319+
})
320+
}
293321
}
294322

295323
/// Alias for projections as they appear in `UserTypeProjection`, where we

compiler/rustc_mir_transform/src/gvn.rs

Lines changed: 15 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -447,26 +447,9 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
447447

448448
Projection(base, elem) => {
449449
let base = self.evaluated[base].as_ref()?;
450-
let elem = match elem {
451-
ProjectionElem::Deref => ProjectionElem::Deref,
452-
ProjectionElem::Downcast(name, read_variant) => {
453-
ProjectionElem::Downcast(name, read_variant)
454-
}
455-
ProjectionElem::Field(f, ()) => ProjectionElem::Field(f, ty.ty),
456-
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
457-
ProjectionElem::ConstantIndex { offset, min_length, from_end }
458-
}
459-
ProjectionElem::Subslice { from, to, from_end } => {
460-
ProjectionElem::Subslice { from, to, from_end }
461-
}
462-
ProjectionElem::OpaqueCast(()) => ProjectionElem::OpaqueCast(ty.ty),
463-
ProjectionElem::Subtype(()) => ProjectionElem::Subtype(ty.ty),
464-
ProjectionElem::UnwrapUnsafeBinder(()) => {
465-
ProjectionElem::UnwrapUnsafeBinder(ty.ty)
466-
}
467-
// This should have been replaced by a `ConstantIndex` earlier.
468-
ProjectionElem::Index(_) => return None,
469-
};
450+
// `Index` by constants should have been replaces by `ConstantIndex` by
451+
// `simplify_place_projection`.
452+
let elem = elem.try_map(|_| None, |()| ty.ty)?;
470453
self.ecx.project(base, elem).discard_err()?
471454
}
472455
Address { place, kind: _, provenance: _ } => {
@@ -476,13 +459,11 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
476459
let local = self.locals[place.local]?;
477460
let pointer = self.evaluated[local].as_ref()?;
478461
let mut mplace = self.ecx.deref_pointer(pointer).discard_err()?;
479-
for proj in place.projection.iter().skip(1) {
480-
// We have no call stack to associate a local with a value, so we cannot
481-
// interpret indexing.
482-
if matches!(proj, ProjectionElem::Index(_)) {
483-
return None;
484-
}
485-
mplace = self.ecx.project(&mplace, proj).discard_err()?;
462+
for elem in place.projection.iter().skip(1) {
463+
// `Index` by constants should have been replaces by `ConstantIndex` by
464+
// `simplify_place_projection`.
465+
let elem = elem.try_map(|_| None, |ty| ty)?;
466+
mplace = self.ecx.project(&mplace, elem).discard_err()?;
486467
}
487468
let pointer = mplace.to_ref(&self.ecx);
488469
ImmTy::from_immediate(pointer, ty).into()
@@ -891,27 +872,14 @@ impl<'body, 'tcx> VnState<'body, 'tcx> {
891872
proj: ProjectionElem<VnIndex, ()>,
892873
loc: Location,
893874
) -> Option<PlaceElem<'tcx>> {
894-
Some(match proj {
895-
ProjectionElem::Deref => ProjectionElem::Deref,
896-
ProjectionElem::Field(idx, ()) => ProjectionElem::Field(idx, ty),
897-
ProjectionElem::Index(idx) => {
898-
let Some(local) = self.try_as_local(idx, loc) else {
899-
return None;
900-
};
875+
proj.try_map(
876+
|value| {
877+
let local = self.try_as_local(value, loc)?;
901878
self.reused_locals.insert(local);
902-
ProjectionElem::Index(local)
903-
}
904-
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
905-
ProjectionElem::ConstantIndex { offset, min_length, from_end }
906-
}
907-
ProjectionElem::Subslice { from, to, from_end } => {
908-
ProjectionElem::Subslice { from, to, from_end }
909-
}
910-
ProjectionElem::Downcast(symbol, idx) => ProjectionElem::Downcast(symbol, idx),
911-
ProjectionElem::OpaqueCast(()) => ProjectionElem::OpaqueCast(ty),
912-
ProjectionElem::Subtype(()) => ProjectionElem::Subtype(ty),
913-
ProjectionElem::UnwrapUnsafeBinder(()) => ProjectionElem::UnwrapUnsafeBinder(ty),
914-
})
879+
Some(local)
880+
},
881+
|()| ty,
882+
)
915883
}
916884

917885
fn simplify_aggregate_to_copy(

0 commit comments

Comments
 (0)