diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 0545a88f36bdc28bd34e0cf3b3d19db6865495a0..388c2455eb3860fd4d901bcd95f5c4b890fb936c 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -33,7 +33,7 @@ use middle::stability; use mir::{self, Mir, interpret}; use mir::interpret::Allocation; -use ty::subst::{Kind, Substs, Subst}; +use ty::subst::{CanonicalSubsts, Kind, Substs, Subst}; use ty::ReprOptions; use traits; use traits::{Clause, Clauses, Goal, Goals}; @@ -371,6 +371,18 @@ pub struct TypeckTables<'tcx> { /// other items. node_substs: ItemLocalMap<&'tcx Substs<'tcx>>, + /// Stores the substitutions that the user explicit gave (if any) + /// attached to `id`. These will not include any inferred + /// values. The canonical form is used to capture things like `_` + /// or other unspecified values. + /// + /// Example: + /// + /// If the user wrote `foo.collect::>()`, then the + /// canonical substitutions would include only `for { Vec + /// }`. + user_substs: ItemLocalMap>, + adjustments: ItemLocalMap>>, /// Stores the actual binding mode for all instances of hir::BindingAnnotation. @@ -444,6 +456,7 @@ pub fn empty(local_id_root: Option) -> TypeckTables<'tcx> { user_provided_tys: ItemLocalMap(), node_types: ItemLocalMap(), node_substs: ItemLocalMap(), + user_substs: ItemLocalMap(), adjustments: ItemLocalMap(), pat_binding_modes: ItemLocalMap(), pat_adjustments: ItemLocalMap(), @@ -561,6 +574,18 @@ pub fn node_substs_opt(&self, id: hir::HirId) -> Option<&'tcx Substs<'tcx>> { self.node_substs.get(&id.local_id).cloned() } + pub fn user_substs_mut(&mut self) -> LocalTableInContextMut> { + LocalTableInContextMut { + local_id_root: self.local_id_root, + data: &mut self.user_substs + } + } + + pub fn user_substs(&self, id: hir::HirId) -> Option> { + validate_hir_id_for_typeck_tables(self.local_id_root, id, false); + self.user_substs.get(&id.local_id).cloned() + } + // Returns the type of a pattern as a monotype. Like @expr_ty, this function // doesn't provide type parameter substitutions. pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { @@ -740,6 +765,7 @@ fn hash_stable(&self, ref user_provided_tys, ref node_types, ref node_substs, + ref user_substs, ref adjustments, ref pat_binding_modes, ref pat_adjustments, @@ -762,6 +788,7 @@ fn hash_stable(&self, user_provided_tys.hash_stable(hcx, hasher); node_types.hash_stable(hcx, hasher); node_substs.hash_stable(hcx, hasher); + user_substs.hash_stable(hcx, hasher); adjustments.hash_stable(hcx, hasher); pat_binding_modes.hash_stable(hcx, hasher); pat_adjustments.hash_stable(hcx, hasher); diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs index 0e85c68b8b1deeb0732bdb7f259198a0ac9cd57c..26e8b72946b54b5e71a01d951709c7d63f7b56f1 100644 --- a/src/librustc/ty/subst.rs +++ b/src/librustc/ty/subst.rs @@ -11,6 +11,7 @@ // Type substitutions. use hir::def_id::DefId; +use infer::canonical::Canonical; use ty::{self, Lift, List, Ty, TyCtxt}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; @@ -179,6 +180,8 @@ fn decode(d: &mut D) -> Result, D::Error> { /// A substitution mapping generic parameters to new values. pub type Substs<'tcx> = List>; +pub type CanonicalSubsts<'gcx> = Canonical<'gcx, &'gcx Substs<'gcx>>; + impl<'a, 'gcx, 'tcx> Substs<'tcx> { /// Creates a Substs that maps each generic parameter to itself. pub fn identity_for_item(tcx: TyCtxt<'a, 'gcx, 'tcx>, def_id: DefId)