]> 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 bf35e25635aa2f94f19e262383b3ca1c2059bd23..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;
@@ -96,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,
         }
     }
 }
@@ -127,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,
         }
     }
 }
@@ -181,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,
@@ -272,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)]
@@ -365,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
@@ -458,6 +474,10 @@ pub struct ctxt<'tcx> {
     pub trait_refs: RefCell<NodeMap<Rc<TraitRef>>>,
     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef>>>,
 
+    /// 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>,
@@ -499,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,
@@ -516,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>,
@@ -536,7 +553,6 @@ pub struct ctxt<'tcx> {
     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>,
 
@@ -557,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 {
@@ -1009,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>>
 }
@@ -1017,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,
@@ -1089,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)]
@@ -1152,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),
         }
     }
 }
@@ -1171,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>,
 }
@@ -1207,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.
@@ -1224,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
@@ -1235,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 {
@@ -1249,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)) => {
@@ -1272,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)) => {
@@ -1287,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)
                     }
@@ -1296,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,
@@ -1328,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>,
 }
@@ -1345,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,
@@ -1352,7 +1433,7 @@ pub struct UnboxedClosure {
     pub kind: UnboxedClosureKind,
 }
 
-#[deriving(PartialEq, Eq)]
+#[deriving(Clone, PartialEq, Eq)]
 pub enum UnboxedClosureKind {
     FnUnboxedClosureKind,
     FnMutUnboxedClosureKind,
@@ -1401,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),
@@ -1429,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()),
     }
 }
 
@@ -1523,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);
       }
@@ -1861,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 {
@@ -2394,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
@@ -2414,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
             }
 
@@ -2909,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
     }
 }
 
@@ -2926,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,
@@ -3448,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)
         }
     }
@@ -3468,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()
         }
@@ -3486,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")
+                }
             }
         }
     }
@@ -3581,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 => {
@@ -3744,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(),
@@ -3760,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()
@@ -3958,12 +4062,19 @@ pub fn provided_trait_methods(cx: &ctxt, id: ast::DefId) -> Vec<Rc<Method>> {
             Some(ast_map::NodeItem(item)) => {
                 match item.node {
                     ItemTrait(_, _, _, ref ms) => {
-                        ms.iter().filter_map(|m| match *m {
-                            ast::RequiredMethod(_) => None,
-                            ast::ProvidedMethod(ref m) => {
-                                match impl_or_trait_item(cx,
-                                        ast_util::local_def(m.id)) {
-                                    MethodTraitItem(m) => Some(m),
+                        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()
@@ -4048,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",
@@ -4362,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();
@@ -4449,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
     });
 
@@ -4683,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) {
@@ -4783,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;
@@ -4856,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={}",
@@ -4944,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,
@@ -4967,6 +5109,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
                            .insert(method_def_id, source);
                     }
                 }
+                TypeTraitItem(_) => {}
             }
         }
 
@@ -4975,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);
 }
 
@@ -5021,6 +5157,7 @@ pub fn populate_implementations_for_trait_if_necessary(
                            .insert(method_def_id, source);
                     }
                 }
+                TypeTraitItem(_) => {}
             }
         }
 
@@ -5104,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);
@@ -5218,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);
@@ -5261,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
@@ -5321,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>,
@@ -5342,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);
         }
@@ -5398,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",