Skip to content

Commit 24a40d8

Browse files
committed
Auto merge of #59514 - tmandry:remove-adt-def-from-projection-elem, r=<try>
Remove adt_def from projections and downcasts in MIR As part of optimizing generator layouts in MIR, we'd like to allow downcasting generators to variants which do not have a corresponding `def_id`, since they are created by the compiler. This refactor hopes to allow that, without regressing perf. r? @eddyb
2 parents 70a497a + f4a1628 commit 24a40d8

40 files changed

+208
-202
lines changed

src/librustc/mir/mod.rs

+37-30
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::slice;
2525
use std::vec::IntoIter;
2626
use std::{iter, mem, option, u32};
2727
use syntax::ast::{self, Name};
28-
use syntax::symbol::InternedString;
28+
use syntax::symbol::{InternedString, Symbol};
2929
use syntax_pos::{Span, DUMMY_SP};
3030
use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
3131
use crate::ty::subst::{Subst, SubstsRef};
@@ -772,7 +772,7 @@ pub struct LocalDecl<'tcx> {
772772
/// e.g., via `let x: T`, then we carry that type here. The MIR
773773
/// borrow checker needs this information since it can affect
774774
/// region inference.
775-
pub user_ty: UserTypeProjections<'tcx>,
775+
pub user_ty: UserTypeProjections,
776776

777777
/// Name of the local, used in debuginfo and pretty-printing.
778778
///
@@ -1805,7 +1805,7 @@ pub enum StatementKind<'tcx> {
18051805
/// - `Contravariant` -- requires that `T_y :> T`
18061806
/// - `Invariant` -- requires that `T_y == T`
18071807
/// - `Bivariant` -- no effect
1808-
AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection<'tcx>>),
1808+
AscribeUserType(Place<'tcx>, ty::Variance, Box<UserTypeProjection>),
18091809

18101810
/// No-op. Useful for deleting instructions without affecting statement indices.
18111811
Nop,
@@ -1939,14 +1939,14 @@ impl_stable_hash_for!(struct Static<'tcx> {
19391939
/// `PlaceProjection` etc below.
19401940
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
19411941
Hash, RustcEncodable, RustcDecodable, HashStable)]
1942-
pub struct Projection<'tcx, B, V, T> {
1942+
pub struct Projection<B, V, T> {
19431943
pub base: B,
1944-
pub elem: ProjectionElem<'tcx, V, T>,
1944+
pub elem: ProjectionElem<V, T>,
19451945
}
19461946

