]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/ty.rs
rustc: remove DefArg and DefBinding in favor of DefLocal.
[rust.git] / src / librustc / middle / ty.rs
index 69b73436477c1ac6b5ee0c980398a33f070feb20..f8fc6713eb9cb905090e5a61a302de08cc7b26fa 100644 (file)
@@ -28,6 +28,7 @@
 use middle::stability;
 use middle::subst::{Subst, Substs, VecPerParamSpace};
 use middle::subst;
+use middle::traits;
 use middle::ty;
 use middle::typeck;
 use middle::ty_fold;
@@ -44,7 +45,6 @@
 use std::fmt::Show;
 use std::fmt;
 use std::hash::{Hash, sip, Writer};
-use std::gc::Gc;
 use std::iter::AdditiveIterator;
 use std::mem;
 use std::ops;
@@ -97,30 +97,37 @@ pub fn id(&self) -> ast::DefId {
 #[deriving(Clone)]
 pub enum ImplOrTraitItem {
     MethodTraitItem(Rc<Method>),
+    TypeTraitItem(Rc<AssociatedType>),
 }
 
 impl ImplOrTraitItem {
     fn id(&self) -> ImplOrTraitItemId {
         match *self {
             MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
+            TypeTraitItem(ref associated_type) => {
+                TypeTraitItemId(associated_type.def_id)
+            }
         }
     }
 
     pub fn def_id(&self) -> ast::DefId {
         match *self {
             MethodTraitItem(ref method) => method.def_id,
+            TypeTraitItem(ref associated_type) => associated_type.def_id,
         }
     }
 
     pub fn ident(&self) -> ast::Ident {
         match *self {
             MethodTraitItem(ref method) => method.ident,
+            TypeTraitItem(ref associated_type) => associated_type.ident,
         }
     }
 
     pub fn container(&self) -> ImplOrTraitItemContainer {
         match *self {
             MethodTraitItem(ref method) => method.container,
+            TypeTraitItem(ref associated_type) => associated_type.container,
         }
     }
 }
@@ -128,12 +135,14 @@ pub fn container(&self) -> ImplOrTraitItemContainer {
 #[deriving(Clone)]
 pub enum ImplOrTraitItemId {
     MethodTraitItemId(ast::DefId),
+    TypeTraitItemId(ast::DefId),
 }
 
 impl ImplOrTraitItemId {
     pub fn def_id(&self) -> ast::DefId {
         match *self {
             MethodTraitItemId(def_id) => def_id,
+            TypeTraitItemId(def_id) => def_id,
         }
     }
 }
@@ -182,6 +191,14 @@ pub fn container_id(&self) -> ast::DefId {
     }
 }
 
+#[deriving(Clone)]
+pub struct AssociatedType {
+    pub ident: ast::Ident,
+    pub vis: ast::Visibility,
+    pub def_id: ast::DefId,
+    pub container: ImplOrTraitItemContainer,
+}
+
 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
 pub struct mt {
     pub ty: t,
@@ -273,9 +290,7 @@ pub enum UnsizeKind {
     // An unsize coercion applied to the tail field of a struct.
     // The uint is the index of the type parameter which is unsized.
     UnsizeStruct(Box<UnsizeKind>, uint),
-    UnsizeVtable(ty::ExistentialBounds,
-                 ast::DefId, /* Trait ID */
-                 subst::Substs /* Trait substitutions */)
+    UnsizeVtable(TyTrait, /* the self type of the trait */ ty::t)
 }
 
 #[deriving(Clone)]
@@ -366,13 +381,13 @@ pub fn type_of_adjust(cx: &ctxt, adj: &AutoAdjustment) -> Option<t> {
     fn type_of_autoref(cx: &ctxt, autoref: &AutoRef) -> Option<t> {
         match autoref {
             &AutoUnsize(ref k) => match k {
-                &UnsizeVtable(bounds, def_id, ref substs) => {
+                &UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
                     Some(mk_trait(cx, def_id, substs.clone(), bounds))
                 }
                 _ => None
             },
             &AutoUnsizeUniq(ref k) => match k {
-                &UnsizeVtable(bounds, def_id, ref substs) => {
+                &UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
                     Some(mk_uniq(cx, mk_trait(cx, def_id, substs.clone(), bounds)))
                 }
                 _ => None
@@ -459,7 +474,11 @@ pub struct ctxt<'tcx> {
     pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
 
-    pub map: ast_map::Map,
+    /// Maps from node-id of a trait object cast (like `foo as
+    /// Box<Trait>`) to the trait reference.
+    pub object_cast_map: typeck::ObjectCastMap,
+
+    pub map: ast_map::Map<'tcx>,
     pub intrinsic_defs: RefCell<DefIdMap<t>>,
     pub freevars: RefCell<freevars::freevar_map>,
     pub tcache: type_cache,
@@ -500,7 +519,7 @@ pub struct ctxt<'tcx> {
     /// Maps a DefId of a type to a list of its inherent impls.
     /// Contains implementations of methods that are inherent to a type.
     /// Methods in these implementations don't need to be exported.
-    pub inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
+    pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>,
 
     /// Maps a DefId of an impl to a list of its items.
     /// Note that this contains all of the impls that we know about,
@@ -517,9 +536,6 @@ pub struct ctxt<'tcx> {
     /// about.
     pub used_mut_nodes: RefCell<NodeSet>,
 
-    /// vtable resolution information for impl declarations
-    pub impl_vtables: typeck::impl_vtable_map,
-
     /// The set of external nominal types whose implementations have been read.
     /// This is used for lazy resolution of methods.
     pub populated_external_types: RefCell<DefIdSet>,
@@ -533,11 +549,10 @@ pub struct ctxt<'tcx> {
 
     /// These two caches are used by const_eval when decoding external statics
     /// and variants that are found.
-    pub extern_const_statics: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
-    pub extern_const_variants: RefCell<DefIdMap<Option<Gc<ast::Expr>>>>,
+    pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
+    pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
 
     pub method_map: typeck::MethodMap,
-    pub vtable_map: typeck::vtable_map,
 
     pub dependency_formats: RefCell<dependency_format::Dependencies>,
 
@@ -558,6 +573,13 @@ pub struct ctxt<'tcx> {
 
     /// Maps closures to their capture clauses.
     pub capture_modes: RefCell<CaptureModeMap>,
+
+    /// Maps def IDs to true if and only if they're associated types.
+    pub associated_types: RefCell<DefIdMap<bool>>,
+
+    /// Maps def IDs of traits to information about their associated types.
+    pub trait_associated_types:
+        RefCell<DefIdMap<Rc<Vec<AssociatedTypeInfo>>>>,
 }
 
 pub enum tbox_flag {
@@ -1010,7 +1032,7 @@ pub enum type_err {
 /// as well as the existential type parameter in an object type.
 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
 pub struct ParamBounds {
-    pub opt_region_bound: Option<ty::Region>,
+    pub region_bounds: Vec<ty::Region>,
     pub builtin_bounds: BuiltinBounds,
     pub trait_bounds: Vec<Rc<TraitRef>>
 }
@@ -1018,7 +1040,8 @@ pub struct ParamBounds {
 /// Bounds suitable for an existentially quantified type parameter
 /// such as those that appear in object types or closure types. The
 /// major difference between this case and `ParamBounds` is that
-/// general purpose trait bounds are omitted.
+/// general purpose trait bounds are omitted and there must be
+/// *exactly one* region.
 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
 pub struct ExistentialBounds {
     pub region_bound: ty::Region,
@@ -1090,7 +1113,13 @@ pub struct RegionVid {
 pub enum InferTy {
     TyVar(TyVid),
     IntVar(IntVid),
-    FloatVar(FloatVid)
+    FloatVar(FloatVid),
+    SkolemizedTy(uint),
+
+    // FIXME -- once integral fallback is impl'd, we should remove
+    // this type. It's only needed to prevent spurious errors for
+    // integers whose type winds up never being constrained.
+    SkolemizedIntTy(uint),
 }
 
 #[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
@@ -1153,6 +1182,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             TyVar(ref v) => v.fmt(f),
             IntVar(ref v) => v.fmt(f),
             FloatVar(ref v) => v.fmt(f),
+            SkolemizedTy(v) => write!(f, "SkolemizedTy({})", v),
+            SkolemizedIntTy(v) => write!(f, "SkolemizedIntTy({})", v),
         }
     }
 }
@@ -1172,6 +1203,7 @@ pub struct TypeParameterDef {
     pub def_id: ast::DefId,
     pub space: subst::ParamSpace,
     pub index: uint,
+    pub associated_with: Option<ast::DefId>,
     pub bounds: ParamBounds,
     pub default: Option<ty::t>,
 }
@@ -1208,6 +1240,12 @@ pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
     }
 }
 
+impl TraitRef {
+    pub fn self_ty(&self) -> ty::t {
+        self.substs.self_ty().unwrap()
+    }
+}
+
 /// When type checking, we use the `ParameterEnvironment` to track
 /// details about the type/lifetime parameters that are in scope.
 /// It primarily stores the bounds information.
@@ -1225,7 +1263,7 @@ pub struct ParameterEnvironment {
     /// the "outer" view of a type or method to the "inner" view.
     /// In general, this means converting from bound parameters to
     /// free parameters. Since we currently represent bound/free type
-    /// parameters in the same way, this only has an affect on regions.
+    /// parameters in the same way, this only has an effect on regions.
     pub free_substs: Substs,
 
     /// Bounds on the various type parameters
@@ -1236,6 +1274,14 @@ pub struct ParameterEnvironment {
     /// may specify stronger requirements). This field indicates the
     /// region of the callee.
     pub implicit_region_bound: ty::Region,
+
+    /// Obligations that the caller must satisfy. This is basically
+    /// the set of bounds on the in-scope type parameters, translated
+    /// into Obligations.
+    ///
+    /// Note: This effectively *duplicates* the `bounds` array for
+    /// now.
+    pub caller_obligations: VecPerParamSpace<traits::Obligation>,
 }
 
 impl ParameterEnvironment {
@@ -1250,11 +1296,23 @@ pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
                                 let method_generics = &method_ty.generics;
                                 construct_parameter_environment(
                                     cx,
+                                    method.span,
                                     method_generics,
                                     method.pe_body().id)
                             }
+                            TypeTraitItem(_) => {
+                                cx.sess
+                                  .bug("ParameterEnvironment::from_item(): \
+                                        can't create a parameter environment \
+                                        for type trait items")
+                            }
                         }
                     }
+                    ast::TypeImplItem(_) => {
+                        cx.sess.bug("ParameterEnvironment::from_item(): \
+                                     can't create a parameter environment \
+                                     for type impl items")
+                    }
                 }
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
@@ -1273,11 +1331,23 @@ pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
                                 let method_generics = &method_ty.generics;
                                 construct_parameter_environment(
                                     cx,
+                                    method.span,
                                     method_generics,
                                     method.pe_body().id)
                             }
+                            TypeTraitItem(_) => {
+                                cx.sess
+                                  .bug("ParameterEnvironment::from_item(): \
+                                        can't create a parameter environment \
+                                        for type trait items")
+                            }
                         }
                     }
