Skip to content

Commit 0bfe184

Browse files
committed
Stop duplicating projections of type annotation.
This commit changes how type annotations are handled in bindings during MIR building. Instead of building up a `PatternTypeProjections` with the `CanonicalUserTypeAnnotation` and projections, the `CanonicalUserTypeAnnotation` is stored in the `canonical_user_type_annotations` map at the start and the (equivalent) `UserTypeProjections` is built up with the new index and same projections. This has the effect of deduplicating type annotations as instead of type annotations being added to the `canonical_user_type_annotations` map multiple times at the end after being duplicated (which happens in building up `PatternTypeProjections`), it is instead added once.
1 parent 28fd1b0 commit 0bfe184

File tree

5 files changed

+99
-114
lines changed

5 files changed

+99
-114
lines changed

src/librustc/mir/mod.rs

+75
Original file line numberDiff line numberDiff line change
@@ -2519,6 +2519,48 @@ impl<'tcx> UserTypeProjections<'tcx> {
25192519
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
25202520
self.contents.iter().map(|&(ref user_type, _span)| user_type)
25212521
}
2522+
2523+
pub fn push_projection(
2524+
mut self,
2525+
user_ty: &UserTypeProjection<'tcx>,
2526+
span: Span,
2527+
) -> Self {
2528+
self.contents.push((user_ty.clone(), span));
2529+
self
2530+
}
2531+
2532+
fn map_projections(
2533+
mut self,
2534+
mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
2535+
) -> Self {
2536+
self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
2537+
self
2538+
}
2539+
2540+
pub fn index(self) -> Self {
2541+
self.map_projections(|pat_ty_proj| pat_ty_proj.index())
2542+
}
2543+
2544+
pub fn subslice(self, from: u32, to: u32) -> Self {
2545+
self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
2546+
}
2547+
2548+
pub fn deref(self) -> Self {
2549+
self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
2550+
}
2551+
2552+
pub fn leaf(self, field: Field) -> Self {
2553+
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
2554+
}
2555+
2556+
pub fn variant(
2557+
self,
2558+
adt_def: &'tcx AdtDef,
2559+
variant_index: VariantIdx,
2560+
field: Field,
2561+
) -> Self {
2562+
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
2563+
}
25222564
}
25232565

25242566
/// Encodes the effect of a user-supplied type annotation on the
@@ -2544,6 +2586,39 @@ pub struct UserTypeProjection<'tcx> {
25442586

25452587
impl<'tcx> Copy for ProjectionKind<'tcx> { }
25462588

2589+
impl<'tcx> UserTypeProjection<'tcx> {
2590+
pub(crate) fn index(mut self) -> Self {
2591+
self.projs.push(ProjectionElem::Index(()));
2592+
self
2593+
}
2594+
2595+
pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
2596+
self.projs.push(ProjectionElem::Subslice { from, to });
2597+
self
2598+
}
2599+
2600+
pub(crate) fn deref(mut self) -> Self {
2601+
self.projs.push(ProjectionElem::Deref);
2602+
self
2603+
}
2604+
2605+
pub(crate) fn leaf(mut self, field: Field) -> Self {
2606+
self.projs.push(ProjectionElem::Field(field, ()));
2607+
self
2608+
}
2609+
2610+
pub(crate) fn variant(
2611+
mut self,
2612+
adt_def: &'tcx AdtDef,
2613+
variant_index: VariantIdx,
2614+
field: Field,
2615+
) -> Self {
2616+
self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
2617+
self.projs.push(ProjectionElem::Field(field, ()));
2618+
self
2619+
}
2620+
}
2621+
25472622
CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }
25482623