19471947
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord,
19481948
Hash, RustcEncodable, RustcDecodable, HashStable)]
1949-
pub enum ProjectionElem<'tcx, V, T> {
1949+
pub enum ProjectionElem<V, T> {
19501950
Deref,
19511951
Field(Field, T),
19521952
Index(V),
@@ -1980,16 +1980,16 @@ pub enum ProjectionElem<'tcx, V, T> {
19801980
/// "Downcast" to a variant of an ADT. Currently, we only introduce
19811981
/// this for ADTs with more than one variant. It may be better to
19821982
/// just introduce it always, or always for enums.
1983-
Downcast(&'tcx AdtDef, VariantIdx),
1983+
Downcast(Option<Symbol>, VariantIdx),
19841984
}
19851985

19861986
/// Alias for projections as they appear in places, where the base is a place
19871987
/// and the index is a local.
1988-
pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>;
1988+
pub type PlaceProjection<'tcx> = Projection<Place<'tcx>, Local, Ty<'tcx>>;
19891989

19901990
/// Alias for projections as they appear in places, where the base is a place
19911991
/// and the index is a local.
1992-
pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>;
1992+
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
19931993

19941994
// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers
19951995
static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
@@ -1998,7 +1998,7 @@ static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE:
19981998

19991999
/// Alias for projections as they appear in `UserTypeProjection`, where we
20002000
/// need neither the `V` parameter for `Index` nor the `T` for `Field`.
2001-
pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>;
2001+
pub type ProjectionKind = ProjectionElem<(), ()>;
20022002

20032003
newtype_index! {
20042004
pub struct Field {
@@ -2019,7 +2019,9 @@ impl<'tcx> Place<'tcx> {
20192019
}
20202020

20212021
pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
2022-
self.elem(ProjectionElem::Downcast(adt_def, variant_index))
2022+
self.elem(ProjectionElem::Downcast(
2023+
Some(adt_def.variants[variant_index].ident.name),
2024+
variant_index))
20232025
}
20242026

20252027
pub fn index(self, index: Local) -> Place<'tcx> {
@@ -2080,8 +2082,11 @@ impl<'tcx> Debug for Place<'tcx> {
20802082
)
20812083
},
20822084
Projection(ref data) => match data.elem {
2083-
ProjectionElem::Downcast(ref adt_def, index) => {
2084-
write!(fmt, "({:?} as {})", data.base, adt_def.variants[index].ident)
2085+
ProjectionElem::Downcast(Some(name), _index) => {
2086+
write!(fmt, "({:?} as {})", data.base, name)
2087+
}
2088+
ProjectionElem::Downcast(None, index) => {
2089+
write!(fmt, "({:?} as variant#{:?})", data.base, index)
20852090
}
20862091
ProjectionElem::Deref => write!(fmt, "(*{:?})", data.base),
20872092
ProjectionElem::Field(field, ty) => {
@@ -2541,36 +2546,36 @@ pub struct Constant<'tcx> {
25412546
/// inferred region `'1`). The second will lead to the constraint `w:
25422547
/// &'static str`.
25432548
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
2544-
pub struct UserTypeProjections<'tcx> {
2545-
pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
2549+
pub struct UserTypeProjections {
2550+
pub(crate) contents: Vec<(UserTypeProjection, Span)>,
25462551
}
25472552

25482553
BraceStructTypeFoldableImpl! {
2549-
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
2554+
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections {
25502555
contents
25512556
}
25522557
}
25532558

2554-
impl<'tcx> UserTypeProjections<'tcx> {
2559+
impl<'tcx> UserTypeProjections {
25552560
pub fn none() -> Self {
25562561
UserTypeProjections { contents: vec![] }
25572562
}
25582563

2559-
pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
2564+
pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection, Span)>) -> Self {
25602565
UserTypeProjections { contents: projs.collect() }
25612566
}
25622567

2563-
pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
2568+
pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection, Span)> {
25642569
self.contents.iter()
25652570
}
25662571

2567-
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
2572+
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection> {
25682573
self.contents.iter().map(|&(ref user_type, _span)| user_type)
25692574
}
25702575

25712576
pub fn push_projection(
25722577
mut self,
2573-
user_ty: &UserTypeProjection<'tcx>,
2578+
user_ty: &UserTypeProjection,
25742579
span: Span,
25752580
) -> Self {
25762581
self.contents.push((user_ty.clone(), span));
@@ -2579,7 +2584,7 @@ impl<'tcx> UserTypeProjections<'tcx> {
25792584

25802585
fn map_projections(
25812586
mut self,
2582-
mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
2587+
mut f: impl FnMut(UserTypeProjection) -> UserTypeProjection
25832588
) -> Self {
25842589
self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
25852590
self
@@ -2627,14 +2632,14 @@ impl<'tcx> UserTypeProjections<'tcx> {
26272632
/// `field[0]` (aka `.0`), indicating that the type of `s` is
26282633
/// determined by finding the type of the `.0` field from `T`.
26292634
#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, HashStable)]
2630-
pub struct UserTypeProjection<'tcx> {
2635+
pub struct UserTypeProjection {
26312636
pub base: UserTypeAnnotationIndex,
2632-
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
2637+
pub projs: Vec<ProjectionElem<(), ()>>,
26332638
}
26342639

2635-
impl<'tcx> Copy for ProjectionKind<'tcx> { }
2640+
impl Copy for ProjectionKind { }
26362641

2637-
impl<'tcx> UserTypeProjection<'tcx> {
2642+
impl UserTypeProjection {
26382643
pub(crate) fn index(mut self) -> Self {
26392644
self.projs.push(ProjectionElem::Index(()));
26402645
self
@@ -2661,15 +2666,17 @@ impl<'tcx> UserTypeProjection<'tcx> {
26612666
variant_index: VariantIdx,
26622667
field: Field,
26632668
) -> Self {
2664-
self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
2669+
self.projs.push(ProjectionElem::Downcast(
2670+
Some(adt_def.variants[variant_index].ident.name),
2671+
variant_index));
26652672
self.projs.push(ProjectionElem::Field(field, ()));
26662673
self
26672674
}
26682675
}
26692676

2670-
CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }
2677+
CloneTypeFoldableAndLiftImpls! { ProjectionKind, }
26712678

2672-
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {
2679+
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection {
26732680
fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
26742681
use crate::mir::ProjectionElem::*;
26752682

@@ -3427,7 +3434,7 @@ impl<'tcx> TypeFoldable<'tcx> for Operand<'tcx> {
34273434
}
34283435
}
34293436

3430-
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<'tcx, B, V, T>
3437+
impl<'tcx, B, V, T> TypeFoldable<'tcx> for Projection<B, V, T>
34313438
where
34323439
B: TypeFoldable<'tcx>,
34333440
V: TypeFoldable<'tcx>,

src/librustc/mir/tcx.rs

+30-37
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
*/
55

66
use crate::mir::*;
7-
use crate::ty::subst::{Subst, SubstsRef};
8-
use crate::ty::{self, AdtDef, Ty, TyCtxt};
7+
use crate::ty::subst::Subst;
8+
use crate::ty::{self, Ty, TyCtxt};
99
use crate::ty::layout::VariantIdx;
1010
use crate::hir;
1111
use crate::ty::util::IntTypeExt;
@@ -16,8 +16,7 @@ pub enum PlaceTy<'tcx> {
1616
Ty { ty: Ty<'tcx> },
1717

1818
/// Downcast to a particular variant of an enum.
19-
Downcast { adt_def: &'tcx AdtDef,
20-
substs: SubstsRef<'tcx>,
19+
Downcast { ty: Ty<'tcx>,
2120
variant_index: VariantIdx },
2221
}
2322

@@ -30,12 +29,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
3029
PlaceTy::Ty { ty }
3130
}
3231

33-
pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
32+
pub fn to_ty(&self) -> Ty<'tcx> {
3433
match *self {
35-
PlaceTy::Ty { ty } =>
36-
ty,
37-
PlaceTy::Downcast { adt_def, substs, variant_index: _ } =>
38-
tcx.mk_adt(adt_def, substs),
34+
PlaceTy::Ty { ty } => ty,
35+
PlaceTy::Downcast { ty, variant_index: _ } => ty,
3936
}
4037
}
4138

@@ -48,21 +45,18 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
4845
/// Note that the resulting type has not been normalized.
4946
pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
5047
{
51-
// Pass `0` here so it can be used as a "default" variant_index in first arm below
52-
let answer = match (self, VariantIdx::new(0)) {
53-
(PlaceTy::Ty {
54-
ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) |
55-
(PlaceTy::Downcast { adt_def, substs, variant_index }, _) => {
48+
let answer = match self.to_ty().sty {
49+
ty::TyKind::Adt(adt_def, substs) => {
50+
let variant_index = match &self {
51+
PlaceTy::Ty { .. } => VariantIdx::new(0),
52+
PlaceTy::Downcast { ty: _, variant_index } => *variant_index,
53+
};
5654
let variant_def = &adt_def.variants[variant_index];
5755
let field_def = &variant_def.fields[f.index()];
5856
field_def.ty(tcx, substs)
5957
}
60-
(PlaceTy::Ty { ty }, _) => {
61-
match ty.sty {
62-
ty::Tuple(ref tys) => tys[f.index()],
63-
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
64-
}
65-
}
58+
ty::Tuple(ref tys) => tys[f.index()],
59+
_ => bug!("extracting field of non-tuple non-adt: {:?}", self),
6660
};
6761
debug!("field_ty self: {:?} f: {:?} yields: {:?}", self, f, answer);
6862
answer
@@ -86,15 +80,15 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
8680
pub fn projection_ty_core<V, T>(
8781
self,
8882
tcx: TyCtxt<'a, 'gcx, 'tcx>,
89-
elem: &ProjectionElem<'tcx, V, T>,
83+
elem: &ProjectionElem<V, T>,
9084
mut handle_field: impl FnMut(&Self, &Field, &T) -> Ty<'tcx>)
9185
-> PlaceTy<'tcx>
9286
where
9387
V: ::std::fmt::Debug, T: ::std::fmt::Debug
9488
{
9589
let answer = match *elem {
9690
ProjectionElem::Deref => {
97-
let ty = self.to_ty(tcx)
91+
let ty = self.to_ty()
9892
.builtin_deref(true)
9993
.unwrap_or_else(|| {
10094
bug!("deref projection of non-dereferencable ty {:?}", self)
@@ -106,10 +100,10 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
106100
}
107101
ProjectionElem::Index(_) | ProjectionElem::ConstantIndex { .. } =>
108102
PlaceTy::Ty {
109-
ty: self.to_ty(tcx).builtin_index().unwrap()
103+
ty: self.to_ty().builtin_index().unwrap()
110104
},
111105
ProjectionElem::Subslice { from, to } => {
112-
let ty = self.to_ty(tcx);
106+
let ty = self.to_ty();
113107
PlaceTy::Ty {
114108
ty: match ty.sty {
115109
ty::Array(inner, size) => {
@@ -124,20 +118,19 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
124118
}
125119
}
126120
}
127-
ProjectionElem::Downcast(adt_def1, index) =>
128-
match self.to_ty(tcx).sty {
129-
ty::Adt(adt_def, substs) => {
121+
ProjectionElem::Downcast(_name, index) => {
122+
let ty = self.to_ty();
123+
match &ty.sty {
124+
ty::Adt(adt_def, _substs) => {
130125
assert!(adt_def.is_enum());
131126
assert!(index.as_usize() < adt_def.variants.len());
132-
assert_eq!(adt_def, adt_def1);
133-
PlaceTy::Downcast { adt_def,
134-
substs,
135-
variant_index: index }
136127
}
137128
_ => {
138129
bug!("cannot downcast non-ADT type: `{:?}`", self)
139130
}
140-
},
131+
};
132+
PlaceTy::Downcast { ty, variant_index: index }
133+
}
141134
ProjectionElem::Field(ref f, ref fty) =>
142135
PlaceTy::Ty { ty: handle_field(&self, f, fty) },
143136
};
@@ -149,7 +142,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
149142
EnumTypeFoldableImpl! {
150143
impl<'tcx> TypeFoldable<'tcx> for PlaceTy<'tcx> {
151144
(PlaceTy::Ty) { ty },
152-
(PlaceTy::Downcast) { adt_def, substs, variant_index },
145+
(PlaceTy::Downcast) { ty, variant_index },
153146
}
154147
}
155148

@@ -186,7 +179,7 @@ impl<'tcx> Place<'tcx> {
186179
match place {
187180
Place::Projection(ref proj) => match proj.elem {
188181
ProjectionElem::Field(field, _ty) => {
189-
let base_ty = proj.base.ty(mir, *tcx).to_ty(*tcx);
182+
let base_ty = proj.base.ty(mir, *tcx).to_ty();
190183

191184
if (base_ty.is_closure() || base_ty.is_generator()) &&
192185
(!by_ref || mir.upvar_decls[field.index()].by_ref)
@@ -218,7 +211,7 @@ impl<'tcx> Rvalue<'tcx> {
218211
tcx.mk_array(operand.ty(local_decls, tcx), count)
219212
}
220213
Rvalue::Ref(reg, bk, ref place) => {
221-
let place_ty = place.ty(local_decls, tcx).to_ty(tcx);
214+
let place_ty = place.ty(local_decls, tcx).to_ty();
222215
tcx.mk_ref(reg,
223216
ty::TypeAndMut {
224217
ty: place_ty,
@@ -244,7 +237,7 @@ impl<'tcx> Rvalue<'tcx> {
244237
operand.ty(local_decls, tcx)
245238
}
246239
Rvalue::Discriminant(ref place) => {
247-
let ty = place.ty(local_decls, tcx).to_ty(tcx);
240+
let ty = place.ty(local_decls, tcx).to_ty();
248241
if let ty::Adt(adt_def, _) = ty.sty {
249242
adt_def.repr.discr_type().to_ty(tcx)
250243
} else {
@@ -293,7 +286,7 @@ impl<'tcx> Operand<'tcx> {
293286
{
294287
match self {
295288
&Operand::Copy(ref l) |
296-
&Operand::Move(ref l) => l.ty(local_decls, tcx).to_ty(tcx),
289+
&Operand::Move(ref l) => l.ty(local_decls, tcx).to_ty(),
297290
&Operand::Constant(ref c) => c.ty,
298291
}
299292
}

0 commit comments

Comments
 (0)