about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/ich/impls_mir.rs1
-rw-r--r--src/librustc/mir/mod.rs42
-rw-r--r--src/librustc/mir/visit.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs12
-rw-r--r--src/librustc_mir/build/block.rs11
-rw-r--r--src/librustc_mir/build/expr/into.rs2
-rw-r--r--src/librustc_mir/build/matches/mod.rs66
-rw-r--r--src/librustc_mir/build/mod.rs2
-rw-r--r--src/librustc_mir/hair/mod.rs3
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs50
-rw-r--r--src/librustc_mir/shim.rs2
-rw-r--r--src/librustc_mir/transform/generator.rs6
-rw-r--r--src/librustc_mir/util/pretty.rs2
13 files changed, 148 insertions, 53 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 94b85247bb8..724481da681 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -608,3 +608,4 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<
 }
 
 impl_stable_hash_for!(struct mir::UserTypeProjection<'tcx> { base });
+impl_stable_hash_for!(struct mir::UserTypeProjections<'tcx> { contents });
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index d2f67a74420..f96c3b432d6 100644
--- a/src/librustc/mir/mod.rs
+++ b/src/librustc/mir/mod.rs
@@ -710,7 +710,7 @@ pub struct LocalDecl<'tcx> {
     /// e.g. via `let x: T`, then we carry that type here. The MIR
     /// borrow checker needs this information since it can affect
     /// region inference.
-    pub user_ty: Option<(UserTypeProjection<'tcx>, Span)>,
+    pub user_ty: UserTypeProjections<'tcx>,
 
     /// Name of the local, used in debuginfo and pretty-printing.
     ///
@@ -882,7 +882,7 @@ impl<'tcx> LocalDecl<'tcx> {
         LocalDecl {
             mutability,
             ty,
-            user_ty: None,
+            user_ty: UserTypeProjections::none(),
             name: None,
             source_info: SourceInfo {
                 span,
@@ -903,7 +903,7 @@ impl<'tcx> LocalDecl<'tcx> {
         LocalDecl {
             mutability: Mutability::Mut,
             ty: return_ty,
-            user_ty: None,
+            user_ty: UserTypeProjections::none(),
             source_info: SourceInfo {
                 span,
                 scope: OUTERMOST_SOURCE_SCOPE,
@@ -2449,6 +2449,42 @@ EnumLiftImpl! {
     }
 }
 
+/// A collection of projections into user types.
+///
+/// They are projections because a binding can occur a part of a
+/// parent pattern that has been ascribed a type.
+///
+/// Its a collection because there can be multiple type ascriptions on
+/// the path from the root of the pattern down to the binding itself.
+#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub struct UserTypeProjections<'tcx> {
+    pub(crate) contents: Vec<(UserTypeProjection<'tcx>, Span)>,
+}
+
+BraceStructTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for UserTypeProjections<'tcx> {
+        contents
+    }
+}
+
+impl<'tcx> UserTypeProjections<'tcx> {
+    pub fn none() -> Self {
+        UserTypeProjections { contents: vec![] }
+    }
+
+    pub fn from_projections(projs: impl Iterator<Item=(UserTypeProjection<'tcx>, Span)>) -> Self {
+        UserTypeProjections { contents: projs.collect() }
+    }
+
+    pub fn projections_and_spans(&self) -> impl Iterator<Item=&(UserTypeProjection<'tcx>, Span)> {
+        self.contents.iter()
+    }
+
+    pub fn projections(&self) -> impl Iterator<Item=&UserTypeProjection<'tcx>> {
+        self.contents.iter().map(|&(ref user_type, _span)| user_type)
+    }
+}
+
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct UserTypeProjection<'tcx> {
     pub base: UserTypeAnnotation<'tcx>,
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index acca7ddcd3f..61eb565fb9a 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -743,7 +743,7 @@ macro_rules! make_mir_visitor {
                     local,
                     source_info: *source_info,
                 });
-                if let Some((user_ty, _)) = user_ty {
+                for (user_ty, _) in & $($mutability)* user_ty.contents {
                     self.visit_user_type_projection(user_ty);
                 }
                 self.visit_source_info(source_info);
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index 708f2f3ad33..828907ddc63 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -284,7 +284,7 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
             if let Err(terr) = self.cx.relate_type_and_user_type(
                 constant.ty,
                 ty::Variance::Invariant,
-                UserTypeProjection { base: user_ty },
+                &UserTypeProjection { base: user_ty },
                 location.to_locations(),
                 ConstraintCategory::Boring,
             ) {
@@ -310,12 +310,12 @@ impl<'a, 'b, 'gcx, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         self.super_local_decl(local, local_decl);
         self.sanitize_type(local_decl, local_decl.ty);
 
-        if let Some((user_ty, span)) = local_decl.user_ty {
+        for (user_ty, span) in local_decl.user_ty.projections_and_spans() {
             if let Err(terr) = self.cx.relate_type_and_user_type(
                 local_decl.ty,
                 ty::Variance::Invariant,
                 user_ty,
-                Locations::All(span),
+                Locations::All(*span),
                 ConstraintCategory::TypeAnnotation,
             ) {
                 span_mirbug!(
@@ -971,7 +971,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         a: Ty<'tcx>,
         v: ty::Variance,
-        user_ty: UserTypeProjection<'tcx>,
+        user_ty: &UserTypeProjection<'tcx>,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
@@ -1173,7 +1173,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     if let Err(terr) = self.relate_type_and_user_type(
                         rv_ty,
                         ty::Variance::Invariant,
-                        UserTypeProjection { base: user_ty },
+                        &UserTypeProjection { base: user_ty },
                         location.to_locations(),
                         ConstraintCategory::Boring,
                     ) {
@@ -1226,7 +1226,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
                     );
                 };
             }
-            StatementKind::AscribeUserType(ref place, variance, box c_ty) => {
+            StatementKind::AscribeUserType(ref place, variance, box ref c_ty) => {
                 let place_ty = place.ty(mir, tcx).to_ty(tcx);
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index b754d63f718..aa383a123b6 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -151,10 +151,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                             None, remainder_span, lint_level, slice::from_ref(&pattern),
                             ArmHasGuard(false), None);
 
-                        this.visit_bindings(&pattern, None, &mut |this, _, _, _, node, span, _, _| {
-                            this.storage_live_binding(block, node, span, OutsideGuard);
-                            this.schedule_drop_for_binding(node, span, OutsideGuard);
-                        })
+                        this.visit_bindings(
+                            &pattern,
+                            &PatternTypeProjections::none(),
+                            &mut |this, _, _, _, node, span, _, _| {
+                                this.storage_live_binding(block, node, span, OutsideGuard);
+                                this.schedule_drop_for_binding(node, span, OutsideGuard);
+                            })
                     }
 
                     // Enter the source scope, after evaluating the initializer.
diff --git a/src/librustc_mir/build/expr/into.rs b/src/librustc_mir/build/expr/into.rs
index 4f5ed34a461..d2913872fca 100644
--- a/src/librustc_mir/build/expr/into.rs
+++ b/src/librustc_mir/build/expr/into.rs
@@ -306,7 +306,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                     let ptr_temp = this.local_decls.push(LocalDecl {
                         mutability: Mutability::Mut,
                         ty: ptr_ty,
-                        user_ty: None,
+                        user_ty: UserTypeProjections::none(),
                         name: None,
                         source_info,
                         visibility_scope: source_info.scope,
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 9bfb6d4e6de..5479ccb2d84 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -18,6 +18,7 @@ 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::hir;
 use rustc::mir::*;
 use rustc::ty::{self, Ty};
@@ -415,7 +416,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let num_patterns = patterns.len();
         self.visit_bindings(
             &patterns[0],
-            None,
+            &PatternTypeProjections::none(),
             &mut |this, mutability, name, mode, var, span, ty, user_ty| {
                 if visibility_scope.is_none() {
                     visibility_scope =
@@ -491,7 +492,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub(super) fn visit_bindings(
         &mut self,
         pattern: &Pattern<'tcx>,
-        mut pattern_user_ty: Option<(PatternTypeProjection<'tcx>, Span)>,
+        pattern_user_ty: &PatternTypeProjections<'tcx>,
         f: &mut impl FnMut(
             &mut Self,
             Mutability,
@@ -500,7 +501,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             NodeId,
             Span,
             Ty<'tcx>,
-            Option<(PatternTypeProjection<'tcx>, Span)>,
+            &PatternTypeProjections<'tcx>,
         ),
     ) {
         match *pattern.kind {
@@ -513,20 +514,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 ref subpattern,
                 ..
             } => {
-                match mode {
-                    BindingMode::ByValue => { }
+                let pattern_ref_binding; // sidestep temp lifetime limitations.
+                let binding_user_ty = match mode {
+                    BindingMode::ByValue => { pattern_user_ty }
                     BindingMode::ByRef(..) => {
                         // If this is a `ref` binding (e.g., `let ref
                         // x: T = ..`), then the type of `x` is not
-                        // `T` but rather `&T`, so ignore
-                        // `pattern_user_ty` for now.
-                        //
-                        // FIXME(#47184): extract or handle `pattern_user_ty` somehow
-                        pattern_user_ty = None;
+                        // `T` but rather `&T`.
+                        pattern_ref_binding = pattern_user_ty.ref_binding();
+                        &pattern_ref_binding
                     }
-                }
+                };
 
-                f(self, mutability, name, mode, var, pattern.span, ty, pattern_user_ty);
+                f(self, mutability, name, mode, var, pattern.span, ty, binding_user_ty);
                 if let Some(subpattern) = subpattern.as_ref() {
                     self.visit_bindings(subpattern, pattern_user_ty, f);
                 }
@@ -541,15 +541,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 ref slice,
                 ref suffix,
             } => {
-                // FIXME(#47184): extract or handle `pattern_user_ty` somehow
-                for subpattern in prefix.iter().chain(slice).chain(suffix) {
-                    self.visit_bindings(subpattern, None, f);
+                for subpattern in prefix {
+                    self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
+                }
+                for subpattern in slice {
+                    self.visit_bindings(subpattern, &pattern_user_ty.subslice(), f);
+                }
+                for subpattern in suffix {
+                    self.visit_bindings(subpattern, &pattern_user_ty.index(), f);
                 }
             }
             PatternKind::Constant { .. } | PatternKind::Range { .. } | PatternKind::Wild => {}
             PatternKind::Deref { ref subpattern } => {
-                // FIXME(#47184): extract or handle `pattern_user_ty` somehow
-                self.visit_bindings(subpattern, None, f);
+                self.visit_bindings(subpattern, &pattern_user_ty.deref(), f);
             }
             PatternKind::AscribeUserType { ref subpattern, user_ty, user_ty_span } => {
                 // This corresponds to something like
@@ -557,17 +561,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // ```
                 // let A::<'a>(_): A<'static> = ...;
                 // ```
-                //
-                // FIXME(#47184): handle `pattern_user_ty` somehow
-                self.visit_bindings(subpattern, Some((user_ty, user_ty_span)), f)
+                let pattern_user_ty = pattern_user_ty.add_user_type(user_ty, user_ty_span);
+                self.visit_bindings(subpattern, &pattern_user_ty, f)
             }
-            PatternKind::Leaf { ref subpatterns }
-            | PatternKind::Variant {
-                ref subpatterns, ..
-            } => {
-                // FIXME(#47184): extract or handle `pattern_user_ty` somehow
-                for subpattern in subpatterns {
-                    self.visit_bindings(&subpattern.pattern, None, f);
+
+            PatternKind::Leaf { ref subpatterns } => {
+                for (j, subpattern) in subpatterns.iter().enumerate() {
+                    self.visit_bindings(&subpattern.pattern, &pattern_user_ty.leaf(j), f);
+                }
+            }
+
+            PatternKind::Variant { ref subpatterns, .. } => {
+                for (j, subpattern) in subpatterns.iter().enumerate() {
+                    self.visit_bindings(&subpattern.pattern, &pattern_user_ty.variant(j), f);
                 }
             }
         }
@@ -1470,7 +1476,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         num_patterns: usize,
         var_id: NodeId,
         var_ty: Ty<'tcx>,
-        user_var_ty: Option<(PatternTypeProjection<'tcx>, Span)>,
+        user_var_ty: &PatternTypeProjections<'tcx>,
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
@@ -1489,7 +1495,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let local = LocalDecl::<'tcx> {
             mutability,
             ty: var_ty,
-            user_ty: user_var_ty.map(|(ut, sp)| (ut.user_ty(), sp)),
+            user_ty: user_var_ty.clone().user_ty(),
             name: Some(name),
             source_info,
             visibility_scope,
@@ -1522,7 +1528,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
                 // See previous comment.
                 mutability: Mutability::Not,
                 ty: tcx.mk_imm_ref(tcx.types.re_empty, var_ty),
-                user_ty: None,
+                user_ty: UserTypeProjections::none(),
                 name: Some(name),
                 source_info,
                 visibility_scope,
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 6ea4628de24..5b4001f0652 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -845,7 +845,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             self.local_decls.push(LocalDecl {
                 mutability: Mutability::Mut,
                 ty,
-                user_ty: None,
+                user_ty: UserTypeProjections::none(),
                 source_info,
                 visibility_scope: source_info.scope,
                 name,
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 888c14194c6..8a24851de81 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -27,7 +27,8 @@ use self::cx::Cx;
 pub mod cx;
 
 pub mod pattern;
-pub use self::pattern::{BindingMode, Pattern, PatternKind, PatternTypeProjection, FieldPattern};
+pub use self::pattern::{BindingMode, Pattern, PatternKind, FieldPattern};
+pub(crate) use self::pattern::{PatternTypeProjection, PatternTypeProjections};
 
 mod util;
 
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 57b2638cc8d..7a04c6e39df 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -21,7 +21,7 @@ use const_eval::{const_field, const_variant_index};
 use hair::util::UserAnnotatedTyHelpers;
 
 use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
-use rustc::mir::{UserTypeAnnotation, UserTypeProjection};
+use rustc::mir::{UserTypeAnnotation, UserTypeProjection, UserTypeProjections};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
 use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
 use rustc::ty::subst::{Substs, Kind};
@@ -65,6 +65,54 @@ pub struct Pattern<'tcx> {
     pub kind: Box<PatternKind<'tcx>>,
 }
 
+
+#[derive(Clone, Debug)]
+pub(crate) struct PatternTypeProjections<'tcx> {
+    contents: Vec<(PatternTypeProjection<'tcx>, Span)>,
+}
+
+impl<'tcx> PatternTypeProjections<'tcx> {
+    pub(crate) fn user_ty(self) -> UserTypeProjections<'tcx> {
+        UserTypeProjections::from_projections(
+            self.contents.into_iter().map(|(pat_ty_proj, span)| (pat_ty_proj.user_ty(), span)))
+    }
+
+    pub(crate) fn none() -> Self {
+        PatternTypeProjections { contents: vec![] }
+    }
+
+    pub(crate) fn ref_binding(&self) -> Self {
+        // FIXME(#47184): ignore for now
+        PatternTypeProjections { contents: vec![] }
+    }
+
+    pub(crate) fn index(&self) -> Self {
+        unimplemented!()
+    }
+
+    pub(crate) fn subslice(&self) -> Self {
+        unimplemented!()
+    }
+
+    pub(crate) fn deref(&self) -> Self {
+        unimplemented!()
+    }
+
+    pub(crate) fn add_user_type(&self, user_ty: PatternTypeProjection<'tcx>, sp: Span) -> Self {
+        let mut new = self.clone();
+        new.contents.push((user_ty, sp));
+        new
+    }
+
+    pub(crate) fn leaf(&self, _index: usize) -> Self {
+        unimplemented!()
+    }
+
+    pub(crate) fn variant(&self, _index: usize) -> Self {
+        unimplemented!()
+    }
+}
+
 #[derive(Copy, Clone, Debug)]
 pub struct PatternTypeProjection<'tcx>(UserTypeProjection<'tcx>);
 
diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs
index d8f627fcf4d..6c32690cdb3 100644
--- a/src/librustc_mir/shim.rs
+++ b/src/librustc_mir/shim.rs
@@ -142,7 +142,7 @@ fn temp_decl(mutability: Mutability, ty: Ty, span: Span) -> LocalDecl {
     LocalDecl {
         mutability,
         ty,
-        user_ty: None,
+        user_ty: UserTypeProjections::none(),
         name: None,
         source_info,
         visibility_scope: source_info.scope,
diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs
index c2ae6832cc0..5889fabee9d 100644
--- a/src/librustc_mir/transform/generator.rs
+++ b/src/librustc_mir/transform/generator.rs
@@ -303,7 +303,7 @@ fn replace_result_variable<'tcx>(
     let new_ret = LocalDecl {
         mutability: Mutability::Mut,
         ty: ret_ty,
-        user_ty: None,
+        user_ty: UserTypeProjections::none(),
         name: None,
         source_info,
         visibility_scope: source_info.scope,
@@ -658,7 +658,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
     mir.local_decls[RETURN_PLACE] = LocalDecl {
         mutability: Mutability::Mut,
         ty: tcx.mk_unit(),
-        user_ty: None,
+        user_ty: UserTypeProjections::none(),
         name: None,
         source_info,
         visibility_scope: source_info.scope,
@@ -676,7 +676,7 @@ fn create_generator_drop_shim<'a, 'tcx>(
             ty: gen_ty,
             mutbl: hir::Mutability::MutMutable,
         }),
-        user_ty: None,
+        user_ty: UserTypeProjections::none(),
         name: None,
         source_info,
         visibility_scope: source_info.scope,
diff --git a/src/librustc_mir/util/pretty.rs b/src/librustc_mir/util/pretty.rs
index 25bd02ff6dc..c74492fe649 100644
--- a/src/librustc_mir/util/pretty.rs
+++ b/src/librustc_mir/util/pretty.rs
@@ -502,7 +502,7 @@ fn write_scope_tree(
                 local,
                 var.ty
             );
-            if let Some(user_ty) = var.user_ty {
+            for user_ty in var.user_ty.projections() {
                 write!(indented_var, " as {:?}", user_ty).unwrap();
             }
             indented_var.push_str(";");