about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-10-10 17:07:10 -0400
committerNiko Matsakis <niko@alum.mit.edu>2018-10-15 16:24:46 -0400
commitaed6e4a0834d11cad0bf5e1ebe065eabff1f405c (patch)
tree25f4d86f919813d744870bf7e60c97d9ce37fddb
parente339e84fffb3156aaa78fbf686436de02ba4cf48 (diff)
downloadrust-aed6e4a0834d11cad0bf5e1ebe065eabff1f405c.tar.gz
rust-aed6e4a0834d11cad0bf5e1ebe065eabff1f405c.zip
introduce a `UserTypeAnnotation` enum
-rw-r--r--src/librustc/ich/impls_mir.rs13
-rw-r--r--src/librustc/mir/mod.rs24
-rw-r--r--src/librustc/mir/visit.rs22
-rw-r--r--src/librustc_mir/borrow_check/nll/constraint_generation.rs5
-rw-r--r--src/librustc_mir/borrow_check/nll/renumber.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs6
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs19
-rw-r--r--src/librustc_mir/build/matches/mod.rs10
-rw-r--r--src/librustc_mir/hair/cx/block.rs4
-rw-r--r--src/librustc_mir/hair/cx/expr.rs27
-rw-r--r--src/librustc_mir/hair/mod.rs18
-rw-r--r--src/librustc_mir/hair/pattern/mod.rs8
-rw-r--r--src/librustc_mir/hair/util.rs48
13 files changed, 126 insertions, 88 deletions
diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs
index 337cc0fc627..38a298d81dd 100644
--- a/src/librustc/ich/impls_mir.rs
+++ b/src/librustc/ich/impls_mir.rs
@@ -587,3 +587,16 @@ impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::ClosureOutlivesSubj
 }
 
 impl_stable_hash_for!(struct mir::interpret::GlobalId<'tcx> { instance, promoted });
+
+impl<'a, 'gcx> HashStable<StableHashingContext<'a>> for mir::UserTypeAnnotation<'gcx> {
+    fn hash_stable<W: StableHasherResult>(&self,
+                                          hcx: &mut StableHashingContext<'a>,
+                                          hasher: &mut StableHasher<W>) {
+        mem::discriminant(self).hash_stable(hcx, hasher);
+        match *self {
+            mir::UserTypeAnnotation::Ty(ref ty) => {
+                ty.hash_stable(hcx, hasher);
+            }
+        }
+    }
+}
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs
index 2587e19b1cb..eb4aa7ece49 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<(CanonicalTy<'tcx>, Span)>,
+    pub user_ty: Option<(UserTypeAnnotation<'tcx>, Span)>,
 
     /// Name of the local, used in debuginfo and pretty-printing.
     ///
@@ -1737,7 +1737,7 @@ pub enum StatementKind<'tcx> {
     /// - `Contravariant` -- requires that `T_y :> T`
     /// - `Invariant` -- requires that `T_y == T`
     /// - `Bivariant` -- no effect
-    AscribeUserType(Place<'tcx>, ty::Variance, CanonicalTy<'tcx>),
+    AscribeUserType(Place<'tcx>, ty::Variance, UserTypeAnnotation<'tcx>),
 
     /// No-op. Useful for deleting instructions without affecting statement indices.
     Nop,
@@ -2188,7 +2188,7 @@ pub enum AggregateKind<'tcx> {
         &'tcx AdtDef,
         usize,
         &'tcx Substs<'tcx>,
-        Option<CanonicalTy<'tcx>>,
+        Option<UserTypeAnnotation<'tcx>>,
         Option<usize>,
     ),
 
@@ -2392,7 +2392,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
 /// this does not necessarily mean that they are "==" in Rust -- in
 /// particular one must be wary of `NaN`!
 
-#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
 pub struct Constant<'tcx> {
     pub span: Span,
     pub ty: Ty<'tcx>,
@@ -2402,11 +2402,25 @@ pub struct Constant<'tcx> {
     /// indicate that `Vec<_>` was explicitly specified.
     ///
     /// Needed for NLL to impose user-given type constraints.
-    pub user_ty: Option<CanonicalTy<'tcx>>,
+    pub user_ty: Option<UserTypeAnnotation<'tcx>>,
 
     pub literal: &'tcx ty::Const<'tcx>,
 }
 
+/// A user-given type annotation attached to a constant.  These arise
+/// from constants that are named via paths, like `Foo::<A>::new` and
+/// so forth.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
+pub enum UserTypeAnnotation<'tcx> {
+    Ty(CanonicalTy<'tcx>),
+}
+
+EnumTypeFoldableImpl! {
+    impl<'tcx> TypeFoldable<'tcx> for UserTypeAnnotation<'tcx> {
+        (UserTypeAnnotation::Ty)(ty),
+    }
+}
+
 newtype_index! {
     pub struct Promoted {
         DEBUG_FORMAT = "promoted[{}]"
diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs
index 920dc88d6a8..3e92b1fd7ce 100644
--- a/src/librustc/mir/visit.rs
+++ b/src/librustc/mir/visit.rs
@@ -10,7 +10,7 @@
 
 use hir::def_id::DefId;
 use ty::subst::Substs;
-use ty::{CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty};
+use ty::{ClosureSubsts, GeneratorSubsts, Region, Ty};
 use mir::*;
 use syntax_pos::Span;
 
@@ -147,9 +147,9 @@ macro_rules! make_mir_visitor {
             fn visit_ascribe_user_ty(&mut self,
                                      place: & $($mutability)* Place<'tcx>,
                                      variance: & $($mutability)* ty::Variance,
-                                     c_ty: & $($mutability)* CanonicalTy<'tcx>,
+                                     user_ty: & $($mutability)* UserTypeAnnotation<'tcx>,
                                      location: Location) {
-                self.super_ascribe_user_ty(place, variance, c_ty, location);
+                self.super_ascribe_user_ty(place, variance, user_ty, location);
             }
 
             fn visit_place(&mut self,
@@ -214,8 +214,8 @@ macro_rules! make_mir_visitor {
                 self.super_ty(ty);
             }
 
-            fn visit_user_ty(&mut self, ty: & $($mutability)* CanonicalTy<'tcx>) {
-                self.super_canonical_ty(ty);
+            fn visit_user_type_annotation(&mut self, ty: & $($mutability)* UserTypeAnnotation<'tcx>) {
+                self.super_user_type_annotation(ty);
             }
 
             fn visit_region(&mut self,
@@ -390,9 +390,9 @@ macro_rules! make_mir_visitor {
                     StatementKind::AscribeUserType(
                         ref $($mutability)* place,
                         ref $($mutability)* variance,
-                        ref $($mutability)* c_ty,
+                        ref $($mutability)* user_ty,
                     ) => {
-                        self.visit_ascribe_user_ty(place, variance, c_ty, location);
+                        self.visit_ascribe_user_ty(place, variance, user_ty, location);
                     }
                     StatementKind::Nop => {}
                 }
@@ -637,10 +637,10 @@ macro_rules! make_mir_visitor {
             fn super_ascribe_user_ty(&mut self,
                                      place: & $($mutability)* Place<'tcx>,
                                      _variance: & $($mutability)* ty::Variance,
-                                     c_ty: & $($mutability)* CanonicalTy<'tcx>,
+                                     user_ty: & $($mutability)* UserTypeAnnotation<'tcx>,
                                      location: Location) {
                 self.visit_place(place, PlaceContext::Validate, location);
-                self.visit_user_ty(c_ty);
+                self.visit_user_type_annotation(user_ty);
             }
 
             fn super_place(&mut self,
@@ -736,7 +736,7 @@ macro_rules! make_mir_visitor {
                     source_info: *source_info,
                 });
                 if let Some((user_ty, _)) = user_ty {
-                    self.visit_user_ty(user_ty);
+                    self.visit_user_type_annotation(user_ty);
                 }
                 self.visit_source_info(source_info);
                 self.visit_source_scope(visibility_scope);
@@ -783,7 +783,7 @@ macro_rules! make_mir_visitor {
                 self.visit_source_scope(scope);
             }
 
-            fn super_canonical_ty(&mut self, _ty: & $($mutability)* CanonicalTy<'tcx>) {
+            fn super_user_type_annotation(&mut self, _ty: & $($mutability)* UserTypeAnnotation<'tcx>) {
             }
 
             fn super_ty(&mut self, _ty: & $($mutability)* Ty<'tcx>) {
diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
index 7e8e1b32d4d..30b263a923a 100644
--- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs
+++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs
@@ -18,9 +18,10 @@ use rustc::mir::visit::TyContext;
 use rustc::mir::visit::Visitor;
 use rustc::mir::{BasicBlock, BasicBlockData, Location, Mir, Place, Rvalue};
 use rustc::mir::{Statement, Terminator};
+use rustc::mir::UserTypeAnnotation;
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, RegionVid};
+use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid};
 
 pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>(
     infcx: &InferCtxt<'cx, 'gcx, 'tcx>,
@@ -179,7 +180,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx
         &mut self,
         _place: &Place<'tcx>,
         _variance: &ty::Variance,
-        _c_ty: &CanonicalTy<'tcx>,
+        _user_ty: &UserTypeAnnotation<'tcx>,
         _location: Location,
     ) {
     }
diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs
index 15a60badc93..363afb87ed9 100644
--- a/src/librustc_mir/borrow_check/nll/renumber.rs
+++ b/src/librustc_mir/borrow_check/nll/renumber.rs
@@ -9,8 +9,8 @@
 // except according to those terms.
 
 use rustc::ty::subst::Substs;
-use rustc::ty::{self, CanonicalTy, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
-use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind};
+use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable};
+use rustc::mir::{BasicBlock, Location, Mir, Statement, StatementKind, UserTypeAnnotation};
 use rustc::mir::visit::{MutVisitor, TyContext};
 use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 
@@ -65,12 +65,12 @@ impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
         debug!("visit_ty: ty={:?}", ty);
     }
 
-    fn visit_user_ty(&mut self, _ty: &mut CanonicalTy<'tcx>) {
-        // `user_ty` annotations represent the types that the user
+    fn visit_user_type_annotation(&mut self, _ty: &mut UserTypeAnnotation<'tcx>) {
+        // User type annotations represent the types that the user
         // wrote in the progarm. We don't want to erase the regions
         // from these types: rather, we want to add them as
         // constraints at type-check time.
-        debug!("visit_user_ty: skipping renumber");
+        debug!("visit_user_type_annotation: skipping renumber");
     }
 
     fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
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 e11f452e16b..1e79bc272e4 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -43,7 +43,7 @@ use rustc::traits::query::{Fallible, NoSolution};
 use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{Subst, UnpackedKind};
-use rustc::ty::{self, CanonicalTy, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
+use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
 use std::rc::Rc;
 use std::{fmt, iter};
 use syntax_pos::{Span, DUMMY_SP};
@@ -966,7 +966,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         &mut self,
         a: Ty<'tcx>,
         v: ty::Variance,
-        b: CanonicalTy<'tcx>,
+        b: UserTypeAnnotation<'tcx>,
         locations: Locations,
         category: ConstraintCategory,
     ) -> Fallible<()> {
@@ -1837,7 +1837,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
     /// If this rvalue supports a user-given type annotation, then
     /// extract and return it. This represents the final type of the
     /// rvalue and will be unified with the inferred type.
-    fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<CanonicalTy<'tcx>> {
+    fn rvalue_user_ty(&self, rvalue: &Rvalue<'tcx>) -> Option<UserTypeAnnotation<'tcx>> {
         match rvalue {
             Rvalue::Use(_)
             | Rvalue::Repeat(..)
diff --git a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
index 99e47663997..35d0b96b88a 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/relate_tys.rs
@@ -10,12 +10,12 @@
 
 use borrow_check::nll::constraints::OutlivesConstraint;
 use borrow_check::nll::type_check::{BorrowCheckContext, Locations};
-use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
 use rustc::infer::nll_relate::{TypeRelating, TypeRelatingDelegate};
-use rustc::mir::ConstraintCategory;
+use rustc::infer::{InferCtxt, NLLRegionVariableOrigin};
+use rustc::mir::{ConstraintCategory, UserTypeAnnotation};
 use rustc::traits::query::Fallible;
 use rustc::ty::relate::TypeRelation;
-use rustc::ty::{self, CanonicalTy, Ty};
+use rustc::ty::{self, Ty};
 use syntax_pos::DUMMY_SP;
 
 /// Adds sufficient constraints to ensure that `a <: b`.
@@ -61,20 +61,21 @@ pub(super) fn relate_type_and_user_type<'tcx>(
     infcx: &InferCtxt<'_, '_, 'tcx>,
     a: Ty<'tcx>,
     v: ty::Variance,
-    canonical_b: CanonicalTy<'tcx>,
+    user_ty: UserTypeAnnotation<'tcx>,
     locations: Locations,
     category: ConstraintCategory,
     borrowck_context: Option<&mut BorrowCheckContext<'_, 'tcx>>,
 ) -> Fallible<Ty<'tcx>> {
     debug!(
         "relate_type_and_user_type(a={:?}, v={:?}, b={:?}, locations={:?})",
-        a, v, canonical_b, locations
+        a, v, user_ty, locations
     );
 
-    let (b, _values) = infcx.instantiate_canonical_with_fresh_inference_vars(
-        DUMMY_SP,
-        &canonical_b,
-    );
+    let (b, _values) = match user_ty {
+        UserTypeAnnotation::Ty(canonical_ty) => {
+            infcx.instantiate_canonical_with_fresh_inference_vars(DUMMY_SP, &canonical_ty)
+        }
+    };
 
     // The `TypeRelating` code assumes that the "canonical variables"
     // appear in the "a" side, so flip `Contravariant` ambient
diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs
index 394fa4e077c..99c0a52a8ee 100644
--- a/src/librustc_mir/build/matches/mod.rs
+++ b/src/librustc_mir/build/matches/mod.rs
@@ -20,7 +20,7 @@ use build::{GuardFrame, GuardFrameLocal, LocalsForNode};
 use hair::*;
 use rustc::hir;
 use rustc::mir::*;
-use rustc::ty::{self, CanonicalTy, Ty};
+use rustc::ty::{self, Ty};
 use rustc_data_structures::bit_set::BitSet;
 use rustc_data_structures::fx::FxHashMap;
 use syntax::ast::{Name, NodeId};
@@ -491,7 +491,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     pub fn visit_bindings(
         &mut self,
         pattern: &Pattern<'tcx>,
-        mut pattern_user_ty: Option<(CanonicalTy<'tcx>, Span)>,
+        mut pattern_user_ty: Option<(UserTypeAnnotation<'tcx>, Span)>,
         f: &mut impl FnMut(
             &mut Self,
             Mutability,
@@ -500,7 +500,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             NodeId,
             Span,
             Ty<'tcx>,
-            Option<(CanonicalTy<'tcx>, Span)>,
+            Option<(UserTypeAnnotation<'tcx>, Span)>,
         ),
     ) {
         match *pattern.kind {
@@ -626,7 +626,7 @@ struct Binding<'tcx> {
 struct Ascription<'tcx> {
     span: Span,
     source: Place<'tcx>,
-    user_ty: CanonicalTy<'tcx>,
+    user_ty: UserTypeAnnotation<'tcx>,
 }
 
 #[derive(Clone, Debug)]
@@ -1470,7 +1470,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         num_patterns: usize,
         var_id: NodeId,
         var_ty: Ty<'tcx>,
-        user_var_ty: Option<(CanonicalTy<'tcx>, Span)>,
+        user_var_ty: Option<(UserTypeAnnotation<'tcx>, Span)>,
         has_guard: ArmHasGuard,
         opt_match_place: Option<(Option<Place<'tcx>>, Span)>,
         pat_span: Span,
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index 022c606a0f8..9865867a196 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -86,12 +86,12 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
                         let mut pattern = cx.pattern_from_hir(&local.pat);
 
                         if let Some(ty) = &local.ty {
-                            if let Some(user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) {
+                            if let Some(&user_ty) = cx.tables.user_provided_tys().get(ty.hir_id) {
                                 pattern = Pattern {
                                     ty: pattern.ty,
                                     span: pattern.span,
                                     kind: Box::new(PatternKind::AscribeUserType {
-                                        user_ty: *user_ty,
+                                        user_ty: UserTypeAnnotation::Ty(user_ty),
                                         user_ty_span: ty.span,
                                         subpattern: pattern
                                     })
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 813400422db..4dc43a533cf 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -296,11 +296,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
 
                     let user_ty = cx.tables().user_substs(fun.hir_id)
                         .map(|user_substs| {
-                            user_substs.unchecked_map(|user_substs| {
+                            UserTypeAnnotation::Ty(user_substs.unchecked_map(|user_substs| {
                                 // Here, we just pair an `AdtDef` with the
                                 // `user_substs`, so no new types etc are introduced.
                                 cx.tcx().mk_adt(adt_def, user_substs)
-                            })
+                            }))
                         });
 
                     let field_refs = args.iter()
@@ -725,9 +725,11 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
         }
         hir::ExprKind::Type(ref source, ref ty) => {
             let user_provided_tys = cx.tables.user_provided_tys();
-            let user_ty = *user_provided_tys
-                .get(ty.hir_id)
-                .expect(&format!("{:?} not found in user_provided_tys, source: {:?}", ty, source));
+            let user_ty = UserTypeAnnotation::Ty(
+                *user_provided_tys
+                    .get(ty.hir_id)
+                    .expect(&format!("{:?} not found in user_provided_tys, source: {:?}", ty, source))
+            );
             if source.is_place_expr() {
                 ExprKind::PlaceTypeAscription {
                     source: source.to_ref(),
@@ -763,7 +765,7 @@ fn user_substs_applied_to_def(
     cx: &mut Cx<'a, 'gcx, 'tcx>,
     hir_id: hir::HirId,
     def: &Def,
-) -> Option<CanonicalTy<'tcx>> {
+) -> Option<UserTypeAnnotation<'tcx>> {
     match def {
         // A reference to something callable -- e.g., a fn, method, or
         // a tuple-struct or tuple-variant. This has the type of a
@@ -772,11 +774,14 @@ fn user_substs_applied_to_def(
         Def::Method(_) |
         Def::StructCtor(_, CtorKind::Fn) |
         Def::VariantCtor(_, CtorKind::Fn) =>
-            Some(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
-                // Here, we just pair a `DefId` with the
-                // `user_substs`, so no new types etc are introduced.
-                cx.tcx().mk_fn_def(def.def_id(), user_substs)
-            })),
+            Some(
+                UserTypeAnnotation::Ty(cx.tables().user_substs(hir_id)?.unchecked_map(|user_substs| {
+                        // Here, we just pair a `DefId` with the
+                        // `user_substs`, so no new types etc are introduced.
+                        cx.tcx().mk_fn_def(def.def_id(), user_substs)
+                    }),
+                )
+            ),
 
         Def::Const(_def_id) |
         Def::AssociatedConst(_def_id) =>
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index e4f88e4fcc3..781b6c92aa1 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -14,11 +14,11 @@
 //! unit-tested and separated from the Rust source and compiler data
 //! structures.
 
-use rustc::mir::{BinOp, BorrowKind, Field, UnOp};
+use rustc::mir::{BinOp, BorrowKind, UserTypeAnnotation, Field, UnOp};
 use rustc::hir::def_id::DefId;
 use rustc::middle::region;
 use rustc::ty::subst::Substs;
-use rustc::ty::{AdtDef, CanonicalTy, UpvarSubsts, Region, Ty, Const};
+use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
 use rustc::hir;
 use syntax::ast;
 use syntax_pos::Span;
@@ -268,7 +268,7 @@ pub enum ExprKind<'tcx> {
 
         /// Optional user-given substs: for something like `let x =
         /// Bar::<T> { ... }`.
-        user_ty: Option<CanonicalTy<'tcx>>,
+        user_ty: Option<UserTypeAnnotation<'tcx>>,
 
         fields: Vec<FieldExprRef<'tcx>>,
         base: Option<FruInfo<'tcx>>
@@ -276,12 +276,12 @@ pub enum ExprKind<'tcx> {
     PlaceTypeAscription {
         source: ExprRef<'tcx>,
         /// Type that the user gave to this expression
-        user_ty: CanonicalTy<'tcx>,
+        user_ty: UserTypeAnnotation<'tcx>,
     },
     ValueTypeAscription {
         source: ExprRef<'tcx>,
         /// Type that the user gave to this expression
-        user_ty: CanonicalTy<'tcx>,
+        user_ty: UserTypeAnnotation<'tcx>,
     },
     Closure {
         closure_id: DefId,
@@ -291,13 +291,7 @@ pub enum ExprKind<'tcx> {
     },
     Literal {
         literal: &'tcx Const<'tcx>,
-
-        /// Optional user-given type: for something like
-        /// `collect::<Vec<_>>`, this would be present and would
-        /// indicate that `Vec<_>` was explicitly specified.
-        ///
-        /// Needed for NLL to impose user-given type constraints.
-        user_ty: Option<CanonicalTy<'tcx>>,
+        user_ty: Option<UserTypeAnnotation<'tcx>>,
     },
     InlineAsm {
         asm: &'tcx hir::InlineAsm,
diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs
index 0238a23895e..cb974366a30 100644
--- a/src/librustc_mir/hair/pattern/mod.rs
+++ b/src/librustc_mir/hair/pattern/mod.rs
@@ -20,9 +20,9 @@ use const_eval::{const_field, const_variant_index};
 
 use hair::util::UserAnnotatedTyHelpers;
 
-use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability};
+use rustc::mir::{fmt_const_val, Field, BorrowKind, Mutability, UserTypeAnnotation};
 use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
-use rustc::ty::{self, CanonicalTy, TyCtxt, AdtDef, Ty, Region};
+use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
 use rustc::ty::subst::{Substs, Kind};
 use rustc::hir::{self, PatKind, RangeEnd};
 use rustc::hir::def::{Def, CtorKind};
@@ -69,7 +69,7 @@ pub enum PatternKind<'tcx> {
     Wild,
 
     AscribeUserType {
-        user_ty: CanonicalTy<'tcx>,
+        user_ty: UserTypeAnnotation<'tcx>,
         subpattern: Pattern<'tcx>,
         user_ty_span: Span,
     },
@@ -980,7 +980,7 @@ macro_rules! CloneImpls {
 CloneImpls!{ <'tcx>
     Span, Field, Mutability, ast::Name, ast::NodeId, usize, &'tcx ty::Const<'tcx>,
     Region<'tcx>, Ty<'tcx>, BindingMode<'tcx>, &'tcx AdtDef,
-    &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, CanonicalTy<'tcx>
+    &'tcx Substs<'tcx>, &'tcx Kind<'tcx>, UserTypeAnnotation<'tcx>
 }
 
 impl<'tcx> PatternFoldable<'tcx> for FieldPattern<'tcx> {
diff --git a/src/librustc_mir/hair/util.rs b/src/librustc_mir/hair/util.rs
index 48a2e67a3dc..46a957f453c 100644
--- a/src/librustc_mir/hair/util.rs
+++ b/src/librustc_mir/hair/util.rs
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 use rustc::hir;
-use rustc::ty::{self, AdtDef, CanonicalTy, TyCtxt};
+use rustc::mir::UserTypeAnnotation;
+use rustc::ty::{self, AdtDef, TyCtxt};
 
 crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
     fn tcx(&self) -> TyCtxt<'_, 'gcx, 'tcx>;
@@ -20,32 +21,41 @@ crate trait UserAnnotatedTyHelpers<'gcx: 'tcx, 'tcx> {
         &self,
         hir_id: hir::HirId,
         adt_def: &'tcx AdtDef,
-    ) -> Option<CanonicalTy<'tcx>> {
+    ) -> Option<UserTypeAnnotation<'tcx>> {
         let user_substs = self.tables().user_substs(hir_id)?;
-        Some(user_substs.unchecked_map(|user_substs| {
-            // Here, we just pair an `AdtDef` with the
-            // `user_substs`, so no new types etc are introduced.
-            self.tcx().mk_adt(adt_def, user_substs)
-        }))
+        Some(UserTypeAnnotation::Ty(user_substs.unchecked_map(
+            |user_substs| {
+                // Here, we just pair an `AdtDef` with the
+                // `user_substs`, so no new types etc are introduced.
+                self.tcx().mk_adt(adt_def, user_substs)
+            },
+        )))
     }
 
     /// Looks up the type associated with this hir-id and applies the
     /// user-given substitutions; the hir-id must map to a suitable
     /// type.
-    fn user_substs_applied_to_ty_of_hir_id(&self, hir_id: hir::HirId) -> Option<CanonicalTy<'tcx>> {
+    fn user_substs_applied_to_ty_of_hir_id(
+        &self,
+        hir_id: hir::HirId,
+    ) -> Option<UserTypeAnnotation<'tcx>> {
         let user_substs = self.tables().user_substs(hir_id)?;
         match &self.tables().node_id_to_type(hir_id).sty {
-            ty::Adt(adt_def, _) => Some(user_substs.unchecked_map(|user_substs| {
-                // Ok to call `unchecked_map` because we just pair an
-                // `AdtDef` with the `user_substs`, so no new types
-                // etc are introduced.
-                self.tcx().mk_adt(adt_def, user_substs)
-            })),
-            ty::FnDef(def_id, _) => Some(user_substs.unchecked_map(|user_substs| {
-                // Here, we just pair a `DefId` with the
-                // `user_substs`, so no new types etc are introduced.
-                self.tcx().mk_fn_def(*def_id, user_substs)
-            })),
+            ty::Adt(adt_def, _) => Some(UserTypeAnnotation::Ty(user_substs.unchecked_map(
+                |user_substs| {
+                    // Ok to call `unchecked_map` because we just pair an
+                    // `AdtDef` with the `user_substs`, so no new types
+                    // etc are introduced.
+                    self.tcx().mk_adt(adt_def, user_substs)
+                },
+            ))),
+            ty::FnDef(def_id, _) => Some(UserTypeAnnotation::Ty(user_substs.unchecked_map(
+                |user_substs| {
+                    // Here, we just pair a `DefId` with the
+                    // `user_substs`, so no new types etc are introduced.
+                    self.tcx().mk_fn_def(*def_id, user_substs)
+                },
+            ))),
             sty => bug!(
                 "sty: {:?} should not have user-substs {:?} recorded ",
                 sty,