25492624
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {

src/librustc_mir/build/block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
144144
debug!("ast_block_stmts: pattern={:?}", pattern);
145145
this.visit_bindings(
146146
&pattern,
147-
&PatternTypeProjections::none(),
147+
UserTypeProjections::none(),
148148
&mut |this, _, _, _, node, span, _, _| {
149149
this.storage_live_binding(block, node, span, OutsideGuard);
150150
this.schedule_drop_for_binding(node, span, OutsideGuard);

src/librustc_mir/build/matches/mod.rs

+20-17
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
88
use build::{BlockAnd, BlockAndExtension, Builder};
99
use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
1010
use hair::*;
11-
use hair::pattern::PatternTypeProjections;
1211
use rustc::mir::*;
1312
use rustc::ty::{self, Ty};
1413
use rustc::ty::layout::VariantIdx;
@@ -412,7 +411,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
412411
debug!("declare_bindings: patterns={:?}", patterns);
413412
self.visit_bindings(
414413
&patterns[0],
415-
&PatternTypeProjections::none(),
414+
UserTypeProjections::none(),
416415
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
417416
if visibility_scope.is_none() {
418417
visibility_scope =
@@ -488,7 +487,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
488487
pub(super) fn visit_bindings(
489488
&mut self,
490489
pattern: &Pattern<'tcx>,
491-
pattern_user_ty: &PatternTypeProjections<'tcx>,
490+
pattern_user_ty: UserTypeProjections<'tcx>,
492491
f: &mut impl FnMut(
493492
&mut Self,
494493
Mutability,
@@ -497,7 +496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
497496
NodeId,
498497
Span,
499498
Ty<'tcx>,
500-
&PatternTypeProjections<'tcx>,
499+
UserTypeProjections<'tcx>,
501500
),
502501
) {
503502
debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
@@ -511,7 +510,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
511510
ref subpattern,
512511
..
513512
} => {
514-
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
513+
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
515514
if let Some(subpattern) = subpattern.as_ref() {
516515
self.visit_bindings(subpattern, pattern_user_ty, f);
517516
}
@@ -529,42 +528,47 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
529528
let from = u32::try_from(prefix.len()).unwrap();
530529
let to = u32::try_from(suffix.len()).unwrap();
531530
for subpattern in prefix {
532-
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
531+
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
533532
}
534533
for subpattern in slice {
535-
self.visit_bindings(subpattern, &pattern_user_ty.subslice(from, to), f);
534+
self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f);
536535
}
537536
for subpattern in suffix {
538-
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
537+
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
539538
}
540539
}
541540
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
542541
PatternKind::Deref { ref subpattern } => {
543-
self.visit_bindings(subpattern, &pattern_user_ty.deref(), f);
542+
self.visit_bindings(subpattern, pattern_user_ty.deref(), f);
544543
}
545544
PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => {
546545
// This corresponds to something like
547546
//
548547
// ```
549548
// let A::<'a>(_): A<'static> = ...;
550549
// ```
551-
let subpattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span);
552-
self.visit_bindings(subpattern, &subpattern_user_ty, f)
550+
let annotation = (user_ty_span, user_ty.base);
551+
let projection = UserTypeProjection {
552+
base: self.canonical_user_type_annotations.push(annotation),
553+
projs: user_ty.projs.clone(),
554+
};
555+
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
556+
self.visit_bindings(subpattern, subpattern_user_ty, f)
553557
}
554558

555559
PatternKind::Leaf { ref subpatterns } => {
556560
for subpattern in subpatterns {
557-
let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field);
561+
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
558562
debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
559-
self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f);
563+
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
560564
}
561565
}
562566

563567
PatternKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => {
564568
for subpattern in subpatterns {
565-
let subpattern_user_ty = pattern_user_ty.variant(
569+
let subpattern_user_ty = pattern_user_ty.clone().variant(
566570
adt_def, variant_index, subpattern.field);
567-
self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f);
571+
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
568572
}
569573
}
570574
}
@@ -1465,7 +1469,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14651469
num_patterns: usize,
14661470
var_id: NodeId,
14671471
var_ty: Ty<'tcx>,
1468-
user_var_ty: &PatternTypeProjections<'tcx>,
1472+
user_ty: UserTypeProjections<'tcx>,
14691473
has_guard: ArmHasGuard,
14701474
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
14711475
pat_span: Span,
@@ -1481,7 +1485,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
14811485
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
14821486
BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
14831487
};
1484-
let user_ty = user_var_ty.clone().user_ty(&mut self.canonical_user_type_annotations);
14851488
debug!("declare_binding: user_ty={:?}", user_ty);
14861489
let local = LocalDecl::<'tcx> {
14871490
mutability,

src/librustc_mir/hair/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ mod constant;
2121

2222
pub mod pattern;
2323
pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern};
24-
pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
24+
pub(crate) use self::pattern::PatternTypeProjection;
2525

2626
mod util;
2727