+                    ast::TypeTraitItem(_) => {
+                        cx.sess.bug("ParameterEnvironment::from_item(): \
+                                     can't create a parameter environment \
+                                     for type trait items")
+                    }
                 }
             }
             Some(ast_map::NodeItem(item)) => {
@@ -1288,6 +1358,7 @@ pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
                         let fn_pty = ty::lookup_item_type(cx, fn_def_id);
 
                         construct_parameter_environment(cx,
+                                                        item.span,
                                                         &fn_pty.generics,
                                                         body.id)
                     }
@@ -1297,7 +1368,8 @@ pub fn for_item(cx: &ctxt, id: NodeId) -> ParameterEnvironment {
                     ast::ItemStatic(..) => {
                         let def_id = ast_util::local_def(id);
                         let pty = ty::lookup_item_type(cx, def_id);
-                        construct_parameter_environment(cx, &pty.generics, id)
+                        construct_parameter_environment(cx, item.span,
+                                                        &pty.generics, id)
                     }
                     _ => {
                         cx.sess.span_bug(item.span,
@@ -1329,7 +1401,14 @@ pub struct Polytype {
 
 /// As `Polytype` but for a trait ref.
 pub struct TraitDef {
+    /// Generic type definitions. Note that `Self` is listed in here
+    /// as having a single bound, the trait itself (e.g., in the trait
+    /// `Eq`, there is a single bound `Self : Eq`). This is so that
+    /// default methods get to assume that the `Self` parameters
+    /// implements the trait.
     pub generics: Generics,
+
+    /// The "supertrait" bounds.
     pub bounds: ParamBounds,
     pub trait_ref: Rc<ty::TraitRef>,
 }
@@ -1346,6 +1425,7 @@ pub struct ItemSubsts {
 pub type node_type_table = RefCell<HashMap<uint,t>>;
 
 /// Records information about each unboxed closure.
+#[deriving(Clone)]
 pub struct UnboxedClosure {
     /// The type of the unboxed closure.
     pub closure_type: ClosureTy,
@@ -1353,7 +1433,7 @@ pub struct UnboxedClosure {
     pub kind: UnboxedClosureKind,
 }
 
-#[deriving(PartialEq, Eq)]
+#[deriving(Clone, PartialEq, Eq)]
 pub enum UnboxedClosureKind {
     FnUnboxedClosureKind,
     FnMutUnboxedClosureKind,
@@ -1382,7 +1462,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
                      type_arena: &'tcx TypedArena<t_box_>,
                      dm: resolve::DefMap,
                      named_region_map: resolve_lifetime::NamedRegionMap,
-                     map: ast_map::Map,
+                     map: ast_map::Map<'tcx>,
                      freevars: freevars::freevar_map,
                      capture_modes: freevars::CaptureModeMap,
                      region_maps: middle::region::RegionMaps,
@@ -1402,6 +1482,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
         item_substs: RefCell::new(NodeMap::new()),
         trait_refs: RefCell::new(NodeMap::new()),
         trait_defs: RefCell::new(DefIdMap::new()),
+        object_cast_map: RefCell::new(NodeMap::new()),
         map: map,
         intrinsic_defs: RefCell::new(DefIdMap::new()),
         freevars: RefCell::new(freevars),
@@ -1430,20 +1511,20 @@ pub fn mk_ctxt<'tcx>(s: Session,
         impl_items: RefCell::new(DefIdMap::new()),
         used_unsafe: RefCell::new(NodeSet::new()),
         used_mut_nodes: RefCell::new(NodeSet::new()),
-        impl_vtables: RefCell::new(DefIdMap::new()),
         populated_external_types: RefCell::new(DefIdSet::new()),
         populated_external_traits: RefCell::new(DefIdSet::new()),
         upvar_borrow_map: RefCell::new(HashMap::new()),
         extern_const_statics: RefCell::new(DefIdMap::new()),
         extern_const_variants: RefCell::new(DefIdMap::new()),
         method_map: RefCell::new(FnvHashMap::new()),
-        vtable_map: RefCell::new(FnvHashMap::new()),
         dependency_formats: RefCell::new(HashMap::new()),
         unboxed_closures: RefCell::new(DefIdMap::new()),
         node_lint_levels: RefCell::new(HashMap::new()),
         transmute_restrictions: RefCell::new(Vec::new()),
         stability: RefCell::new(stability),
         capture_modes: RefCell::new(capture_modes),
+        associated_types: RefCell::new(DefIdMap::new()),
+        trait_associated_types: RefCell::new(DefIdMap::new()),
     }
 }
 
@@ -1524,7 +1605,7 @@ fn flags_for_bounds(bounds: &ExistentialBounds) -> uint {
       &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
           flags |= sflags(substs);
       }
-      &ty_trait(box ty::TyTrait { ref substs, ref bounds, .. }) => {
+      &ty_trait(box TyTrait { ref substs, ref bounds, .. }) => {
           flags |= sflags(substs);
           flags |= flags_for_bounds(bounds);
       }
@@ -1862,6 +1943,10 @@ pub fn for_def(def: &TypeParameterDef) -> ParamTy {
     pub fn to_ty(self, tcx: &ty::ctxt) -> ty::t {
         ty::mk_param(tcx, self.space, self.idx, self.def_id)
     }
+
+    pub fn is_self(&self) -> bool {
+        self.space == subst::SelfSpace && self.idx == 0
+    }
 }
 
 impl ItemSubsts {
@@ -2395,6 +2480,7 @@ fn tc_ty(cx: &ctxt,
             }
 
             // Scalar and unique types are sendable, and durable
+            ty_infer(ty::SkolemizedIntTy(_)) |
             ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
             ty_bare_fn(_) | ty::ty_char => {
                 TC::None
@@ -2415,7 +2501,7 @@ fn tc_ty(cx: &ctxt,
                 }
             }
 
-            ty_trait(box ty::TyTrait { bounds, .. }) => {
+            ty_trait(box TyTrait { bounds, .. }) => {
                 object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
             }
 
@@ -2910,13 +2996,17 @@ fn type_structurally_recursive(cx: &ctxt, sp: Span, seen: &mut Vec<DefId>,
 }
 
 pub fn type_is_trait(ty: t) -> bool {
+    type_trait_info(ty).is_some()
+}
+
+pub fn type_trait_info(ty: t) -> Option<&'static TyTrait> {
     match get(ty).sty {
         ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match get(ty).sty {
-            ty_trait(..) => true,
-            _ => false
+            ty_trait(ref t) => Some(&**t),
+            _ => None
         },
-        ty_trait(..) => true,
-        _ => false
+        ty_trait(ref t) => Some(&**t),
+        _ => None
     }
 }
 
@@ -2927,6 +3017,14 @@ pub fn type_is_integral(ty: t) -> bool {
     }
 }
 
+pub fn type_is_skolemized(ty: t) -> bool {
+    match get(ty).sty {
+      ty_infer(SkolemizedTy(_)) => true,
+      ty_infer(SkolemizedIntTy(_)) => true,
+      _ => false
+    }
+}
+
 pub fn type_is_uint(ty: t) -> bool {
     match get(ty).sty {
       ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
@@ -2992,14 +3090,13 @@ pub fn lltype_is_sized(cx: &ctxt, ty: t) -> bool {
 pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t {
     match get(ty).sty {
         ty_str | ty_trait(..) | ty_vec(..) => ty,
-        ty_struct(_, ref substs) => {
-            // Exactly one of the type parameters must be unsized.
-            for tp in substs.types.get_slice(subst::TypeSpace).iter() {
-                if !type_is_sized(cx, *tp) {
-                    return unsized_part_of_type(cx, *tp);
-                }
-            }
-            fail!("Unsized struct type with no unsized type params? {}", ty_to_string(cx, ty));
+        ty_struct(def_id, ref substs) => {
+            let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
+                .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
+            // Exactly one of the fields must be unsized.
+            assert!(unsized_fields.len() == 1)
+
+            unsized_part_of_type(cx, unsized_fields[0])
         }
         _ => {
             assert!(type_is_sized(cx, ty),
@@ -3450,7 +3547,7 @@ pub fn unsize_ty(cx: &ctxt,
                                   format!("UnsizeStruct with bad sty: {}",
                                           ty_to_string(cx, ty)).as_slice())
         },
-        &UnsizeVtable(bounds, def_id, ref substs) => {
+        &UnsizeVtable(TyTrait { def_id, substs: ref substs, bounds }, _) => {
             mk_trait(cx, def_id, substs.clone(), bounds)
         }
     }
@@ -3470,10 +3567,10 @@ pub fn map_region(&self, f: |Region| -> Region) -> AutoRef {
 }
 
 pub fn method_call_type_param_defs<'tcx, T>(typer: &T,
-                                            origin: typeck::MethodOrigin)
+                                            origin: &typeck::MethodOrigin)
                                             -> VecPerParamSpace<TypeParameterDef>
                                             where T: mc::Typer<'tcx> {
-    match origin {
+    match *origin {
         typeck::MethodStatic(did) => {
             ty::lookup_item_type(typer.tcx(), did).generics.types.clone()
         }
@@ -3488,17 +3585,21 @@ pub fn method_call_type_param_defs<'tcx, T>(typer: &T,
             lookup_trait_def(typer.tcx(), def_id).generics.types.clone()
         }
         typeck::MethodParam(typeck::MethodParam{
-            trait_id: trt_id,
+            trait_ref: ref trait_ref,
             method_num: n_mth,
             ..
         }) |
         typeck::MethodObject(typeck::MethodObject{
-                trait_id: trt_id,
+                trait_ref: ref trait_ref,
                 method_num: n_mth,
                 ..
         }) => {
-            match ty::trait_item(typer.tcx(), trt_id, n_mth) {
+            match ty::trait_item(typer.tcx(), trait_ref.def_id, n_mth) {
                 ty::MethodTraitItem(method) => method.generics.types.clone(),
+                ty::TypeTraitItem(_) => {
+                    typer.tcx().sess.bug("method_call_type_param_defs() \
+                                          called on associated type")
+                }
             }
         }
     }
@@ -3583,9 +3684,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                 // DefArg's, particularly those of immediate type, ought to
                 // considered rvalues.
                 def::DefStatic(..) |
-                def::DefBinding(..) |
                 def::DefUpvar(..) |
-                def::DefArg(..) |
                 def::DefLocal(..) => LvalueExpr,
 
                 def => {
@@ -3600,6 +3699,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
 
         ast::ExprUnary(ast::UnDeref, _) |
         ast::ExprField(..) |
+        ast::ExprTupField(..) |
         ast::ExprIndex(..) => {
             LvalueExpr
         }
@@ -3619,7 +3719,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             RvalueDpsExpr
         }
 
-        ast::ExprLit(lit) if lit_is_str(lit) => {
+        ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
             RvalueDpsExpr
         }
 
@@ -3668,7 +3768,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             RvalueDatumExpr
         }
 
-        ast::ExprBox(place, _) => {
+        ast::ExprBox(ref place, _) => {
             // Special case `Box<T>`/`Gc<T>` for now:
             let definition = match tcx.def_map.borrow().find(&place.id) {
                 Some(&def) => def,
@@ -3745,7 +3845,8 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
         ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
         ty_box(_) => "Gc-ptr".to_string(),
         ty_uniq(_) => "box".to_string(),
-        ty_vec(_, _) => "vector".to_string(),
+        ty_vec(_, Some(_)) => "array".to_string(),
+        ty_vec(_, None) => "unsized array".to_string(),
         ty_ptr(_) => "*-ptr".to_string(),
         ty_rptr(_, _) => "&-ptr".to_string(),
         ty_bare_fn(_) => "extern fn".to_string(),
@@ -3761,6 +3862,8 @@ pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
         ty_infer(TyVar(_)) => "inferred type".to_string(),
         ty_infer(IntVar(_)) => "integral variable".to_string(),
         ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
+        ty_infer(SkolemizedTy(_)) => "skolemized type".to_string(),
+        ty_infer(SkolemizedIntTy(_)) => "skolemized integral type".to_string(),
         ty_param(ref p) => {
             if p.space == subst::SelfSpace {
                 "Self".to_string()
@@ -3959,16 +4062,22 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
                     ItemTrait(_, _, _, ref ms) => {
-                        let (_, p) = ast_util::split_trait_methods(ms.as_slice());
+                        let (_, p) =
+                            ast_util::split_trait_methods(ms.as_slice());
                         p.iter()
                          .map(|m| {
                             match impl_or_trait_item(
                                     cx,
                                     ast_util::local_def(m.id)) {
                                 MethodTraitItem(m) => m,
+                                TypeTraitItem(_) => {
+                                    cx.sess.bug("provided_trait_methods(): \
+                                                 split_trait_methods() put \
+                                                 associated types in the \
+                                                 provided method bucket?!")
+                                }
                             }
-                         })
-                         .collect()
+                         }).collect()
                     }
                     _ => {
                         cx.sess.bug(format!("provided_trait_methods: `{}` is \
@@ -4050,6 +4159,75 @@ pub fn impl_or_trait_item(cx: &ctxt, id: ast::DefId) -> ImplOrTraitItem {
     })
 }
 
+/// Returns true if the given ID refers to an associated type and false if it
+/// refers to anything else.
+pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
+    let result = match cx.associated_types.borrow_mut().find(&id) {
+        Some(result) => return *result,
+        None if id.krate == ast::LOCAL_CRATE => {
+            match cx.impl_or_trait_items.borrow().find(&id) {
+                Some(ref item) => {
+                    match **item {
+                        TypeTraitItem(_) => true,
+                        MethodTraitItem(_) => false,
+                    }
+                }
+                None => false,
+            }
+        }
+        None => {
+            csearch::is_associated_type(&cx.sess.cstore, id)
+        }
+    };
+
+    cx.associated_types.borrow_mut().insert(id, result);
+    result
+}
+
+/// Returns the parameter index that the given associated type corresponds to.
+pub fn associated_type_parameter_index(cx: &ctxt,
+                                       trait_def: &TraitDef,
+                                       associated_type_id: ast::DefId)
+                                       -> uint {
+    for type_parameter_def in trait_def.generics.types.iter() {
+        if type_parameter_def.def_id == associated_type_id {
+            return type_parameter_def.index
+        }
+    }
+    cx.sess.bug("couldn't find associated type parameter index")
+}
+
+#[deriving(PartialEq, Eq)]
+pub struct AssociatedTypeInfo {
+    pub def_id: ast::DefId,
+    pub index: uint,
+    pub ident: ast::Ident,
+}
+
+impl PartialOrd for AssociatedTypeInfo {
+    fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
+        Some(self.index.cmp(&other.index))
+    }
+}
+
+impl Ord for AssociatedTypeInfo {
+    fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
+        self.index.cmp(&other.index)
+    }
+}
+
+/// Returns the associated types belonging to the given trait, in parameter
+/// order.
+pub fn associated_types_for_trait(cx: &ctxt, trait_id: ast::DefId)
+                                  -> Rc<Vec<AssociatedTypeInfo>> {
+    cx.trait_associated_types
+      .borrow()
+      .find(&trait_id)
+      .expect("associated_types_for_trait(): trait not found, try calling \
+               ensure_associated_types()")
+      .clone()
+}
+
 pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
                           -> Rc<Vec<ImplOrTraitItemId>> {
     lookup_locally_or_in_crate_store("trait_item_def_ids",
@@ -4289,11 +4467,11 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
           expr, since check_enum_variants also updates the enum_var_cache
          */
         match cx.map.get(id.node) {
-            ast_map::NodeItem(item) => {
+            ast_map::NodeItem(ref item) => {
                 match item.node {
                     ast::ItemEnum(ref enum_definition, _) => {
                         let mut last_discriminant: Option<Disr> = None;
-                        Rc::new(enum_definition.variants.iter().map(|&variant| {
+                        Rc::new(enum_definition.variants.iter().map(|variant| {
 
                             let mut discriminant = match last_discriminant {
                                 Some(val) => val + 1,
@@ -4324,7 +4502,7 @@ pub fn enum_variants(cx: &ctxt, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo>>> {
                             };
 
                             last_discriminant = Some(discriminant);
-                            Rc::new(VariantInfo::from_ast_variant(cx, &*variant,
+                            Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
                                                                   discriminant))
                         }).collect())
                     }
@@ -4364,14 +4542,6 @@ pub fn lookup_item_type(cx: &ctxt,
         || csearch::get_type(cx, did))
 }
 
-pub fn lookup_impl_vtables(cx: &ctxt,
-                           did: ast::DefId)
-                           -> typeck::vtable_res {
-    lookup_locally_or_in_crate_store(
-        "impl_vtables", did, &mut *cx.impl_vtables.borrow_mut(),
-        || csearch::get_impl_vtables(cx, did) )
-}
-
 /// Given the did of a trait, returns its canonical trait ref.
 pub fn lookup_trait_def(cx: &ctxt, did: ast::DefId) -> Rc<ty::TraitDef> {
     let mut trait_defs = cx.trait_defs.borrow_mut();
@@ -4451,7 +4621,7 @@ pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Vec<attr::ReprAttr> {
     let mut acc = Vec::new();
 
     ty::each_attr(tcx, did, |meta| {
-        acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(), meta).move_iter());
+        acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(), meta).into_iter());
         true
     });
 
@@ -4529,6 +4699,11 @@ pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
     }
 }
 
+pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool {
+    let fields = lookup_struct_fields(cx, did);
+    !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
+}
+
 pub fn lookup_struct_field(cx: &ctxt,
                            parent: ast::DefId,
                            field_id: ast::DefId)
@@ -4556,6 +4731,21 @@ pub fn struct_fields(cx: &ctxt, did: ast::DefId, substs: &Substs)
     }).collect()
 }
 
+// Returns a list of fields corresponding to the tuple's items. trans uses
+// this.
+pub fn tup_fields(v: &[t]) -> Vec<field> {
+    v.iter().enumerate().map(|(i, &f)| {
+       field {
+            // FIXME #6993: change type of field to Name and get rid of new()
+            ident: ast::Ident::new(token::intern(i.to_string().as_slice())),
+            mt: mt {
+                ty: f,
+                mutbl: MutImmutable
+            }
+        }
+    }).collect()
+}
+
 pub struct UnboxedClosureUpvar {
     pub def: def::Def,
     pub span: Span,
@@ -4665,7 +4855,7 @@ pub fn normalize_ty(cx: &ctxt, t: t) -> t {
     struct TypeNormalizer<'a, 'tcx: 'a>(&'a ctxt<'tcx>);
 
     impl<'a, 'tcx> TypeFolder<'tcx> for TypeNormalizer<'a, 'tcx> {
-        fn tcx<'a>(&'a self) -> &'a ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
+        fn tcx(&self) -> &ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
 
         fn fold_ty(&mut self, t: ty::t) -> ty::t {
             match self.tcx().normalized_cache.borrow().find_copy(&t) {
@@ -4765,42 +4955,11 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
 pub fn each_bound_trait_and_supertraits(tcx: &ctxt,
                                         bounds: &[Rc<TraitRef>],
                                         f: |Rc<TraitRef>| -> bool)
-                                        -> bool {
-    for bound_trait_ref in bounds.iter() {
-        let mut supertrait_set = HashMap::new();
-        let mut trait_refs = Vec::new();
-        let mut i = 0;
-
-        // Seed the worklist with the trait from the bound
-        supertrait_set.insert(bound_trait_ref.def_id, ());
-        trait_refs.push(bound_trait_ref.clone());
-
-        // Add the given trait ty to the hash map
-        while i < trait_refs.len() {
-            debug!("each_bound_trait_and_supertraits(i={:?}, trait_ref={})",
-                   i, trait_refs.get(i).repr(tcx));
-
-            if !f(trait_refs.get(i).clone()) {
-                return false;
-            }
-
-            // Add supertraits to supertrait_set
-            let trait_ref = trait_refs.get(i).clone();
-            let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
-            for supertrait_ref in trait_def.bounds.trait_bounds.iter() {
-                let supertrait_ref = supertrait_ref.subst(tcx, &trait_ref.substs);
-                debug!("each_bound_trait_and_supertraits(supertrait_ref={})",
-                       supertrait_ref.repr(tcx));
-
-                let d_id = supertrait_ref.def_id;
-                if !supertrait_set.contains_key(&d_id) {
-                    // FIXME(#5527) Could have same trait multiple times
-                    supertrait_set.insert(d_id, ());
-                    trait_refs.push(supertrait_ref.clone());
-                }
-            }
-
-            i += 1;
+                                        -> bool
+{
+    for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
+        if !f(bound_trait_ref) {
+            return false;
         }
     }
     return true;
@@ -4838,7 +4997,7 @@ pub fn required_region_bounds(tcx: &ctxt,
         trait_bounds,
         |trait_ref| {
             let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
-            push_region_bounds(bounds.opt_region_bound.as_slice(),
+            push_region_bounds(bounds.region_bounds.as_slice(),
                                bounds.builtin_bounds,
                                &mut all_bounds);
             debug!("from {}: bounds={} all_bounds={}",
@@ -4926,6 +5085,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
         return
     }
 
+    let mut inherent_impls = Vec::new();
     csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
             |impl_def_id| {
         let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
@@ -4949,6 +5109,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
                            .insert(method_def_id, source);
                     }
                 }
+                TypeTraitItem(_) => {}
             }
         }
 
@@ -4957,18 +5118,11 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
 
         // If this is an inherent implementation, record it.
         if associated_traits.is_none() {
-            match tcx.inherent_impls.borrow().find(&type_id) {
-                Some(implementation_list) => {
-                    implementation_list.borrow_mut().push(impl_def_id);
-                    return;
-                }
-                None => {}
-            }
-            tcx.inherent_impls.borrow_mut().insert(type_id,
-                                                   Rc::new(RefCell::new(vec!(impl_def_id))));
+            inherent_impls.push(impl_def_id);
         }
     });
 
+    tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
     tcx.populated_external_types.borrow_mut().insert(type_id);
 }
 
@@ -5003,6 +5157,7 @@ pub fn populate_implementations_for_trait_if_necessary(
                            .insert(method_def_id, source);
                     }
                 }
+                TypeTraitItem(_) => {}
             }
         }
 
@@ -5086,9 +5241,7 @@ pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
         Some(m) => m.clone(),
         None => return None,
     };
-    let name = match impl_item {
-        MethodTraitItem(method) => method.ident.name,
-    };
+    let name = impl_item.ident().name;
     match trait_of_item(tcx, def_id) {
         Some(trait_did) => {
             let trait_items = ty::trait_items(tcx, trait_did);
@@ -5200,7 +5353,7 @@ pub fn hash_crate_independent(tcx: &ctxt, t: t, svh: &Svh) -> u64 {
                     }
                 }
             }
-            ty_trait(box ty::TyTrait { def_id: d, bounds, .. }) => {
+            ty_trait(box TyTrait { def_id: d, bounds, .. }) => {
                 byte!(17);
                 did(&mut state, d);
                 hash!(bounds);
@@ -5243,8 +5396,22 @@ pub fn to_string(self) -> &'static str {
     }
 }
 
+pub fn empty_parameter_environment() -> ParameterEnvironment {
+    /*!
+     * Construct a parameter environment suitable for static contexts
+     * or other contexts where there are no free type/lifetime
+     * parameters in scope.
+     */
+
+    ty::ParameterEnvironment { free_substs: Substs::empty(),
+                               bounds: VecPerParamSpace::empty(),
+                               caller_obligations: VecPerParamSpace::empty(),
+                               implicit_region_bound: ty::ReEmpty }
+}
+
 pub fn construct_parameter_environment(
     tcx: &ctxt,
+    span: Span,
     generics: &ty::Generics,
     free_id: ast::NodeId)
     -> ParameterEnvironment
@@ -5303,10 +5470,14 @@ pub fn construct_parameter_environment(
            free_substs.repr(tcx),
            bounds.repr(tcx));
 
+    let obligations = traits::obligations_for_generics(tcx, traits::ObligationCause::misc(span),
+                                                       generics, &free_substs);
+
     return ty::ParameterEnvironment {
         free_substs: free_substs,
         bounds: bounds,
         implicit_region_bound: ty::ReScope(free_id),
+        caller_obligations: obligations,
     };
 
     fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
@@ -5324,6 +5495,11 @@ fn push_types_from_defs(tcx: &ty::ctxt,
                             space: subst::ParamSpace,
                             defs: &[TypeParameterDef]) {
         for (i, def) in defs.iter().enumerate() {
+            debug!("construct_parameter_environment(): push_types_from_defs: \
+                    space={} def={} index={}",
+                   space,
+                   def.repr(tcx),
+                   i);
             let ty = ty::mk_param(tcx, space, i, def.def_id);
             types.push(space, ty);
         }
@@ -5380,6 +5556,26 @@ pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
         }
     }
 
+    pub fn to_mutbl_lossy(self) -> ast::Mutability {
+        /*!
+         * Returns a mutability `m` such that an `&m T` pointer could
+         * be used to obtain this borrow kind. Because borrow kinds
+         * are richer than mutabilities, we sometimes have to pick a
+         * mutability that is stronger than necessary so that it at
+         * least *would permit* the borrow in question.
+         */
+
+        match self {
+            MutBorrow => ast::MutMutable,
+            ImmBorrow => ast::MutImmutable,
+
+            // We have no type correponding to a unique imm borrow, so
+            // use `&mut`. It gives all the capabilities of an `&uniq`
+            // and hence is a safe "over approximation".
+            UniqueImmBorrow => ast::MutMutable,
+        }
+    }
+
     pub fn to_user_str(&self) -> &'static str {
         match *self {
             MutBorrow => "mutable",