]> git.lizzy.rs Git - rust.git/commitdiff
Currently trans uses Vec<ty::t> to represent substitutions instead of a proper
authorNiko Matsakis <niko@alum.mit.edu>
Wed, 7 May 2014 11:20:15 +0000 (07:20 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Fri, 9 May 2014 09:56:44 +0000 (05:56 -0400)
ty::substs struct. This is a holdover from the olden days of yore. This patch
removes the last vestiges of that practice. This is part of the work
I was doing on #5527.

18 files changed:
src/librustc/metadata/common.rs
src/librustc/middle/astencode.rs
src/librustc/middle/kind.rs
src/librustc/middle/subst.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/common.rs
src/librustc/middle/trans/debuginfo.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/intrinsic.rs
src/librustc/middle/trans/meth.rs
src/librustc/middle/trans/monomorphize.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/check/writeback.rs
src/librustc/middle/typeck/mod.rs
src/librustc/util/ppaux.rs

index 839b0e08d37952a8e192d96d6bbc06fc5713411f..26f5ead37bec83713fbf4d6c9f51f454c7187bae 100644 (file)
@@ -128,7 +128,7 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
     tag_table_val = 0x45,
     tag_table_def = 0x46,
     tag_table_node_type = 0x47,
-    tag_table_node_type_subst = 0x48,
+    tag_table_item_subst = 0x48,
     tag_table_freevars = 0x49,
     tag_table_tcache = 0x4a,
     tag_table_param_defs = 0x4b,
index 5ada0068a47ef6e8f5fa106e3b8fa3a84752210a..523e0042cce50b58e0ac9b402c61cd22b9176df1 100644 (file)
@@ -657,13 +657,13 @@ pub fn encode_vtable_origin(ecx: &e::EncodeContext,
                         vtable_origin: &typeck::vtable_origin) {
     ebml_w.emit_enum("vtable_origin", |ebml_w| {
         match *vtable_origin {
-          typeck::vtable_static(def_id, ref tys, ref vtable_res) => {
+          typeck::vtable_static(def_id, ref substs, ref vtable_res) => {
             ebml_w.emit_enum_variant("vtable_static", 0u, 3u, |ebml_w| {
                 ebml_w.emit_enum_variant_arg(0u, |ebml_w| {
                     Ok(ebml_w.emit_def_id(def_id))
                 });
                 ebml_w.emit_enum_variant_arg(1u, |ebml_w| {
-                    Ok(ebml_w.emit_tys(ecx, tys.as_slice()))
+                    Ok(ebml_w.emit_substs(ecx, substs))
                 });
                 ebml_w.emit_enum_variant_arg(2u, |ebml_w| {
                     Ok(encode_vtable_res(ecx, ebml_w, vtable_res))
@@ -744,7 +744,7 @@ fn read_vtable_origin(&mut self,
                             Ok(this.read_def_id_noxcx(cdata))
                         }).unwrap(),
                         this.read_enum_variant_arg(1u, |this| {
-                            Ok(this.read_tys_noxcx(tcx, cdata))
+                            Ok(this.read_substs_noxcx(tcx, cdata))
                         }).unwrap(),
                         this.read_enum_variant_arg(2u, |this| {
                             Ok(this.read_vtable_res(tcx, cdata))
@@ -962,11 +962,11 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
         })
     }
 
-    for tys in tcx.node_type_substs.borrow().find(&id).iter() {
-        ebml_w.tag(c::tag_table_node_type_subst, |ebml_w| {
+    for &item_substs in tcx.item_substs.borrow().find(&id).iter() {
+        ebml_w.tag(c::tag_table_item_subst, |ebml_w| {
             ebml_w.id(id);
             ebml_w.tag(c::tag_table_val, |ebml_w| {
-                ebml_w.emit_tys(ecx, tys.as_slice())
+                ebml_w.emit_substs(ecx, &item_substs.substs);
             })
         })
     }
@@ -1091,6 +1091,9 @@ fn read_ty_noxcx(&mut self,
     fn read_tys_noxcx(&mut self,
                       tcx: &ty::ctxt,
                       cdata: &cstore::crate_metadata) -> Vec<ty::t>;
+    fn read_substs_noxcx(&mut self, tcx: &ty::ctxt,
+                         cdata: &cstore::crate_metadata)
+                         -> ty::substs;
 }
 
 impl<'a> ebml_decoder_decoder_helpers for reader::Decoder<'a> {
@@ -1115,6 +1118,21 @@ fn read_tys_noxcx(&mut self,
             .collect()
     }
 
+    fn read_substs_noxcx(&mut self,
+                         tcx: &ty::ctxt,
+                         cdata: &cstore::crate_metadata)
+                         -> ty::substs
+    {
+        self.read_opaque(|_, doc| {
+            Ok(tydecode::parse_substs_data(
+                doc.data,
+                cdata.cnum,
+                doc.start,
+                tcx,
+                |_, id| decoder::translate_def_id(cdata, id)))
+        }).unwrap()
+    }
+
     fn read_ty(&mut self, xcx: &ExtendedDecodeContext) -> ty::t {
         // Note: regions types embed local node ids.  In principle, we
         // should translate these node ids into the new decode
@@ -1312,9 +1330,12 @@ fn decode_side_tables(xcx: &ExtendedDecodeContext,
                                id, ty_to_str(dcx.tcx, ty));
                         dcx.tcx.node_types.borrow_mut().insert(id as uint, ty);
                     }
-                    c::tag_table_node_type_subst => {
-                        let tys = val_dsr.read_tys(xcx);
-                        dcx.tcx.node_type_substs.borrow_mut().insert(id, tys);
+                    c::tag_table_item_subst => {
+                        let item_substs = ty::ItemSubsts {
+                            substs: val_dsr.read_substs(xcx)
+                        };
+                        dcx.tcx.item_substs.borrow_mut().insert(
+                            id, item_substs);
                     }
                     c::tag_table_freevars => {
                         let fv_info = val_dsr.read_to_vec(|val_dsr| {
index e63711f0a575a2b10e4806106ec3f5e81f6b1921..b88083c0df9abeb08537cdb856cbf653bf091b00 100644 (file)
@@ -245,10 +245,10 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
     {
         let method_map = cx.tcx.method_map.borrow();
         let method = method_map.find(&typeck::MethodCall::expr(e.id));
-        let node_type_substs = cx.tcx.node_type_substs.borrow();
+        let item_substs = cx.tcx.item_substs.borrow();
         let r = match method {
             Some(method) => Some(&method.substs.tps),
-            None => node_type_substs.find(&e.id)
+            None => item_substs.find(&e.id).map(|s| &s.substs.tps)
         };
         for ts in r.iter() {
             let def_map = cx.tcx.def_map.borrow();
@@ -341,15 +341,19 @@ fn check_trait_cast(cx: &mut Context, source_ty: ty::t, target_ty: ty::t, span:
 fn check_ty(cx: &mut Context, aty: &Ty) {
     match aty.node {
         TyPath(_, _, id) => {
-            let node_type_substs = cx.tcx.node_type_substs.borrow();
-            let r = node_type_substs.find(&id);
-            for ts in r.iter() {
-                let def_map = cx.tcx.def_map.borrow();
-                let did = ast_util::def_id_of_def(def_map.get_copy(&id));
-                let generics = ty::lookup_item_type(cx.tcx, did).generics;
-                let type_param_defs = generics.type_param_defs();
-                for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
-                    check_typaram_bounds(cx, aty.span, ty, type_param_def)
+            match cx.tcx.item_substs.borrow().find(&id) {
+                None => { }
+                Some(ref item_substs) => {
+                    let def_map = cx.tcx.def_map.borrow();
+                    let did = ast_util::def_id_of_def(def_map.get_copy(&id));
+                    let generics = ty::lookup_item_type(cx.tcx, did).generics;
+                    let type_param_defs = generics.type_param_defs();
+                    for (&ty, type_param_def) in
+                        item_substs.substs.tps.iter().zip(
+                            type_param_defs.iter())
+                    {
+                        check_typaram_bounds(cx, aty.span, ty, type_param_def)
+                    }
                 }
             }
         }
index e964bc5d6b0bc53f0cafd1e96d9ba9a12c29d75a..59ff1f804036da62b3a3600c77d2c9516faf36fe 100644 (file)
@@ -195,6 +195,17 @@ fn subst_spanned(&self, tcx: &ty::ctxt,
     }
 }
 
+impl Subst for ty::ItemSubsts {
+    fn subst_spanned(&self, tcx: &ty::ctxt,
+                     substs: &ty::substs,
+                     span: Option<Span>)
+                     -> ty::ItemSubsts {
+        ty::ItemSubsts {
+            substs: self.substs.subst_spanned(tcx, substs, span)
+        }
+    }
+}
+
 impl Subst for ty::RegionSubsts {
     fn subst_spanned(&self, tcx: &ty::ctxt,
                      substs: &ty::substs,
index 400aa83a615143a04092b8c38428290c468c947c..6c4566c09aa7aabfc40a4bf92b6df01d8d90f992 100644 (file)
@@ -478,7 +478,7 @@ pub fn note_unique_llvm_symbol(ccx: &CrateContext, sym: ~str) {
 pub fn get_res_dtor(ccx: &CrateContext,
                     did: ast::DefId,
                     parent_id: ast::DefId,
-                    substs: &[ty::t])
+                    substs: &ty::substs)
                  -> ValueRef {
     let _icx = push_ctxt("trans_res_dtor");
     let did = if did.krate != ast::LOCAL_CRATE {
@@ -486,16 +486,12 @@ pub fn get_res_dtor(ccx: &CrateContext,
     } else {
         did
     };
-    if !substs.is_empty() {
+
+    if !substs.tps.is_empty() || !substs.self_ty.is_none() {
         assert_eq!(did.krate, ast::LOCAL_CRATE);
-        let tsubsts = ty::substs {
-            regions: ty::ErasedRegions,
-            self_ty: None,
-            tps: Vec::from_slice(substs),
-        };
 
-        let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, &tsubsts);
-        let (val, _) = monomorphize::monomorphic_fn(ccx, did, &tsubsts, vtables, None, None);
+        let vtables = typeck::check::vtable::trans_resolve_method(ccx.tcx(), did.node, substs);
+        let (val, _) = monomorphize::monomorphic_fn(ccx, did, substs, vtables, None, None);
 
         val
     } else if did.krate == ast::LOCAL_CRATE {
@@ -503,10 +499,8 @@ pub fn get_res_dtor(ccx: &CrateContext,
     } else {
         let tcx = ccx.tcx();
         let name = csearch::get_symbol(&ccx.sess().cstore, did);
-        let class_ty = ty::subst_tps(tcx,
-                                     substs,
-                                     None,
-                                     ty::lookup_item_type(tcx, parent_id).ty);
+        let class_ty = ty::subst(tcx, substs,
+                                 ty::lookup_item_type(tcx, parent_id).ty);
         let llty = type_of_dtor(ccx, class_ty);
 
         get_extern_fn(&mut *ccx.externs.borrow_mut(), ccx.llmod, name,
@@ -670,7 +664,7 @@ fn iter_variant<'r,
                     repr: &adt::Repr,
                     av: ValueRef,
                     variant: &ty::VariantInfo,
-                    tps: &[ty::t],
+                    substs: &ty::substs,
                     f: val_and_ty_fn<'r,'b>)
                     -> &'b Block<'b> {
         let _icx = push_ctxt("iter_variant");
@@ -680,7 +674,7 @@ fn iter_variant<'r,
         for (i, &arg) in variant.args.iter().enumerate() {
             cx = f(cx,
                    adt::trans_field_ptr(cx, repr, av, variant.disr_val, i),
-                   ty::subst_tps(tcx, tps, None, arg));
+                   ty::subst(tcx, substs, arg));
         }
         return cx;
     }
@@ -722,7 +716,7 @@ fn iter_variant<'r,
           match adt::trans_switch(cx, &*repr, av) {
               (_match::single, None) => {
                   cx = iter_variant(cx, &*repr, av, &**variants.get(0),
-                                    substs.tps.as_slice(), f);
+                                    substs, f);
               }
               (_match::switch, Some(lldiscrim_a)) => {
                   cx = f(cx, lldiscrim_a, ty::mk_int());
@@ -748,7 +742,7 @@ fn iter_variant<'r,
                                        &*repr,
                                        av,
                                        &**variant,
-                                       substs.tps.as_slice(),
+                                       substs,
                                        |x,y,z| f(x,y,z));
                       Br(variant_cx, next_cx.llbb);
                   }
@@ -1153,15 +1147,7 @@ pub fn new_fn_ctxt<'a>(ccx: &'a CrateContext,
            },
            id, param_substs.map(|s| s.repr(ccx.tcx())));
 
-    let substd_output_type = match param_substs {
-        None => output_type,
-        Some(substs) => {
-            ty::subst_tps(ccx.tcx(),
-                          substs.tys.as_slice(),
-                          substs.self_ty,
-                          output_type)
-        }
-    };
+    let substd_output_type = output_type.substp(ccx.tcx(), param_substs);
     let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
     let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
 
@@ -1213,15 +1199,7 @@ pub fn init_function<'a>(fcx: &'a FunctionContext<'a>,
 
     // This shouldn't need to recompute the return type,
     // as new_fn_ctxt did it already.
-    let substd_output_type = match fcx.param_substs {
-        None => output_type,
-        Some(substs) => {
-            ty::subst_tps(fcx.ccx.tcx(),
-                          substs.tys.as_slice(),
-                          substs.self_ty,
-                          output_type)
-        }
-    };
+    let substd_output_type = output_type.substp(fcx.ccx.tcx(), fcx.param_substs);
 
     if !return_type_is_void(fcx.ccx, substd_output_type) {
         // If the function returns nil/bot, there is no real return
@@ -1508,18 +1486,8 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
                                            disr: ty::Disr,
                                            param_substs: Option<&param_substs>,
                                            llfndecl: ValueRef) {
-    let ctor_ty = {
-        let no_substs: &[ty::t] = [];
-        let ty_param_substs: &[ty::t] = match param_substs {
-            Some(substs) => substs.tys.as_slice(),
-            None => no_substs
-        };
-
-        ty::subst_tps(ccx.tcx(),
-                      ty_param_substs,
-                      None,
-                      ty::node_id_to_type(ccx.tcx(), ctor_id))
-    };
+    let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
+    let ctor_ty = ctor_ty.substp(ccx.tcx(), param_substs);
 
     let result_ty = match ty::get(ctor_ty).sty {
         ty::ty_bare_fn(ref bft) => bft.sig.output,
index e1763ab3ff16481c7d0d73721fa89ff8d9045747..f32aa62d861d36796595a63de65709b54146a6cd 100644 (file)
@@ -159,36 +159,36 @@ fn trans_def<'a>(bcx: &'a Block<'a>, def: ast::Def, ref_expr: &ast::Expr)
 
 pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) -> ValueRef {
     /*!
-     *
      * Translates a reference (with id `ref_id`) to the fn/method
      * with id `def_id` into a function pointer.  This may require
-     * monomorphization or inlining. */
+     * monomorphization or inlining.
+     */
 
     let _icx = push_ctxt("trans_fn_ref");
 
-    let type_params = node_id_type_params(bcx, node);
+    let substs = node_id_substs(bcx, node);
     let vtable_key = match node {
         ExprId(id) => MethodCall::expr(id),
         MethodCall(method_call) => method_call
     };
     let vtables = node_vtables(bcx, vtable_key);
-    debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
-           def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
+    debug!("trans_fn_ref(def_id={}, node={:?}, substs={}, vtables={})",
+           def_id.repr(bcx.tcx()),
+           node,
+           substs.repr(bcx.tcx()),
            vtables.repr(bcx.tcx()));
-    trans_fn_ref_with_vtables(bcx, def_id, node,
-                              type_params,
-                              vtables)
+    trans_fn_ref_with_vtables(bcx, def_id, node, substs, vtables)
 }
 
 fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
                                            def_id: ast::DefId,
                                            ref_id: ast::NodeId,
-                                           type_params: Vec<ty::t>,
+                                           substs: ty::substs,
                                            vtables: Option<typeck::vtable_res>)
                                            -> Callee<'a> {
     Callee {bcx: bcx,
             data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ExprId(ref_id),
-                                               type_params, vtables))}
+                                               substs, vtables))}
 }
 
 fn resolve_default_method_vtables(bcx: &Block,
@@ -204,8 +204,7 @@ fn resolve_default_method_vtables(bcx: &Block,
     // Build up a param_substs that we are going to resolve the
     // trait_vtables under.
     let param_substs = param_substs {
-        tys: substs.tps.clone(),
-        self_ty: substs.self_ty,
+        substs: (*substs).clone(),
         vtables: impl_vtables.clone(),
         self_vtables: None
     };
@@ -241,7 +240,7 @@ pub fn trans_fn_ref_with_vtables(
         bcx: &Block,       //
         def_id: ast::DefId,   // def id of fn
         node: ExprOrMethodCall,  // node id of use of fn; may be zero if N/A
-        type_params: Vec<ty::t>, // values for fn's ty params
+        substs: ty::substs, // values for fn's ty params
         vtables: Option<typeck::vtable_res>) // vtables for the call
      -> ValueRef {
     /*!
@@ -255,7 +254,7 @@ pub fn trans_fn_ref_with_vtables(
      * - `node`: node id of the reference to the fn/method, if applicable.
      *   This parameter may be zero; but, if so, the resulting value may not
      *   have the right type, so it must be cast before being used.
-     * - `type_params`: values for each of the fn/method's type parameters
+     * - `substs`: values for each of the fn/method's parameters
      * - `vtables`: values for each bound on each of the type parameters
      */
 
@@ -264,24 +263,18 @@ pub fn trans_fn_ref_with_vtables(
     let tcx = bcx.tcx();
 
     debug!("trans_fn_ref_with_vtables(bcx={}, def_id={}, node={:?}, \
-            type_params={}, vtables={})",
+            substs={}, vtables={})",
            bcx.to_str(),
            def_id.repr(tcx),
            node,
-           type_params.repr(tcx),
+           substs.repr(tcx),
            vtables.repr(tcx));
 
-    assert!(type_params.iter().all(|t| !ty::type_needs_infer(*t)));
+    assert!(substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
 
     // Polytype of the function item (may have type params)
     let fn_tpt = ty::lookup_item_type(tcx, def_id);
 
-    let substs = ty::substs {
-        regions: ty::ErasedRegions,
-        self_ty: None,
-        tps: type_params
-    };
-
     // Load the info for the appropriate trait if necessary.
     match ty::trait_of_method(tcx, def_id) {
         None => {}
@@ -510,7 +503,7 @@ pub fn trans_lang_call<'a>(
                                 trans_fn_ref_with_vtables_to_callee(bcx,
                                                                     did,
                                                                     0,
-                                                                    vec!(),
+                                                                    ty::substs::empty(),
                                                                     None)
                              },
                              ArgVals(args),
index 24abf1fd3f1bb8d3d2fef46c98c8d1d55b94cfe3..e438477a4a3f816e617445314f832566ba5d1eb4 100644 (file)
@@ -25,6 +25,7 @@
 use middle::trans::debuginfo;
 use middle::trans::type_::Type;
 use middle::ty;
+use middle::subst::Subst;
 use middle::typeck;
 use util::ppaux::Repr;
 use util::nodemap::NodeMap;
@@ -177,23 +178,24 @@ pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
 // Here `self_ty` is the real type of the self parameter to this method. It
 // will only be set in the case of default methods.
 pub struct param_substs {
-    pub tys: Vec<ty::t> ,
-    pub self_ty: Option<ty::t>,
+    pub substs: ty::substs,
     pub vtables: Option<typeck::vtable_res>,
     pub self_vtables: Option<typeck::vtable_param_res>
 }
 
 impl param_substs {
     pub fn validate(&self) {
-        for t in self.tys.iter() { assert!(!ty::type_needs_infer(*t)); }
-        for t in self.self_ty.iter() { assert!(!ty::type_needs_infer(*t)); }
+        for t in self.substs.tps.iter() {
+            assert!(!ty::type_needs_infer(*t));
+        }
+        for t in self.substs.self_ty.iter() {
+            assert!(!ty::type_needs_infer(*t));
+        }
     }
 }
 
 fn param_substs_to_str(this: &param_substs, tcx: &ty::ctxt) -> ~str {
-    format!("param_substs \\{tys:{}, vtables:{}\\}",
-         this.tys.repr(tcx),
-         this.vtables.repr(tcx))
+    format!("param_substs({})", this.substs.repr(tcx))
 }
 
 impl Repr for param_substs {
@@ -202,6 +204,25 @@ fn repr(&self, tcx: &ty::ctxt) -> ~str {
     }
 }
 
+pub trait SubstP {
+    fn substp(&self, tcx: &ty::ctxt, param_substs: Option<&param_substs>)
+              -> Self;
+}
+
+impl<T:Subst+Clone> SubstP for T {
+    fn substp(&self, tcx: &ty::ctxt, param_substs: Option<&param_substs>)
+              -> T {
+        match param_substs {
+            Some(substs) => {
+                self.subst(tcx, &substs.substs)
+            }
+            None => {
+                (*self).clone()
+            }
+        }
+    }
+}
+
 // work around bizarre resolve errors
 pub type RvalueDatum = datum::Datum<datum::Rvalue>;
 pub type LvalueDatum = datum::Datum<datum::Lvalue>;
@@ -676,7 +697,7 @@ pub fn is_null(val: ValueRef) -> bool {
 pub fn monomorphize_type(bcx: &Block, t: ty::t) -> ty::t {
     match bcx.fcx.param_substs {
         Some(ref substs) => {
-            ty::subst_tps(bcx.tcx(), substs.tys.as_slice(), substs.self_ty, t)
+            ty::subst(bcx.tcx(), &substs.substs, t)
         }
         _ => {
             assert!(!ty::type_has_params(t));
@@ -710,32 +731,28 @@ pub enum ExprOrMethodCall {
     MethodCall(typeck::MethodCall)
 }
 
-pub fn node_id_type_params(bcx: &Block, node: ExprOrMethodCall) -> Vec<ty::t> {
+pub fn node_id_substs(bcx: &Block,
+                      node: ExprOrMethodCall)
+                      -> ty::substs {
     let tcx = bcx.tcx();
-    let params = match node {
-        ExprId(id) => ty::node_id_to_type_params(tcx, id),
+
+    let substs = match node {
+        ExprId(id) => {
+            ty::node_id_item_substs(tcx, id).substs
+        }
         MethodCall(method_call) => {
-            tcx.method_map.borrow().get(&method_call).substs.tps.clone()
+            tcx.method_map.borrow().get(&method_call).substs.clone()
         }
     };
 
-    if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
+    if !substs.tps.iter().all(|t| !ty::type_needs_infer(*t)) {
         bcx.sess().bug(
             format!("type parameters for node {:?} include inference types: {}",
-                 node, params.iter()
-                             .map(|t| bcx.ty_to_str(*t))
-                             .collect::<Vec<~str>>()
-                             .connect(",")));
+                    node,
+                    substs.repr(bcx.tcx())));
     }
 
-    match bcx.fcx.param_substs {
-        Some(ref substs) => {
-            params.iter().map(|t| {
-                ty::subst_tps(tcx, substs.tys.as_slice(), substs.self_ty, *t)
-            }).collect()
-        }
-        _ => params
-    }
+    substs.substp(tcx, bcx.fcx.param_substs)
 }
 
 pub fn node_vtables(bcx: &Block, id: typeck::MethodCall)
@@ -785,20 +802,10 @@ pub fn resolve_vtable_under_param_substs(tcx: &ty::ctxt,
                                          vt: &typeck::vtable_origin)
                                          -> typeck::vtable_origin {
     match *vt {
-        typeck::vtable_static(trait_id, ref tys, ref sub) => {
-            let tys = match param_substs {
-                Some(substs) => {
-                    tys.iter().map(|t| {
-                        ty::subst_tps(tcx,
-                                      substs.tys.as_slice(),
-                                      substs.self_ty,
-                                      *t)
-                    }).collect()
-                }
-                _ => Vec::from_slice(tys.as_slice())
-            };
+        typeck::vtable_static(trait_id, ref vtable_substs, ref sub) => {
+            let vtable_substs = vtable_substs.substp(tcx, param_substs);
             typeck::vtable_static(
-                trait_id, tys,
+                trait_id, vtable_substs,
                 resolve_vtables_under_param_substs(tcx, param_substs, sub.as_slice()))
         }
         typeck::vtable_param(n_param, n_bound) => {
index fe92105118936d0f061da3d33340a5394e8f34f8..304aa9b4025b532a1ca55764eccb00fc815b1d51 100644 (file)
@@ -793,16 +793,7 @@ fn get_function_signature(cx: &CrateContext,
                 assert_type_for_node_id(cx, fn_ast_id, error_span);
 
                 let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
-                let return_type = match param_substs {
-                    None => return_type,
-                    Some(substs) => {
-                        ty::subst_tps(cx.tcx(),
-                                      substs.tys.as_slice(),
-                                      substs.self_ty,
-                                      return_type)
-                    }
-                };
-
+                let return_type = return_type.substp(cx.tcx(), param_substs);
                 signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
             }
         }
@@ -811,16 +802,7 @@ fn get_function_signature(cx: &CrateContext,
         for arg in fn_decl.inputs.iter() {
             assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
             let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
-            let arg_type = match param_substs {
-                None => arg_type,
-                Some(substs) => {
-                    ty::subst_tps(cx.tcx(),
-                                  substs.tys.as_slice(),
-                                  substs.self_ty,
-                                  arg_type)
-                }
-            };
-
+            let arg_type = arg_type.substp(cx.tcx(), param_substs);
             signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
         }
 
@@ -834,7 +816,7 @@ fn get_template_parameters(cx: &CrateContext,
                                name_to_append_suffix_to: &mut StrBuf)
                                -> DIArray {
         let self_type = match param_substs {
-            Some(param_substs) => param_substs.self_ty,
+            Some(param_substs) => param_substs.substs.self_ty,
             _ => None
         };
 
@@ -890,7 +872,7 @@ fn get_template_parameters(cx: &CrateContext,
 
         // Handle other generic parameters
         let actual_types = match param_substs {
-            Some(param_substs) => &param_substs.tys,
+            Some(param_substs) => &param_substs.substs.tps,
             None => {
                 return create_DIArray(DIB(cx), template_params.as_slice());
             }
index 1bde80815c33f5c27db145d727df5296fad2644b..4f03ec0567cfb43a6beaabf2a28e710b95744422 100644 (file)
@@ -236,7 +236,7 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>,
 
     // Find and call the actual destructor
     let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did,
-                                 class_did, substs.tps.as_slice());
+                                 class_did, substs);
 
     // The second argument is the "self" argument for drop
     let params = unsafe {
index 86fde5d821a00b4050c2900a4db5da43e0842eb6..cd28d314772127d158b06e7cca1e6043c71b3866 100644 (file)
@@ -295,7 +295,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             RetVoid(bcx);
         }
         "size_of" => {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             let lltp_ty = type_of::type_of(ccx, tp_ty);
             Ret(bcx, C_uint(ccx, machine::llsize_of_real(ccx, lltp_ty) as uint));
         }
@@ -305,7 +305,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             // if the value is non-immediate. Note that, with
             // intrinsics, there are no argument cleanups to
             // concern ourselves with, so we can use an rvalue datum.
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             let mode = appropriate_rvalue_mode(ccx, tp_ty);
             let src = Datum {val: get_param(decl, first_real_arg + 1u),
                              ty: tp_ty,
@@ -314,17 +314,17 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             RetVoid(bcx);
         }
         "min_align_of" => {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             let lltp_ty = type_of::type_of(ccx, tp_ty);
             Ret(bcx, C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty) as uint));
         }
         "pref_align_of"=> {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             let lltp_ty = type_of::type_of(ccx, tp_ty);
             Ret(bcx, C_uint(ccx, machine::llalign_of_pref(ccx, lltp_ty) as uint));
         }
         "get_tydesc" => {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             let static_ti = get_tydesc(ccx, tp_ty);
             glue::lazily_emit_visit_glue(ccx, &*static_ti);
 
@@ -339,7 +339,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
         "type_id" => {
             let hash = ty::hash_crate_independent(
                 ccx.tcx(),
-                *substs.tys.get(0),
+                *substs.substs.tps.get(0),
                 &ccx.link_meta.crate_hash);
             // NB: This needs to be kept in lockstep with the TypeId struct in
             //     libstd/unstable/intrinsics.rs
@@ -354,7 +354,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             }
         }
         "init" => {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             let lltp_ty = type_of::type_of(ccx, tp_ty);
             match bcx.fcx.llretptr.get() {
                 Some(ptr) => { Store(bcx, C_null(lltp_ty), ptr); RetVoid(bcx); }
@@ -364,7 +364,7 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
         }
         "uninit" => {
             // Do nothing, this is effectively a no-op
-            let retty = *substs.tys.get(0);
+            let retty = *substs.substs.tps.get(0);
             if type_is_immediate(ccx, retty) && !return_type_is_void(ccx, retty) {
                 unsafe {
                     Ret(bcx, lib::llvm::llvm::LLVMGetUndef(type_of(ccx, retty).to_ref()));
@@ -377,7 +377,8 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             RetVoid(bcx);
         }
         "transmute" => {
-            let (in_type, out_type) = (*substs.tys.get(0), *substs.tys.get(1));
+            let (in_type, out_type) = (*substs.substs.tps.get(0),
+                                       *substs.substs.tps.get(1));
             let llintype = type_of::type_of(ccx, in_type);
             let llouttype = type_of::type_of(ccx, out_type);
 
@@ -444,11 +445,11 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             }
         }
         "needs_drop" => {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             Ret(bcx, C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty)));
         }
         "owns_managed" => {
-            let tp_ty = *substs.tys.get(0);
+            let tp_ty = *substs.substs.tps.get(0);
             Ret(bcx, C_bool(ccx, ty::type_contents(ccx.tcx(), tp_ty).owns_managed()));
         }
         "visit_tydesc" => {
@@ -464,14 +465,20 @@ fn count_zeros_intrinsic(bcx: &Block, name: &'static str) {
             let lladdr = InBoundsGEP(bcx, ptr, [offset]);
             Ret(bcx, lladdr);
         }
-        "copy_nonoverlapping_memory" => copy_intrinsic(bcx, false, false, *substs.tys.get(0)),
-        "copy_memory" => copy_intrinsic(bcx, true, false, *substs.tys.get(0)),
-        "set_memory" => memset_intrinsic(bcx, false, *substs.tys.get(0)),
+        "copy_nonoverlapping_memory" => {
+            copy_intrinsic(bcx, false, false, *substs.substs.tps.get(0))
+        }
+        "copy_memory" => {
+            copy_intrinsic(bcx, true, false, *substs.substs.tps.get(0))
+        }
+        "set_memory" => {
+            memset_intrinsic(bcx, false, *substs.substs.tps.get(0))
+        }
 
         "volatile_copy_nonoverlapping_memory" =>
-            copy_intrinsic(bcx, false, true, *substs.tys.get(0)),
-        "volatile_copy_memory" => copy_intrinsic(bcx, true, true, *substs.tys.get(0)),
-        "volatile_set_memory" => memset_intrinsic(bcx, true, *substs.tys.get(0)),
+            copy_intrinsic(bcx, false, true, *substs.substs.tps.get(0)),
+        "volatile_copy_memory" => copy_intrinsic(bcx, true, true, *substs.substs.tps.get(0)),
+        "volatile_set_memory" => memset_intrinsic(bcx, true, *substs.substs.tps.get(0)),
 
         "ctlz8" => count_zeros_intrinsic(bcx, "llvm.ctlz.i8"),
         "ctlz16" => count_zeros_intrinsic(bcx, "llvm.ctlz.i16"),
index b13444a4410aed6d5a9529dfad36e82b9aad32bb..e735fd21034f728bb18338da3e871ea173f85522 100644 (file)
@@ -198,7 +198,7 @@ pub fn trans_static_method_callee(bcx: &Block,
 
     match vtbls.move_iter().nth(bound_index).unwrap().move_iter().nth(0).unwrap() {
         typeck::vtable_static(impl_did, rcvr_substs, rcvr_origins) => {
-            assert!(rcvr_substs.iter().all(|t| !ty::type_needs_infer(*t)));
+            assert!(rcvr_substs.tps.iter().all(|t| !ty::type_needs_infer(*t)));
 
             let mth_id = method_with_name(ccx, impl_did, mname);
             let (callee_substs, callee_origins) =
@@ -277,39 +277,41 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
 fn combine_impl_and_methods_tps(bcx: &Block,
                                 mth_did: ast::DefId,
                                 node: ExprOrMethodCall,
-                                rcvr_substs: Vec<ty::t>,
+                                rcvr_substs: ty::substs,
                                 rcvr_origins: typeck::vtable_res)
-                                -> (Vec<ty::t>, typeck::vtable_res) {
+                                -> (ty::substs, typeck::vtable_res)
+{
     /*!
-    *
-    * Creates a concatenated set of substitutions which includes
-    * those from the impl and those from the method.  This are
-    * some subtle complications here.  Statically, we have a list
-    * of type parameters like `[T0, T1, T2, M1, M2, M3]` where
-    * `Tn` are type parameters that appear on the receiver.  For
-    * example, if the receiver is a method parameter `A` with a
-    * bound like `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
-    *
-    * The weird part is that the type `A` might now be bound to
-    * any other type, such as `foo<X>`.  In that case, the vector
-    * we want is: `[X, M1, M2, M3]`.  Therefore, what we do now is
-    * to slice off the method type parameters and append them to
-    * the type parameters from the type that the receiver is
-    * mapped to. */
+     * Creates a concatenated set of substitutions which includes
+     * those from the impl and those from the method.  This are
+     * some subtle complications here.  Statically, we have a list
+     * of type parameters like `[T0, T1, T2, M1, M2, M3]` where
+     * `Tn` are type parameters that appear on the receiver.  For
+     * example, if the receiver is a method parameter `A` with a
+     * bound like `trait<B,C,D>` then `Tn` would be `[B,C,D]`.
+     *
+     * The weird part is that the type `A` might now be bound to
+     * any other type, such as `foo<X>`.  In that case, the vector
+     * we want is: `[X, M1, M2, M3]`.  Therefore, what we do now is
+     * to slice off the method type parameters and append them to
+     * the type parameters from the type that the receiver is
+     * mapped to.
+     */
 
     let ccx = bcx.ccx();
     let method = ty::method(ccx.tcx(), mth_did);
     let n_m_tps = method.generics.type_param_defs().len();
-    let node_substs = node_id_type_params(bcx, node);
+    let node_substs = node_id_substs(bcx, node);
     debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx()));
     debug!("node_substs={:?}", node_substs.repr(ccx.tcx()));
-    let mut ty_substs = rcvr_substs;
+    let rcvr_self_ty = rcvr_substs.self_ty;
+    let mut tps = rcvr_substs.tps;
     {
-        let start = node_substs.len() - n_m_tps;
-        ty_substs.extend(node_substs.move_iter().skip(start));
+        let start = node_substs.tps.len() - n_m_tps;
+        tps.extend(node_substs.tps.move_iter().skip(start));
     }
     debug!("n_m_tps={:?}", n_m_tps);
-    debug!("ty_substs={:?}", ty_substs.repr(ccx.tcx()));
+    debug!("tps={}", tps.repr(ccx.tcx()));
 
 
     // Now, do the same work for the vtables.  The vtables might not
@@ -333,6 +335,12 @@ fn combine_impl_and_methods_tps(bcx: &Block,
         }
     }
 
+    let ty_substs = ty::substs {
+        tps: tps,
+        regions: ty::ErasedRegions,
+        self_ty: rcvr_self_ty
+    };
+
     (ty_substs, vtables)
 }
 
@@ -485,7 +493,7 @@ pub fn make_vtable<I: Iterator<ValueRef>>(ccx: &CrateContext,
 
 fn emit_vtable_methods(bcx: &Block,
                        impl_id: ast::DefId,
-                       substs: Vec<ty::t>,
+                       substs: ty::substs,
                        vtables: typeck::vtable_res)
                        -> Vec<ValueRef> {
     let ccx = bcx.ccx();
index 4fd4f2f9d6ef0e635a147e737f71e85984127df1..69f1dcbc67cd4172bc1980119d74c7e1632a4b74 100644 (file)
@@ -85,9 +85,8 @@ pub fn monomorphic_fn(ccx: &CrateContext,
     }
 
     let psubsts = param_substs {
-        tys: real_substs.tps.clone(),
+        substs: (*real_substs).clone(),
         vtables: vtables,
-        self_ty: real_substs.self_ty.clone(),
         self_vtables: self_vtables
     };
 
@@ -139,8 +138,7 @@ pub fn monomorphic_fn(ccx: &CrateContext,
 
     debug!("monomorphic_fn about to subst into {}", llitem_ty.repr(ccx.tcx()));
     let mono_ty = match is_static_provided {
-        None => ty::subst_tps(ccx.tcx(), real_substs.tps.as_slice(),
-                              real_substs.self_ty, llitem_ty),
+        None => ty::subst(ccx.tcx(), real_substs, llitem_ty),
         Some(num_method_ty_params) => {
             // Static default methods are a little unfortunate, in
             // that the "internal" and "external" type of them differ.
@@ -157,13 +155,19 @@ pub fn monomorphic_fn(ccx: &CrateContext,
             // This is a bit unfortunate.
 
             let idx = real_substs.tps.len() - num_method_ty_params;
-            let substs = Vec::from_slice(real_substs.tps.slice(0, idx))
-                         .append([real_substs.self_ty.unwrap()])
-                         .append(real_substs.tps.tailn(idx));
+            let mut tps = Vec::new();
+            tps.push_all(real_substs.tps.slice(0, idx));
+            tps.push(real_substs.self_ty.unwrap());
+            tps.push_all(real_substs.tps.tailn(idx));
+
+            let substs = ty::substs { regions: ty::ErasedRegions,
+                                      self_ty: None,
+                                      tps: tps };
+
             debug!("static default: changed substitution to {}",
                    substs.repr(ccx.tcx()));
 
-            ty::subst_tps(ccx.tcx(), substs.as_slice(), None, llitem_ty)
+            ty::subst(ccx.tcx(), &substs, llitem_ty)
         }
     };
 
@@ -334,7 +338,10 @@ pub fn make_vtable_id(ccx: &CrateContext,
         &typeck::vtable_static(impl_id, ref substs, ref sub_vtables) => {
             MonoId {
                 def: impl_id,
-                params: sub_vtables.iter().zip(substs.iter()).map(|(vtable, subst)| {
+                // FIXME(NDM) -- this is pretty bogus. It ignores self-type,
+                // and vtables are not necessary, AND they are not guaranteed
+                // to be same length as the number of TPS ANYHOW!
+                params: sub_vtables.iter().zip(substs.tps.iter()).map(|(vtable, subst)| {
                     MonoParamId {
                         subst: *subst,
                         // Do we really need the vtables to be hashed? Isn't the type enough?
index 7067ce888368bccca1da038c7ad7746c7a98f125..e61961f999c8e241d9620c9af3adae34ff5d0a3a 100644 (file)
@@ -255,9 +255,9 @@ pub struct ctxt {
 
     // Stores the type parameters which were substituted to obtain the type
     // of this node.  This only applies to nodes that refer to entities
-    // parameterized by type parameters, such as generic fns, types, or
+    // param<eterized by type parameters, such as generic fns, types, or
     // other items.
-    pub node_type_substs: RefCell<NodeMap<Vec<t>>>,
+    pub item_substs: RefCell<NodeMap<ItemSubsts>>,
 
     // Maps from a method to the method "descriptor"
     pub methods: RefCell<DefIdMap<Rc<Method>>>,
@@ -1060,6 +1060,13 @@ pub struct TraitDef {
     pub trait_ref: Rc<ty::TraitRef>,
 }
 
+/// Records the substitutions used to translate the polytype for an
+/// item into the monotype of an item reference.
+#[deriving(Clone)]
+pub struct ItemSubsts {
+    pub substs: ty::substs,
+}
+
 pub struct ty_param_substs_and_ty {
     pub substs: ty::substs,
     pub ty: ty::t
@@ -1086,7 +1093,7 @@ pub fn mk_ctxt(s: Session,
         def_map: dm,
         region_maps: region_maps,
         node_types: RefCell::new(HashMap::new()),
-        node_type_substs: RefCell::new(NodeMap::new()),
+        item_substs: RefCell::new(NodeMap::new()),
         trait_refs: RefCell::new(NodeMap::new()),
         trait_defs: RefCell::new(DefIdMap::new()),
         map: map,
@@ -1510,47 +1517,13 @@ pub fn walk_regions_and_ty(cx: &ctxt, ty: t, fldr: |r: Region|, fldt: |t: t|)
                                    |t| { fldt(t); t }).fold_ty(ty)
 }
 
-// Substitute *only* type parameters.  Used in trans where regions are erased.
-pub fn subst_tps(tcx: &ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
-    let mut subst = TpsSubst { tcx: tcx, self_ty_opt: self_ty_opt, tps: tps };
-    return subst.fold_ty(typ);
-
-    struct TpsSubst<'a> {
-        tcx: &'a ctxt,
-        self_ty_opt: Option<t>,
-        tps: &'a [t],
+impl ItemSubsts {
+    pub fn empty() -> ItemSubsts {
+        ItemSubsts { substs: substs::empty() }
     }
 
-    impl<'a> TypeFolder for TpsSubst<'a> {
-        fn tcx<'a>(&'a self) -> &'a ctxt { self.tcx }
-
-        fn fold_ty(&mut self, t: ty::t) -> ty::t {
-            if self.tps.len() == 0u && self.self_ty_opt.is_none() {
-                return t;
-            }
-
-            let tb = ty::get(t);
-            if self.self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) {
-                return t;
-            }
-
-            match ty::get(t).sty {
-                ty_param(p) => {
-                    self.tps[p.idx]
-                }
-
-                ty_self(_) => {
-                    match self.self_ty_opt {
-                        None => self.tcx.sess.bug("ty_self unexpected here"),
-                        Some(self_ty) => self_ty
-                    }
-                }
-
-                _ => {
-                    ty_fold::super_fold_ty(self, t)
-                }
-            }
-        }
+    pub fn is_noop(&self) -> bool {
+        ty::substs_is_noop(&self.substs)
     }
 }
 
@@ -2669,11 +2642,10 @@ pub fn node_id_to_type_opt(cx: &ctxt, id: ast::NodeId) -> Option<t> {
     }
 }
 
-// FIXME(pcwalton): Makes a copy, bleh. Probably better to not do that.
-pub fn node_id_to_type_params(cx: &ctxt, id: ast::NodeId) -> Vec<t> {
-    match cx.node_type_substs.borrow().find(&id) {
-      None => return Vec::new(),
-      Some(ts) => return (*ts).clone(),
+pub fn node_id_item_substs(cx: &ctxt, id: ast::NodeId) -> ItemSubsts {
+    match cx.item_substs.borrow().find(&id) {
+      None => ItemSubsts::empty(),
+      Some(ts) => ts.clone(),
     }
 }
 
@@ -2991,21 +2963,6 @@ pub fn map_region(&self, f: |Region| -> Region) -> AutoRef {
     }
 }
 
-pub struct ParamsTy {
-    pub params: Vec<t>,
-    pub ty: t
-}
-
-#[allow(dead_code)] // this may be useful?
-pub fn expr_ty_params_and_ty(cx: &ctxt,
-                             expr: &ast::Expr)
-                          -> ParamsTy {
-    ParamsTy {
-        params: node_id_to_type_params(cx, expr.id),
-        ty: node_id_to_type(cx, expr.id)
-    }
-}
-
 pub fn method_call_type_param_defs(tcx: &ctxt, origin: typeck::MethodOrigin)
                                    -> Rc<Vec<TypeParameterDef>> {
     match origin {
index bf5874e133661f7b0a0aaddb3a0dc715d7b92043..472386209e399291ce9f0bbd3deef550f5f2966e 100644 (file)
@@ -52,7 +52,7 @@
 
 While type checking a function, the intermediate types for the
 expressions, blocks, and so forth contained within the function are
-stored in `fcx.node_types` and `fcx.node_type_substs`.  These types
+stored in `fcx.node_types` and `fcx.item_substs`.  These types
 may contain unresolved type variables.  After type checking is
 complete, the functions in the writeback module are used to take the
 types from this table, resolve them, and then write them into their
@@ -161,7 +161,7 @@ pub struct Inherited<'a> {
 
     // Temporary tables:
     node_types: RefCell<NodeMap<ty::t>>,
-    node_type_substs: RefCell<NodeMap<ty::substs>>,
+    item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
     adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
     method_map: MethodMap,
     vtable_map: vtable_map,
@@ -268,7 +268,7 @@ fn new(tcx: &'a ty::ctxt,
             locals: RefCell::new(NodeMap::new()),
             param_env: param_env,
             node_types: RefCell::new(NodeMap::new()),
-            node_type_substs: RefCell::new(NodeMap::new()),
+            item_substs: RefCell::new(NodeMap::new()),
             adjustments: RefCell::new(NodeMap::new()),
             method_map: RefCell::new(FnvHashMap::new()),
             vtable_map: RefCell::new(FnvHashMap::new()),
@@ -1111,22 +1111,22 @@ pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
         self.inh.node_types.borrow_mut().insert(node_id, ty);
     }
 
-    pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::substs) {
-        if !ty::substs_is_noop(&substs) {
+    pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
+        if !ty::substs_is_noop(&substs.substs) {
             debug!("write_substs({}, {}) in fcx {}",
                    node_id,
-                   ty::substs_to_str(self.tcx(), &substs),
+                   substs.repr(self.tcx()),
                    self.tag());
 
-            self.inh.node_type_substs.borrow_mut().insert(node_id, substs);
+            self.inh.item_substs.borrow_mut().insert(node_id, substs);
         }
     }
 
     pub fn write_ty_substs(&self,
                            node_id: ast::NodeId,
                            ty: ty::t,
-                           substs: ty::substs) {
-        let ty = ty::subst(self.tcx(), &substs, ty);
+                           substs: ty::ItemSubsts) {
+        let ty = ty::subst(self.tcx(), &substs.substs, ty);
         self.write_ty(node_id, ty);
         self.write_substs(node_id, substs);
     }
@@ -1204,8 +1204,8 @@ pub fn method_ty_substs(&self, id: ast::NodeId) -> ty::substs {
 
     pub fn opt_node_ty_substs(&self,
                               id: ast::NodeId,
-                              f: |&ty::substs|) {
-        match self.inh.node_type_substs.borrow().find(&id) {
+                              f: |&ty::ItemSubsts|) {
+        match self.inh.item_substs.borrow().find(&id) {
             Some(s) => { f(s) }
             None => { }
         }
@@ -3963,10 +3963,10 @@ pub fn instantiate_path(fcx: &FnCtxt,
         (tps, regions)
     };
 
-    fcx.write_ty_substs(node_id, tpt.ty, substs {
-        regions: regions,
-        self_ty: None,
-        tps: tps
+    fcx.write_ty_substs(node_id, tpt.ty, ty::ItemSubsts {
+        substs: substs { regions: regions,
+                         self_ty: None,
+                         tps: tps }
     });
 
     debug!("<<<");
index b6d7cddda474587fd2688b75fca2d8b84c967ea0..04facc1426dba4e34e25a8f7593e8656a42721a1 100644 (file)
@@ -15,6 +15,7 @@
 use middle::typeck::astconv::AstConv;
 use middle::typeck::check::{FnCtxt, impl_self_ty};
 use middle::typeck::check::{structurally_resolved_type};
+use middle::typeck::check::writeback;
 use middle::typeck::infer::fixup_err_to_str;
 use middle::typeck::infer::{resolve_and_force_all_but_regions, resolve_type};
 use middle::typeck::infer;
@@ -444,7 +445,7 @@ fn search_for_vtable(vcx: &VtableContext,
         // Finally, we register that we found a matching impl, and
         // record the def ID of the impl as well as the resolved list
         // of type substitutions for the target trait.
-        found.push(vtable_static(impl_did, substs_f.tps.clone(), subres));
+        found.push(vtable_static(impl_did, substs_f, subres));
     }
 
     match found.len() {
@@ -625,7 +626,7 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
     };
     match ex.node {
       ast::ExprPath(..) => {
-        fcx.opt_node_ty_substs(ex.id, |substs| {
+        fcx.opt_node_ty_substs(ex.id, |item_substs| {
             debug!("vtable resolution on parameter bounds for expr {}",
                    ex.repr(fcx.tcx()));
             let def = cx.tcx.def_map.borrow().get_copy(&ex.id);
@@ -639,7 +640,7 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
                 let vcx = fcx.vtable_context();
                 let vtbls = lookup_vtables(&vcx, ex.span,
                                            item_ty.generics.type_param_defs(),
-                                           substs, is_early);
+                                           &item_substs.substs, is_early);
                 if !is_early {
                     insert_vtables(fcx, MethodCall::expr(ex.id), vtbls);
                 }
@@ -733,8 +734,10 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
 pub fn resolve_impl(tcx: &ty::ctxt,
                     impl_item: &ast::Item,
                     impl_generics: &ty::Generics,
-                    impl_trait_ref: &ty::TraitRef)
-{
+                    impl_trait_ref: &ty::TraitRef) {
+    debug!("resolve_impl(impl_item.id={})",
+           impl_item.id);
+
     let param_env = ty::construct_parameter_environment(
         tcx,
         None,
@@ -745,6 +748,7 @@ pub fn resolve_impl(tcx: &ty::ctxt,
         impl_item.id);
 
     let impl_trait_ref = impl_trait_ref.subst(tcx, &param_env.free_substs);
+    debug!("impl_trait_ref={}", impl_trait_ref.repr(tcx));
 
     let infcx = &infer::new_infer_ctxt(tcx);
     let vcx = VtableContext { infcx: infcx, param_env: &param_env };
@@ -781,8 +785,13 @@ pub fn resolve_impl(tcx: &ty::ctxt,
         trait_vtables: vtbls,
         self_vtables: self_vtable_res
     };
+    let res = writeback::resolve_impl_res(infcx, impl_item.span, &res);
     let impl_def_id = ast_util::local_def(impl_item.id);
 
+    debug!("impl_vtables for {} are {}",
+           impl_def_id.repr(tcx),
+           res.repr(tcx));
+
     tcx.impl_vtables.borrow_mut().insert(impl_def_id, res);
 }
 
index 77429118a2c457cced57ab82c64f8aa3e0f10033..8c7a3fed21b4ec212fb79d5822dc599ff3a02cd6 100644 (file)
 use middle::typeck::infer::{force_all, resolve_all, resolve_region};
 use middle::typeck::infer::resolve_type;
 use middle::typeck::infer;
+use middle::typeck::impl_res;
 use middle::typeck::{MethodCall, MethodCallee};
 use middle::typeck::{vtable_origin, vtable_static, vtable_param};
 use middle::typeck::write_substs_to_tcx;
 use middle::typeck::write_ty_to_tcx;
 use util::ppaux::Repr;
 
+use std::cell::Cell;
+
 use syntax::ast;
 use syntax::codemap::Span;
 use syntax::print::pprust::pat_to_str;
@@ -61,6 +64,17 @@ pub fn resolve_type_vars_in_fn(fcx: &FnCtxt,
     wbcx.visit_upvar_borrow_map();
 }
 
+pub fn resolve_impl_res(infcx: &infer::InferCtxt,
+                        span: Span,
+                        impl_res: &impl_res)
+                        -> impl_res {
+    let errors = Cell::new(false); // nobody cares
+    let mut resolver = Resolver::from_infcx(infcx,
+                                            &errors,
+                                            ResolvingImplRes(span));
+    impl_res.resolve_in(&mut resolver)
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // The Writerback context. This visitor walks the AST, checking the
 // fn-specific tables to find references to types or regions. It
@@ -159,7 +173,7 @@ fn visit_local(&mut self, l: &ast::Local, _: ()) {
         }
 
         let var_ty = self.fcx.local_ty(l.span, l.id);
-        let var_ty = var_ty.resolve(self.fcx, ResolvingLocal(l.span));
+        let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
         write_ty_to_tcx(self.tcx(), l.id, var_ty);
         visit::walk_local(self, l, ());
     }
@@ -177,7 +191,7 @@ fn visit_upvar_borrow_map(&self) {
 
         for (upvar_id, upvar_borrow) in self.fcx.inh.upvar_borrow_map.borrow().iter() {
             let r = upvar_borrow.region;
-            let r = r.resolve(self.fcx, ResolvingUpvar(*upvar_id));
+            let r = self.resolve(&r, ResolvingUpvar(*upvar_id));
             let new_upvar_borrow = ty::UpvarBorrow { kind: upvar_borrow.kind,
                                                      region: r };
             debug!("Upvar borrow for {} resolved to {}",
@@ -194,17 +208,14 @@ fn visit_node_id(&self, reason: ResolveReason, id: ast::NodeId) {
 
         // Resolve the type of the node with id `id`
         let n_ty = self.fcx.node_ty(id);
-        let n_ty = n_ty.resolve(self.fcx, reason);
+        let n_ty = self.resolve(&n_ty, reason);
         write_ty_to_tcx(self.tcx(), id, n_ty);
         debug!("Node {} has type {}", id, n_ty.repr(self.tcx()));
 
         // Resolve any substitutions
-        self.fcx.opt_node_ty_substs(id, |node_substs| {
-            let mut new_tps = Vec::new();
-            for subst in node_substs.tps.iter() {
-                new_tps.push(subst.resolve(self.fcx, reason));
-            }
-            write_substs_to_tcx(self.tcx(), id, new_tps);
+        self.fcx.opt_node_ty_substs(id, |item_substs| {
+            write_substs_to_tcx(self.tcx(), id,
+                                self.resolve(item_substs, reason));
         });
     }
 
@@ -228,12 +239,12 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
                             }
                             _ => {
                                 self.tcx().sess.span_err(
-                                    reason.span(self.fcx),
+                                    reason.span(self.tcx()),
                                     "cannot coerce non-statically resolved bare fn")
                             }
                         }
 
-                        ty::AutoAddEnv(store.resolve(self.fcx, reason))
+                        ty::AutoAddEnv(self.resolve(&store, reason))
                     }
 
                     ty::AutoDerefRef(adj) => {
@@ -245,7 +256,7 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
 
                         ty::AutoDerefRef(ty::AutoDerefRef {
                             autoderefs: adj.autoderefs,
-                            autoref: adj.autoref.resolve(self.fcx, reason),
+                            autoref: self.resolve(&adj.autoref, reason),
                         })
                     }
 
@@ -269,8 +280,8 @@ fn visit_method_map_entry(&self,
                        method.repr(self.tcx()));
                 let mut new_method = MethodCallee {
                     origin: method.origin,
-                    ty: method.ty.resolve(self.fcx, reason),
-                    substs: method.substs.resolve(self.fcx, reason),
+                    ty: self.resolve(&method.ty, reason),
+                    substs: self.resolve(&method.substs, reason),
                 };
 
                 // Wack. For some reason I don't quite know, we always
@@ -297,7 +308,7 @@ fn visit_vtable_map_entry(&self,
         // Resolve any vtable map entry
         match self.fcx.inh.vtable_map.borrow_mut().pop(&vtable_key) {
             Some(origins) => {
-                let r_origins = origins.resolve(self.fcx, reason);
+                let r_origins = self.resolve(&origins, reason);
                 debug!("writeback::resolve_vtable_map_entry(\
                         vtable_key={}, vtables={:?})",
                        vtable_key, r_origins.repr(self.tcx()));
@@ -306,6 +317,10 @@ fn visit_vtable_map_entry(&self,
             None => {}
         }
     }
+
+    fn resolve<T:ResolveIn>(&self, t: &T, reason: ResolveReason) -> T {
+        t.resolve_in(&mut Resolver::new(self.fcx, reason))
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
@@ -315,18 +330,20 @@ enum ResolveReason {
     ResolvingExpr(Span),
     ResolvingLocal(Span),
     ResolvingPattern(Span),
-    ResolvingUpvar(ty::UpvarId)
+    ResolvingUpvar(ty::UpvarId),
+    ResolvingImplRes(Span),
 }
 
 impl ResolveReason {
-    fn span(&self, fcx: &FnCtxt) -> Span {
+    fn span(&self, tcx: &ty::ctxt) -> Span {
         match *self {
             ResolvingExpr(s) => s,
             ResolvingLocal(s) => s,
             ResolvingPattern(s) => s,
             ResolvingUpvar(upvar_id) => {
-                ty::expr_span(fcx.tcx(), upvar_id.closure_expr_id)
+                ty::expr_span(tcx, upvar_id.closure_expr_id)
             }
+            ResolvingImplRes(s) => s,
         }
     }
 }
@@ -334,59 +351,67 @@ fn span(&self, fcx: &FnCtxt) -> Span {
 ///////////////////////////////////////////////////////////////////////////
 // Convenience methods for resolving different kinds of things.
 
-trait Resolve {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Self;
+trait ResolveIn {
+    fn resolve_in(&self, resolver: &mut Resolver) -> Self;
 }
 
-impl<T:Resolve> Resolve for Option<T> {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Option<T> {
-        self.as_ref().map(|t| t.resolve(fcx, reason))
+impl<T:ResolveIn> ResolveIn for Option<T> {
+    fn resolve_in(&self, resolver: &mut Resolver) -> Option<T> {
+        self.as_ref().map(|t| t.resolve_in(resolver))
     }
 }
 
-impl<T:Resolve> Resolve for Vec<T> {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> Vec<T> {
-        self.iter().map(|t| t.resolve(fcx, reason)).collect()
+impl<T:ResolveIn> ResolveIn for Vec<T> {
+    fn resolve_in(&self, resolver: &mut Resolver) -> Vec<T> {
+        self.iter().map(|t| t.resolve_in(resolver)).collect()
     }
 }
 
-impl Resolve for ty::TraitStore {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::TraitStore {
-        Resolver::new(fcx, reason).fold_trait_store(*self)
+impl ResolveIn for ty::TraitStore {
+    fn resolve_in(&self, resolver: &mut Resolver) -> ty::TraitStore {
+        resolver.fold_trait_store(*self)
     }
 }
 
-impl Resolve for ty::t {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::t {
-        Resolver::new(fcx, reason).fold_ty(*self)
+impl ResolveIn for ty::t {
+    fn resolve_in(&self, resolver: &mut Resolver) -> ty::t {
+        resolver.fold_ty(*self)
     }
 }
 
-impl Resolve for ty::Region {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::Region {
-        Resolver::new(fcx, reason).fold_region(*self)
+impl ResolveIn for ty::Region {
+    fn resolve_in(&self, resolver: &mut Resolver) -> ty::Region {
+        resolver.fold_region(*self)
     }
 }
 
-impl Resolve for ty::substs {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::substs {
-        Resolver::new(fcx, reason).fold_substs(self)
+impl ResolveIn for ty::substs {
+    fn resolve_in(&self, resolver: &mut Resolver) -> ty::substs {
+        resolver.fold_substs(self)
     }
 }
 
-impl Resolve for ty::AutoRef {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> ty::AutoRef {
-        Resolver::new(fcx, reason).fold_autoref(self)
+impl ResolveIn for ty::ItemSubsts {
+    fn resolve_in(&self, resolver: &mut Resolver) -> ty::ItemSubsts {
+        ty::ItemSubsts {
+            substs: self.substs.resolve_in(resolver)
+        }
     }
 }
 
-impl Resolve for vtable_origin {
-    fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> vtable_origin {
+impl ResolveIn for ty::AutoRef {
+    fn resolve_in(&self, resolver: &mut Resolver) -> ty::AutoRef {
+        resolver.fold_autoref(self)
+    }
+}
+
+impl ResolveIn for vtable_origin {
+    fn resolve_in(&self, resolver: &mut Resolver) -> vtable_origin {
         match *self {
-            vtable_static(def_id, ref tys, ref origins) => {
-                let r_tys = tys.resolve(fcx, reason);
-                let r_origins = origins.resolve(fcx, reason);
-                vtable_static(def_id, r_tys, r_origins)
+            vtable_static(def_id, ref substs, ref origins) => {
+                let r_substs = substs.resolve_in(resolver);
+                let r_origins = origins.resolve_in(resolver);
+                vtable_static(def_id, r_substs, r_origins)
             }
             vtable_param(n, b) => {
                 vtable_param(n, b)
@@ -395,12 +420,23 @@ fn resolve(&self, fcx: &FnCtxt, reason: ResolveReason) -> vtable_origin {
     }
 }
 
+impl ResolveIn for impl_res {
+    fn resolve_in(&self, resolver: &mut Resolver) -> impl_res {
+        impl_res {
+            trait_vtables: self.trait_vtables.resolve_in(resolver),
+            self_vtables: self.self_vtables.resolve_in(resolver),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // The Resolver. This is the type folding engine that detects
 // unresolved types and so forth.
 
 struct Resolver<'cx> {
-    fcx: &'cx FnCtxt<'cx>,
+    tcx: &'cx ty::ctxt,
+    infcx: &'cx infer::InferCtxt<'cx>,
+    writeback_errors: &'cx Cell<bool>,
     reason: ResolveReason,
 }
 
@@ -409,15 +445,29 @@ fn new(fcx: &'cx FnCtxt<'cx>,
            reason: ResolveReason)
            -> Resolver<'cx>
     {
-        Resolver { fcx: fcx, reason: reason }
+        Resolver { infcx: fcx.infcx(),
+                   tcx: fcx.tcx(),
+                   writeback_errors: &fcx.writeback_errors,
+                   reason: reason }
+    }
+
+    fn from_infcx(infcx: &'cx infer::InferCtxt<'cx>,
+                  writeback_errors: &'cx Cell<bool>,
+                  reason: ResolveReason)
+                  -> Resolver<'cx>
+    {
+        Resolver { infcx: infcx,
+                   tcx: infcx.tcx,
+                   writeback_errors: writeback_errors,
+                   reason: reason }
     }
 
     fn report_error(&self, e: infer::fixup_err) {
-        self.fcx.writeback_errors.set(true);
-        if !self.tcx().sess.has_errors() {
+        self.writeback_errors.set(true);
+        if !self.tcx.sess.has_errors() {
             match self.reason {
                 ResolvingExpr(span) => {
-                    self.tcx().sess.span_err(
+                    self.tcx.sess.span_err(
                         span,
                         format!("cannot determine a type for \
                                  this expression: {}",
@@ -425,7 +475,7 @@ fn report_error(&self, e: infer::fixup_err) {
                 }
 
                 ResolvingLocal(span) => {
-                    self.tcx().sess.span_err(
+                    self.tcx.sess.span_err(
                         span,
                         format!("cannot determine a type for \
                                  this local variable: {}",
@@ -433,7 +483,7 @@ fn report_error(&self, e: infer::fixup_err) {
                 }
 
                 ResolvingPattern(span) => {
-                    self.tcx().sess.span_err(
+                    self.tcx.sess.span_err(
                         span,
                         format!("cannot determine a type for \
                                  this pattern binding: {}",
@@ -441,16 +491,22 @@ fn report_error(&self, e: infer::fixup_err) {
                 }
 
                 ResolvingUpvar(upvar_id) => {
-                    let span = self.reason.span(self.fcx);
-                    self.tcx().sess.span_err(
+                    let span = self.reason.span(self.tcx);
+                    self.tcx.sess.span_err(
                         span,
                         format!("cannot resolve lifetime for \
                                  captured variable `{}`: {}",
                                 ty::local_var_name_str(
-                                    self.tcx(),
+                                    self.tcx,
                                     upvar_id.var_id).get().to_str(),
                                 infer::fixup_err_to_str(e)));
                 }
+
+                ResolvingImplRes(span) => {
+                    self.tcx.sess.span_err(
+                        span,
+                        format!("cannot determine a type for impl supertrait"));
+                }
             }
         }
     }
@@ -458,7 +514,7 @@ fn report_error(&self, e: infer::fixup_err) {
 
 impl<'cx> TypeFolder for Resolver<'cx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt {
-        self.fcx.tcx()
+        self.tcx
     }
 
     fn fold_ty(&mut self, t: ty::t) -> ty::t {
@@ -466,7 +522,7 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
             return t;
         }
 
-        match resolve_type(self.fcx.infcx(), t, resolve_all | force_all) {
+        match resolve_type(self.infcx, t, resolve_all | force_all) {
             Ok(t) => t,
             Err(e) => {
                 self.report_error(e);
@@ -476,7 +532,7 @@ fn fold_ty(&mut self, t: ty::t) -> ty::t {
     }
 
     fn fold_region(&mut self, r: ty::Region) -> ty::Region {
-        match resolve_region(self.fcx.infcx(), r, resolve_all | force_all) {
+        match resolve_region(self.infcx, r, resolve_all | force_all) {
             Ok(r) => r,
             Err(e) => {
                 self.report_error(e);
index 84b08851deb7bea8a26b8abb732c3ed260ed6e03..49297e919ec60b9ddfdacbc9fb1924fe3c392f4d 100644 (file)
@@ -184,7 +184,7 @@ pub enum vtable_origin {
       from whence comes the vtable, and tys are the type substs.
       vtable_res is the vtable itself
      */
-    vtable_static(ast::DefId, Vec<ty::t>, vtable_res),
+    vtable_static(ast::DefId, ty::substs, vtable_res),
 
     /*
       Dynamic vtable, comes from a parameter that has a bound on it:
@@ -253,13 +253,16 @@ pub fn write_ty_to_tcx(tcx: &ty::ctxt, node_id: ast::NodeId, ty: ty::t) {
 }
 pub fn write_substs_to_tcx(tcx: &ty::ctxt,
                            node_id: ast::NodeId,
-                           substs: Vec<ty::t> ) {
-    if substs.len() > 0u {
-        debug!("write_substs_to_tcx({}, {:?})", node_id,
-               substs.iter().map(|t| ppaux::ty_to_str(tcx, *t)).collect::<Vec<~str>>());
-        assert!(substs.iter().all(|t| !ty::type_needs_infer(*t)));
+                           item_substs: ty::ItemSubsts) {
+    if !item_substs.is_noop() {
+        debug!("write_substs_to_tcx({}, {})",
+               node_id,
+               item_substs.repr(tcx));
 
-        tcx.node_type_substs.borrow_mut().insert(node_id, substs);
+        assert!(item_substs.substs.tps.iter().
+                all(|t| !ty::type_needs_infer(*t)));
+
+        tcx.item_substs.borrow_mut().insert(node_id, item_substs);
     }
 }
 pub fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> ast::Def {
index 1808c0209b754c1e39e62b503753380643b45b7c..94815d0144db35221bc726d0141632084ba79b1e 100644 (file)
@@ -561,6 +561,12 @@ fn repr(&self, tcx: &ctxt) -> ~str {
     }
 }
 
+impl Repr for ty::ItemSubsts {
+    fn repr(&self, tcx: &ctxt) -> ~str {
+        format!("ItemSubsts({})", self.substs.repr(tcx))
+    }
+}
+
 impl Repr for ty::RegionSubsts {
     fn repr(&self, tcx: &ctxt) -> ~str {
         match *self {