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.
This commit is contained in:
parent
28fd1b04e5
commit
0bfe184b1a
@ -2519,6 +2519,48 @@ impl<'tcx> UserTypeProjections<'tcx> {
|
||||
pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
|
||||
self.contents.iter().map(|&(ref user_type, _span)| user_type)
|
||||
}
|
||||
|
||||
pub fn push_projection(
|
||||
mut self,
|
||||
user_ty: &UserTypeProjection<'tcx>,
|
||||
span: Span,
|
||||
) -> Self {
|
||||
self.contents.push((user_ty.clone(), span));
|
||||
self
|
||||
}
|
||||
|
||||
fn map_projections(
|
||||
mut self,
|
||||
mut f: impl FnMut(UserTypeProjection<'tcx>) -> UserTypeProjection<'tcx>
|
||||
) -> Self {
|
||||
self.contents = self.contents.drain(..).map(|(proj, span)| (f(proj), span)).collect();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn index(self) -> Self {
|
||||
self.map_projections(|pat_ty_proj| pat_ty_proj.index())
|
||||
}
|
||||
|
||||
pub fn subslice(self, from: u32, to: u32) -> Self {
|
||||
self.map_projections(|pat_ty_proj| pat_ty_proj.subslice(from, to))
|
||||
}
|
||||
|
||||
pub fn deref(self) -> Self {
|
||||
self.map_projections(|pat_ty_proj| pat_ty_proj.deref())
|
||||
}
|
||||
|
||||
pub fn leaf(self, field: Field) -> Self {
|
||||
self.map_projections(|pat_ty_proj| pat_ty_proj.leaf(field))
|
||||
}
|
||||
|
||||
pub fn variant(
|
||||
self,
|
||||
adt_def: &'tcx AdtDef,
|
||||
variant_index: VariantIdx,
|
||||
field: Field,
|
||||
) -> Self {
|
||||
self.map_projections(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes the effect of a user-supplied type annotation on the
|
||||
@ -2544,6 +2586,39 @@ pub struct UserTypeProjection<'tcx> {
|
||||
|
||||
impl<'tcx> Copy for ProjectionKind<'tcx> { }
|
||||
|
||||
impl<'tcx> UserTypeProjection<'tcx> {
|
||||
pub(crate) fn index(mut self) -> Self {
|
||||
self.projs.push(ProjectionElem::Index(()));
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn subslice(mut self, from: u32, to: u32) -> Self {
|
||||
self.projs.push(ProjectionElem::Subslice { from, to });
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn deref(mut self) -> Self {
|
||||
self.projs.push(ProjectionElem::Deref);
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn leaf(mut self, field: Field) -> Self {
|
||||
self.projs.push(ProjectionElem::Field(field, ()));
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn variant(
|
||||
mut self,
|
||||
adt_def: &'tcx AdtDef,
|
||||
variant_index: VariantIdx,
|
||||
field: Field,
|
||||
) -> Self {
|
||||
self.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
|
||||
self.projs.push(ProjectionElem::Field(field, ()));
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
CloneTypeFoldableAndLiftImpls! { ProjectionKind<'tcx>, }
|
||||
|
||||
impl<'tcx> TypeFoldable<'tcx> for UserTypeProjection<'tcx> {
|
||||
|
@ -144,7 +144,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
debug!("ast_block_stmts: pattern={:?}", pattern);
|
||||
this.visit_bindings(
|
||||
&pattern,
|
||||
&PatternTypeProjections::none(),
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, _, _, _, node, span, _, _| {
|
||||
this.storage_live_binding(block, node, span, OutsideGuard);
|
||||
this.schedule_drop_for_binding(node, span, OutsideGuard);
|
||||
|
@ -8,7 +8,6 @@ use build::ForGuard::{self, OutsideGuard, RefWithinGuard, ValWithinGuard};
|
||||
use build::{BlockAnd, BlockAndExtension, Builder};
|
||||
use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
|
||||
use hair::*;
|
||||
use hair::pattern::PatternTypeProjections;
|
||||
use rustc::mir::*;
|
||||
use rustc::ty::{self, Ty};
|
||||
use rustc::ty::layout::VariantIdx;
|
||||
@ -412,7 +411,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
debug!("declare_bindings: patterns={:?}", patterns);
|
||||
self.visit_bindings(
|
||||
&patterns[0],
|
||||
&PatternTypeProjections::none(),
|
||||
UserTypeProjections::none(),
|
||||
&mut |this, mutability, name, mode, var, span, ty, user_ty| {
|
||||
if visibility_scope.is_none() {
|
||||
visibility_scope =
|
||||
@ -488,7 +487,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
pub(super) fn visit_bindings(
|
||||
&mut self,
|
||||
pattern: &Pattern<'tcx>,
|
||||
pattern_user_ty: &PatternTypeProjections<'tcx>,
|
||||
pattern_user_ty: UserTypeProjections<'tcx>,
|
||||
f: &mut impl FnMut(
|
||||
&mut Self,
|
||||
Mutability,
|
||||
@ -497,7 +496,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
NodeId,
|
||||
Span,
|
||||
Ty<'tcx>,
|
||||
&PatternTypeProjections<'tcx>,
|
||||
UserTypeProjections<'tcx>,
|
||||
),
|
||||
) {
|
||||
debug!("visit_bindings: pattern={:?} pattern_user_ty={:?}", pattern, pattern_user_ty);
|
||||
@ -511,7 +510,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
ref subpattern,
|
||||
..
|
||||
} => {
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
|
||||
f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty.clone());
|
||||
if let Some(subpattern) = subpattern.as_ref() {
|
||||
self.visit_bindings(subpattern, pattern_user_ty, f);
|
||||
}
|
||||
@ -529,18 +528,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
let from = u32::try_from(prefix.len()).unwrap();
|
||||
let to = u32::try_from(suffix.len()).unwrap();
|
||||
for subpattern in prefix {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
|
||||
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
|
||||
}
|
||||
for subpattern in slice {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.subslice(from, to), f);
|
||||
self.visit_bindings(subpattern, pattern_user_ty.clone().subslice(from, to), f);
|
||||
}
|
||||
for subpattern in suffix {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
|
||||
self.visit_bindings(subpattern, pattern_user_ty.clone().index(), f);
|
||||
}
|
||||
}
|
||||
PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
|
||||
PatternKind::Deref { ref subpattern } => {
|
||||
self.visit_bindings(subpattern, &pattern_user_ty.deref(), f);
|
||||
self.visit_bindings(subpattern, pattern_user_ty.deref(), f);
|
||||
}
|
||||
PatternKind::AscribeUserType { ref subpattern, ref user_ty, user_ty_span } => {
|
||||
// This corresponds to something like
|
||||
@ -548,23 +547,28 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
// ```
|
||||
// let A::<'a>(_): A<'static> = ...;
|
||||
// ```
|
||||
let subpattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span);
|
||||
self.visit_bindings(subpattern, &subpattern_user_ty, f)
|
||||
let annotation = (user_ty_span, user_ty.base);
|
||||
let projection = UserTypeProjection {
|
||||
base: self.canonical_user_type_annotations.push(annotation),
|
||||
projs: user_ty.projs.clone(),
|
||||
};
|
||||
let subpattern_user_ty = pattern_user_ty.push_projection(&projection, user_ty_span);
|
||||
self.visit_bindings(subpattern, subpattern_user_ty, f)
|
||||
}
|
||||
|
||||
PatternKind::Leaf { ref subpatterns } => {
|
||||
for subpattern in subpatterns {
|
||||
let subpattern_user_ty = pattern_user_ty.leaf(subpattern.field);
|
||||
let subpattern_user_ty = pattern_user_ty.clone().leaf(subpattern.field);
|
||||
debug!("visit_bindings: subpattern_user_ty={:?}", subpattern_user_ty);
|
||||
self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f);
|
||||
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
|
||||
}
|
||||
}
|
||||
|
||||
PatternKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => {
|
||||
for subpattern in subpatterns {
|
||||
let subpattern_user_ty = pattern_user_ty.variant(
|
||||
let subpattern_user_ty = pattern_user_ty.clone().variant(
|
||||
adt_def, variant_index, subpattern.field);
|
||||
self.visit_bindings(&subpattern.pattern, &subpattern_user_ty, f);
|
||||
self.visit_bindings(&subpattern.pattern, subpattern_user_ty, f);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1465,7 +1469,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
num_patterns: usize,
|
||||
var_id: NodeId,
|
||||
var_ty: Ty<'tcx>,
|
||||
user_var_ty: &PatternTypeProjections<'tcx>,
|
||||
user_ty: UserTypeProjections<'tcx>,
|
||||
has_guard: ArmHasGuard,
|
||||
opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
|
||||
pat_span: Span,
|
||||
@ -1481,7 +1485,6 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
BindingMode::ByValue => ty::BindingMode::BindByValue(mutability.into()),
|
||||
BindingMode::ByRef { .. } => ty::BindingMode::BindByReference(mutability.into()),
|
||||
};
|
||||
let user_ty = user_var_ty.clone().user_ty(&mut self.canonical_user_type_annotations);
|
||||
debug!("declare_binding: user_ty={:?}", user_ty);
|
||||
let local = LocalDecl::<'tcx> {
|
||||
mutability,
|
||||
|
@ -21,7 +21,7 @@ mod constant;
|
||||
|
||||
pub mod pattern;
|
||||
pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternRange, FieldPattern};
|
||||
pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
|
||||
pub(crate) use self::pattern::PatternTypeProjection;
|
||||
|
||||
mod util;
|
||||
|
||||
|
@ -12,7 +12,7 @@ use hair::util::UserAnnotatedTyHelpers;
|
||||
use hair::constant::*;
|
||||
|
||||
use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
|
||||
use rustc::mir::{ProjectionElem, UserTypeProjection, UserTypeProjections};
|
||||
use rustc::mir::{ProjectionElem, UserTypeProjection};
|
||||
use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
|
||||
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty, Lift};
|
||||
use rustc::ty::{CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, UserTypeAnnotation};
|
||||
@ -58,64 +58,6 @@ pub struct Pattern<'tcx> {
|
||||
}
|
||||
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct PatternTypeProjections<'tcx> {
|
||||
contents: Vec<(PatternTypeProjection<'tcx>, Span)>,
|
||||
}
|
||||
|
||||
impl<'tcx> PatternTypeProjections<'tcx> {
|
||||
pub(crate) fn user_ty(
|
||||
self,
|
||||
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
||||
) -> UserTypeProjections<'tcx> {
|
||||
UserTypeProjections::from_projections(
|
||||
self.contents
|
||||
.into_iter()
|
||||
.map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(annotations, span), span))
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn none() -> Self {
|
||||
PatternTypeProjections { contents: vec![] }
|
||||
}
|
||||
|
||||
fn map_projs(&self,
|
||||
mut f: impl FnMut(&PatternTypeProjection<'tcx>) -> PatternTypeProjection<'tcx>)
|
||||
-> Self
|
||||
{
|
||||
PatternTypeProjections {
|
||||
contents: self.contents
|
||||
.iter()
|
||||
.map(|(proj, span)| (f(proj), *span))
|
||||
.collect(), }
|
||||
}
|
||||
|
||||
pub(crate) fn index(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.index()) }
|
||||
|
||||
pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
|
||||
self.map_projs(|pat_ty_proj| pat_ty_proj.subslice(from, to))
|
||||
}
|
||||
|
||||
pub(crate) fn deref(&self) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.deref()) }
|
||||
|
||||
pub(crate) fn leaf(&self, field: Field) -> Self {
|
||||
self.map_projs(|pat_ty_proj| pat_ty_proj.leaf(field))
|
||||
}
|
||||
|
||||
pub(crate) fn variant(&self,
|
||||
adt_def: &'tcx AdtDef,
|
||||
variant_index: VariantIdx,
|
||||
field: Field) -> Self {
|
||||
self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field))
|
||||
}
|
||||
|
||||
pub(crate) fn add_user_type(&self, user_ty: &PatternTypeProjection<'tcx>, sp: Span) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.contents.push((user_ty.clone(), sp));
|
||||
new
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PatternTypeProjection<'tcx> {
|
||||
pub base: CanonicalUserTypeAnnotation<'tcx>,
|
||||
@ -123,40 +65,6 @@ pub struct PatternTypeProjection<'tcx> {
|
||||
}
|
||||
|
||||
impl<'tcx> PatternTypeProjection<'tcx> {
|
||||
pub(crate) fn index(&self) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.projs.push(ProjectionElem::Index(()));
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn subslice(&self, from: u32, to: u32) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.projs.push(ProjectionElem::Subslice { from, to });
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn deref(&self) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.projs.push(ProjectionElem::Deref);
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn leaf(&self, field: Field) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.projs.push(ProjectionElem::Field(field, ()));
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn variant(&self,
|
||||
adt_def: &'tcx AdtDef,
|
||||
variant_index: VariantIdx,
|
||||
field: Field) -> Self {
|
||||
let mut new = self.clone();
|
||||
new.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
|
||||
new.projs.push(ProjectionElem::Field(field, ()));
|
||||
new
|
||||
}
|
||||
|
||||
pub(crate) fn from_user_type(user_annotation: CanonicalUserTypeAnnotation<'tcx>) -> Self {
|
||||
Self {
|
||||
base: user_annotation,
|
||||
@ -169,9 +77,8 @@ impl<'tcx> PatternTypeProjection<'tcx> {
|
||||
annotations: &mut CanonicalUserTypeAnnotations<'tcx>,
|
||||
span: Span,
|
||||
) -> UserTypeProjection<'tcx> {
|
||||
let annotation_index = annotations.push((span, self.base));
|
||||
UserTypeProjection {
|
||||
base: annotation_index,
|
||||
base: annotations.push((span, self.base)),
|
||||
projs: self.projs
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user