Skip to content

Commit 9061ffb

Browse files
committed
use no type in ProjectionElem::Field for PlaceBuilder::UpVar
1 parent c39de61 commit 9061ffb

File tree

9 files changed

+105
-52
lines changed

9 files changed

+105
-52
lines changed

compiler/rustc_middle/src/mir/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1517,7 +1517,7 @@ impl<'tcx> StatementKind<'tcx> {
15171517
///////////////////////////////////////////////////////////////////////////
15181518
// Places
15191519

1520-
impl<V, T> ProjectionElem<V, T> {
1520+
impl<V, T, U> ProjectionElem<V, T, U> {
15211521
/// Returns `true` if the target of this projection may refer to a different region of memory
15221522
/// than the base.
15231523
fn is_indirect(&self) -> bool {
@@ -1546,7 +1546,7 @@ impl<V, T> ProjectionElem<V, T> {
15461546

15471547
/// Alias for projections as they appear in `UserTypeProjection`, where we
15481548
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
1549-
pub type ProjectionKind = ProjectionElem<(), ()>;
1549+
pub type ProjectionKind = ProjectionElem<(), (), ()>;
15501550

15511551
rustc_index::newtype_index! {
15521552
/// A [newtype'd][wrapper] index type in the MIR [control-flow graph][CFG]

compiler/rustc_middle/src/mir/syntax.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -877,9 +877,9 @@ pub struct Place<'tcx> {
877877

878878
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
879879
#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable, TypeVisitable)]
880-
pub enum ProjectionElem<V, T> {
880+
pub enum ProjectionElem<V, T1, T2> {
881881
Deref,
882-
Field(Field, T),
882+
Field(Field, T1),
883883
/// Index into a slice/array.
884884
///
885885
/// Note that this does not also dereference, and so it does not exactly correspond to slice
@@ -935,12 +935,36 @@ pub enum ProjectionElem<V, T> {
935935

936936
/// Like an explicit cast from an opaque type to a concrete type, but without
937937
/// requiring an intermediate variable.
938-
OpaqueCast(T),
938+
OpaqueCast(T2),
939939
}
940940

941941
/// Alias for projections as they appear in places, where the base is a place
942942
/// and the index is a local.
943-
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
943+
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>, Ty<'tcx>>;
944+
945+
/// Alias for projections that appear in `PlaceBuilder::UpVar`, for which
946+
/// we cannot provide any field types.
947+
pub type UpvarProjectionElem<'tcx> = ProjectionElem<Local, (), Ty<'tcx>>;
948+
949+
impl<'tcx> From<PlaceElem<'tcx>> for UpvarProjectionElem<'tcx> {
950+
fn from(elem: PlaceElem<'tcx>) -> Self {
951+
match elem {
952+
ProjectionElem::Deref => ProjectionElem::Deref,
953+
ProjectionElem::Field(field, _) => ProjectionElem::Field(field, ()),
954+
ProjectionElem::Index(v) => ProjectionElem::Index(v),
955+
ProjectionElem::ConstantIndex { offset, min_length, from_end } => {
956+
ProjectionElem::ConstantIndex { offset, min_length, from_end }
957+
}
958+
ProjectionElem::Subslice { from, to, from_end } => {
959+
ProjectionElem::Subslice { from, to, from_end }
960+
}
961+
ProjectionElem::Downcast(opt_sym, variant_idx) => {
962+
ProjectionElem::Downcast(opt_sym, variant_idx)
963+
}
964+
ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty),
965+
}
966+
}
967+
}
944968

945969
///////////////////////////////////////////////////////////////////////////
946970
// Operands

compiler/rustc_middle/src/mir/tcx.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ impl<'tcx> PlaceTy<'tcx> {
2828
/// `place_ty.field_ty(tcx, f)` computes the type at a given field
2929
/// of a record or enum-variant. (Most clients of `PlaceTy` can
3030
/// instead just extract the relevant type directly from their
31-
/// `PlaceElem`, but some instances of `ProjectionElem<V, T>` do
32-
/// not carry a `Ty` for `T`.)
31+
/// `PlaceElem`, but some instances of `ProjectionElem<V, T1, T2>` do
32+
/// not carry a `Ty` for `T1` or `T2`.)
3333
///
3434
/// Note that the resulting type has not been normalized.
3535
pub fn field_ty(self, tcx: TyCtxt<'tcx>, f: Field) -> Ty<'tcx> {
@@ -64,17 +64,18 @@ impl<'tcx> PlaceTy<'tcx> {
6464
/// `Ty` or downcast variant corresponding to that projection.
6565
/// The `handle_field` callback must map a `Field` to its `Ty`,
6666
/// (which should be trivial when `T` = `Ty`).
67-
pub fn projection_ty_core<V, T>(
67+
pub fn projection_ty_core<V, T1, T2>(
6868
self,
6969
tcx: TyCtxt<'tcx>,
7070
param_env: ty::ParamEnv<'tcx>,
71-
elem: &ProjectionElem<V, T>,
72-
mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>,
73-
mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>,
71+
elem: &ProjectionElem<V, T1, T2>,
72+
mut handle_field: impl FnMut(&Self, Field, T1) -> Ty<'tcx>,
73+
mut handle_opaque_cast: impl FnMut(&Self, T2) -> Ty<'tcx>,
7474
) -> PlaceTy<'tcx>
7575
where
7676
V: ::std::fmt::Debug,
77-
T: ::std::fmt::Debug + Copy,
77+
T1: ::std::fmt::Debug + Copy,
78+
T2: ::std::fmt::Debug + Copy,
7879
{
7980
if self.variant_index.is_some() && !matches!(elem, ProjectionElem::Field(..)) {
8081
bug!("cannot use non field projection on downcasted place")

compiler/rustc_mir_build/src/build/expr/as_place.rs

+60-32
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use rustc_target::abi::VariantIdx;
1919
use rustc_index::vec::Idx;
2020

2121
use std::assert_matches::assert_matches;
22+
use std::convert::From;
2223
use std::iter;
2324

2425
/// `PlaceBuilder` is used to create places during MIR construction. It allows you to "build up" a
@@ -66,7 +67,7 @@ pub(in crate::build) enum PlaceBuilder<'tcx> {
6667
///
6768
/// Note: in contrast to `PlaceBuilder::Local` we have not yet determined all `Field` types
6869
/// and will only do so once converting to `PlaceBuilder::Local`.
69-
UpVar(UpVar, Vec<PlaceElem<'tcx>>),
70+
UpVar(UpVar, Vec<UpvarProjectionElem<'tcx>>),
7071
}
7172

7273
#[derive(Copy, Clone, Debug, PartialEq)]
@@ -82,7 +83,7 @@ pub(crate) struct UpVar {
8283
/// part of a path that is captured by a closure. We stop applying projections once we see the first
8384
/// projection that isn't captured by a closure.
8485
fn convert_to_hir_projections_and_truncate_for_capture<'tcx>(
85-
mir_projections: &[PlaceElem<'tcx>],
86+
mir_projections: &[UpvarProjectionElem<'tcx>],
8687
) -> Vec<HirProjectionKind> {
8788
let mut hir_projections = Vec::new();
8889
let mut variant = None;
@@ -156,7 +157,7 @@ fn is_ancestor_or_same_capture(
156157
fn find_capture_matching_projections<'a, 'tcx>(
157158
upvars: &'a CaptureMap<'tcx>,
158159
var_hir_id: LocalVarId,
159-
projections: &[PlaceElem<'tcx>],
160+
projections: &[UpvarProjectionElem<'tcx>],
160161
) -> Option<(usize, &'a Capture<'tcx>)> {
161162
let hir_projections = convert_to_hir_projections_and_truncate_for_capture(projections);
162163

@@ -212,8 +213,7 @@ fn to_upvars_resolved_place_builder<'tcx>(
212213
capture.captured_place.place.base_ty,
213214
projection,
214215
&capture.captured_place.place.projections,
215-
)
216-
.collect::<Vec<_>>();
216+
);
217217

218218
let upvar_resolved_place_builder = PlaceBuilder::construct_local_place_builder(
219219
cx,
@@ -222,6 +222,37 @@ fn to_upvars_resolved_place_builder<'tcx>(
222222
upvar_projection,
223223
);
224224

225+
debug_assert!({
226+
let builder = upvar_resolved_place_builder.clone();
227+
let mut valid_conversion = true;
228+
match builder {
229+
PlaceBuilder::Local(_, projections) => {
230+
for proj in projections.iter() {
231+
match proj {
232+
ProjectionElem::Field(_, field_ty) => {
233+
if matches!(field_ty.kind(), ty::Infer(..)) {
234+
debug!(
235+
"field ty should have been converted for projection {:?} in PlaceBuilder {:?}",
236+
proj,
237+
upvar_resolved_place_builder.clone()
238+
);
239+
240+
valid_conversion = false;
241+
break;
242+
}
243+
}
244+
_ => {}
245+
}
246+
}
247+
}
248+
PlaceBuilder::UpVar(..) => {
249+
unreachable!()
250+
}
251+
}
252+
253+
valid_conversion
254+
});
255+
225256
Some(upvar_resolved_place_builder)
226257
}
227258

@@ -233,14 +264,14 @@ fn to_upvars_resolved_place_builder<'tcx>(
233264
/// projection kinds are unsupported.
234265
fn strip_prefix<'a, 'tcx>(
235266
mut base_ty: Ty<'tcx>,
236-
projections: &'a [PlaceElem<'tcx>],
267+
projections: &'a [UpvarProjectionElem<'tcx>],
237268
prefix_projections: &[HirProjection<'tcx>],
238-
) -> impl Iterator<Item = PlaceElem<'tcx>> + 'a {
269+
) -> Vec<UpvarProjectionElem<'tcx>> {
239270
let mut iter = projections
240271
.iter()
241-
.copied()
242272
// Filter out opaque casts, they are unnecessary in the prefix.
243-
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)));
273+
.filter(|elem| !matches!(elem, ProjectionElem::OpaqueCast(..)))
274+
.map(|elem| *elem);
244275
for projection in prefix_projections {
245276
debug!(?projection, ?projection.ty);
246277

@@ -261,7 +292,8 @@ fn strip_prefix<'a, 'tcx>(
261292

262293
base_ty = projection.ty;
263294
}
264-
iter
295+
296+
iter.collect::<Vec<_>>()
265297
}
266298

267299
impl<'tcx> PlaceBuilder<'tcx> {
@@ -292,11 +324,11 @@ impl<'tcx> PlaceBuilder<'tcx> {
292324
&self,
293325
cx: &Builder<'_, 'tcx>,
294326
) -> Option<PlaceBuilder<'tcx>> {
295-
let PlaceBuilder::Upvar( Upvar {var_hir_id, closure_def_id }, projection) = self else {
327+
let PlaceBuilder::UpVar( UpVar {var_hir_id, closure_def_id }, projection) = self else {
296328
return None;
297329
};
298330

299-
to_upvars_resolved_place_builder(cx, var_hir_id, closure_def_id, &projection)
331+
to_upvars_resolved_place_builder(cx, *var_hir_id, *closure_def_id, &projection)
300332
}
301333

302334
pub(crate) fn get_local_projection(&self) -> &[PlaceElem<'tcx>] {
@@ -309,19 +341,16 @@ impl<'tcx> PlaceBuilder<'tcx> {
309341
}
310342

311343
#[instrument(skip(cx), level = "debug")]
312-
pub(crate) fn field(
313-
self,
314-
cx: &Builder<'_, 'tcx>,
315-
f: Field,
316-
default_field_ty: Ty<'tcx>,
317-
) -> Self {
344+
pub(crate) fn field(self, cx: &Builder<'_, 'tcx>, f: Field) -> Self {
318345
let field_ty = match self {
319346
PlaceBuilder::Local(..) => {
320347
let base_place = self.clone();
321-
PlaceBuilder::try_compute_field_ty(cx, f, base_place)
322-
.unwrap_or_else(|| default_field_ty)
348+
PlaceBuilder::compute_field_ty(cx, f, base_place)
349+
}
350+
PlaceBuilder::UpVar(..) => {
351+
let dummy_ty = cx.tcx.mk_ty_infer(ty::FreshTy(0));
352+
dummy_ty
323353
}
324-
PlaceBuilder::UpVar(..) => default_field_ty,
325354
};
326355

327356
self.project(ProjectionElem::Field(f, field_ty))
@@ -347,7 +376,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
347376
PlaceBuilder::Local(local, proj)
348377
}
349378
PlaceBuilder::UpVar(upvar, mut proj) => {
350-
proj.push(elem);
379+
proj.push(elem.into());
351380
PlaceBuilder::UpVar(upvar, proj)
352381
}
353382
};
@@ -363,8 +392,8 @@ impl<'tcx> PlaceBuilder<'tcx> {
363392
*local,
364393
Vec::from_iter(proj.iter().copied().chain([elem.into()])),
365394
),
366-
PlaceBuilder::Upvar(upvar, proj) => PlaceBuilder::UpVar(
367-
upvar,
395+
PlaceBuilder::UpVar(upvar, proj) => PlaceBuilder::UpVar(
396+
*upvar,
368397
Vec::from_iter(proj.iter().copied().chain([elem.into()])),
369398
),
370399
}
@@ -378,11 +407,11 @@ impl<'tcx> PlaceBuilder<'tcx> {
378407
/// Fallible as the root of this place may be an upvar for
379408
/// which no base type can be determined.
380409
#[instrument(skip(cx), level = "debug")]
381-
fn try_compute_field_ty(
410+
fn compute_field_ty(
382411
cx: &Builder<'_, 'tcx>,
383412
field: Field,
384413
base_place: PlaceBuilder<'tcx>,
385-
) -> Option<Ty<'tcx>> {
414+
) -> Ty<'tcx> {
386415
let field_idx = field.as_usize();
387416
let PlaceTy { ty, variant_index } = base_place.to_place(cx).ty(&cx.local_decls, cx.tcx);
388417
let base_ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty);
@@ -442,7 +471,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
442471
_ => bug!("couldn't create field type, unexpected base type: {:?}", base_ty),
443472
};
444473

445-
Some(cx.tcx.normalize_erasing_regions(cx.param_env, field_ty))
474+
cx.tcx.normalize_erasing_regions(cx.param_env, field_ty)
446475
}
447476

448477
/// Creates a `PlaceBuilder::Local` from a `PlaceBuilder::UpVar` whose upvars
@@ -455,7 +484,7 @@ impl<'tcx> PlaceBuilder<'tcx> {
455484
cx: &Builder<'_, 'tcx>,
456485
local: Local,
457486
mut local_projection: Vec<PlaceElem<'tcx>>,
458-
upvar_projection: Vec<PlaceElem<'tcx>>,
487+
upvar_projection: Vec<UpvarProjectionElem<'tcx>>,
459488
) -> Self {
460489
// We iterate through `upvar_projection` and whenever we find a `ProjectionElem::Field` we use
461490
// the ancestor projections, i.e. those projection elements that come before the field projection,
@@ -464,11 +493,10 @@ impl<'tcx> PlaceBuilder<'tcx> {
464493
for proj in upvar_projection.iter() {
465494
debug!("proj: {:?}, local_projection: {:?}", proj, local_projection);
466495
match *proj {
467-
ProjectionElem::Field(field, default_field_ty) => {
496+
ProjectionElem::Field(field, _) => {
468497
let ancestor_proj = local_projection.to_vec();
469498
let base_place = PlaceBuilder::Local(local, ancestor_proj);
470-
let field_ty = PlaceBuilder::try_compute_field_ty(cx, field, base_place)
471-
.unwrap_or_else(|| default_field_ty);
499+
let field_ty = PlaceBuilder::compute_field_ty(cx, field, base_place);
472500
debug!(?field_ty);
473501

474502
local_projection.push(ProjectionElem::Field(field, field_ty));
@@ -593,7 +621,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
593621
place_builder = place_builder.downcast(*adt_def, variant_index);
594622
}
595623
}
596-
block.and(place_builder.field(this, name, expr.ty))
624+
block.and(place_builder.field(this, name))
597625
}
598626
ExprKind::Deref { arg } => {
599627
let place_builder = unpack!(

compiler/rustc_mir_build/src/build/expr/into.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -355,12 +355,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
355355
// base-supplied field, generate an operand that
356356
// reads it from the base.
357357
iter::zip(field_names, &**field_types)
358-
.map(|(n, ty)| match fields_map.get(&n) {
358+
.map(|(n, _ty)| match fields_map.get(&n) {
359359
Some(v) => v.clone(),
360360
None => {
361361
let place_builder = place_builder.clone();
362362
this.consume_by_copy_or_move(
363-
place_builder.field(this, n, *ty).to_place(this),
363+
place_builder.field(this, n).to_place(this),
364364
)
365365
}
366366
})

compiler/rustc_mir_build/src/build/matches/test.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -760,7 +760,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
760760
let downcast_place = match_pair.place.downcast(adt_def, variant_index); // `(x as Variant)`
761761
let consequent_match_pairs = subpatterns.iter().map(|subpattern| {
762762
// e.g., `(x as Variant).0`
763-
let place = downcast_place.clone().field(self, subpattern.field, subpattern.pattern.ty);
763+
let place = downcast_place.clone().field(self, subpattern.field);
764764
// e.g., `(x as Variant).0 @ P1`
765765
MatchPair::new(place, &subpattern.pattern, self)
766766
});

compiler/rustc_mir_build/src/build/matches/util.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
1717
subpatterns
1818
.iter()
1919
.map(|fieldpat| {
20-
let place = place.clone().field(self, fieldpat.field, fieldpat.pattern.ty);
20+
let place = place.clone().field(self, fieldpat.field);
2121

2222
MatchPair::new(place, &fieldpat.pattern, self)
2323
})

compiler/rustc_mir_dataflow/src/move_paths/abs_domain.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use rustc_middle::ty::Ty;
1818
pub struct AbstractOperand;
1919
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
2020
pub struct AbstractType;
21-
pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType>;
21+
pub type AbstractElem = ProjectionElem<AbstractOperand, AbstractType, AbstractType>;
2222

2323
pub trait Lift {
2424
type Abstract;

compiler/rustc_mir_dataflow/src/value_analysis.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -777,10 +777,10 @@ pub enum TrackElem {
777777
Field(Field),
778778
}
779779

780-
impl<V, T> TryFrom<ProjectionElem<V, T>> for TrackElem {
780+
impl<V, T1, T2> TryFrom<ProjectionElem<V, T1, T2>> for TrackElem {
781781
type Error = ();
782782

783-
fn try_from(value: ProjectionElem<V, T>) -> Result<Self, Self::Error> {
783+
fn try_from(value: ProjectionElem<V, T1, T2>) -> Result<Self, Self::Error> {
784784
match value {
785785
ProjectionElem::Field(field, _) => Ok(TrackElem::Field(field)),
786786
_ => Err(()),

0 commit comments

Comments
 (0)