src/librustc_mir/hair/pattern/mod.rs

+2-95
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use hair::util::UserAnnotatedTyHelpers;
1212
use hair::constant::*;
1313

1414
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
15-
use rustc::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections};
15+
use rustc::mir::{ProjectionElem, UserTypeProjection};
1616
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
1717
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
1818
use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation};
@@ -58,105 +58,13 @@ pub struct Pattern<'tcx> {
5858
}
5959

6060

61-
#[derive(Clone, Debug)]
62-
pub(crate) struct PatternTypeProjections<'tcx> {
63-
contents: Vec<(PatternTypeProjection<'tcx>, Span)>,
64-
}
65-
66-
impl<'tcx> PatternTypeProjections<'tcx> {
67-
pub(crate) fn user_ty(
68-
self,
69-
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
70-
) -> UserTypeProjections<'tcx> {
71-
UserTypeProjections::from_projections(
72-
self.contents
73-
.into_iter()
74-
.map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(annotations, span), span))
75-
)
76-
}
77-
78-
pub(crate) fn none() -> Self {
79-
PatternTypeProjections { contents: vec![] }
80-
}
81-
82-
fn map_projs(&self,
83-
mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>)
84-
-> Self
85-
{
86-
PatternTypeProjections {
87-
contents: self.contents
88-
.iter()
89-
.map(|(proj, span)| (f(proj), *span))
90-
.collect(), }
91-
}
92-
93-
pub(crate) fn index(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.index()) }
94-
95-
pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
96-
self.map_projs(|pat_ty_proj| pat_ty_proj.subslice(from, to))
97-
}
98-
99-
pub(crate) fn deref(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.deref()) }
100-
101-
pub(crate) fn leaf(&self, field: Field) -> Self {
102-
self.map_projs(|pat_ty_proj| pat_ty_proj.leaf(field))
103-
}
104-
105-
pub(crate) fn variant(&self,
106-
adt_def: &'tcx AdtDef,
107-
variant_index: VariantIdx,
108-
field: Field) -> Self {
109-
self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
110-
}
111-
112-
pub(crate) fn add_user_type(&self, user_ty: &PatternTypeProjection<'tcx>, sp: Span) -> Self {
113-
let mut new = self.clone();
114-
new.contents.push((user_ty.clone(), sp));
115-
new
116-
}
117-
}
118-
11961
#[derive(Clone, Debug)]
12062
pub struct PatternTypeProjection<'tcx> {
12163
pub base: CanonicalUserTypeAnnotation<'tcx>,
12264
pub projs: Vec<ProjectionElem<'tcx, (), ()>>,
12365
}
12466

12567
impl<'tcx> PatternTypeProjection<'tcx> {
126-
pub(crate) fn index(&self) -> Self {
127-
let mut new = self.clone();
128-
new.projs.push(ProjectionElem::Index(()));
129-
new
130-
}
131-
132-
pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
133-
let mut new = self.clone();
134-
new.projs.push(ProjectionElem::Subslice { from, to });
135-
new
136-
}
137-
138-
pub(crate) fn deref(&self) -> Self {
139-
let mut new = self.clone();
140-
new.projs.push(ProjectionElem::Deref);
141-
new
142-
}
143-
144-
pub(crate) fn leaf(&self, field: Field) -> Self {
145-
let mut new = self.clone();
146-
new.projs.push(ProjectionElem::Field(field, ()));
147-
new
148-
}
149-
150-
pub(crate) fn variant(&self,
151-
adt_def: &'tcx AdtDef,
152-
variant_index: VariantIdx,
153-
field: Field) -> Self {
154-
let mut new = self.clone();
155-
new.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
156-
new.projs.push(ProjectionElem::Field(field, ()));
157-
new
158-
}
159-
16068
pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self {
16169
Self {
16270
base: user_annotation,
@@ -169,9 +77,8 @@ impl<'tcx> PatternTypeProjection<'tcx> {
16977
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
17078
span: Span,
17179
) -> UserTypeProjection<'tcx> {
172-
let annotation_index = annotations.push((span, self.base));
17380
UserTypeProjection {
174-
base: annotation_index,
81+
base: annotations.push((span, self.base)),
17582
projs: self.projs
17683
}
17784
}

0 commit comments

Comments
 (0)