]> git.lizzy.rs Git - rust.git/commitdiff
Generalize AST and ty::Generics to accept multiple lifetimes.
authorNiko Matsakis <niko@alum.mit.edu>
Tue, 29 Oct 2013 10:03:32 +0000 (06:03 -0400)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 9 Nov 2013 00:42:46 +0000 (19:42 -0500)
52 files changed:
src/librustc/front/std_inject.rs
src/librustc/front/test.rs
src/librustc/lib.rs
src/librustc/metadata/common.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astencode.rs
src/librustc/middle/borrowck/gather_loans/mod.rs
src/librustc/middle/kind.rs
src/librustc/middle/privacy.rs
src/librustc/middle/resolve.rs
src/librustc/middle/subst.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/method.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/check/regionck.rs
src/librustc/middle/typeck/check/regionmanip.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/infer/combine.rs
src/librustc/middle/typeck/infer/glb.rs
src/librustc/middle/typeck/infer/lattice.rs
src/librustc/middle/typeck/infer/lub.rs
src/librustc/middle/typeck/infer/mod.rs
src/librustc/middle/typeck/infer/region_inference/mod.rs
src/librustc/middle/typeck/infer/resolve.rs
src/librustc/middle/typeck/infer/sub.rs
src/librustc/middle/typeck/mod.rs
src/librustc/util/ppaux.rs
src/librustdoc/clean.rs
src/librustdoc/html/format.rs
src/libstd/at_vec.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map.rs
src/libsyntax/ast_util.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/concat_idents.rs
src/libsyntax/ext/deriving/generic.rs
src/libsyntax/ext/deriving/rand.rs
src/libsyntax/ext/deriving/ty.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/format.rs
src/libsyntax/fold.rs
src/libsyntax/opt_vec.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs

index b34829bf47fc1e0a2003f0b7c988e7c33b089e25..c2d0251b23cc21d3a490cb128702734129ae777f 100644 (file)
@@ -116,12 +116,12 @@ fn fold_mod(&self, module: &ast::_mod) -> ast::_mod {
             segments: ~[
                 ast::PathSegment {
                     identifier: self.sess.ident_of("std"),
-                    lifetime: None,
+                    lifetimes: opt_vec::Empty,
                     types: opt_vec::Empty,
                 },
                 ast::PathSegment {
                     identifier: self.sess.ident_of("prelude"),
-                    lifetime: None,
+                    lifetimes: opt_vec::Empty,
                     types: opt_vec::Empty,
                 },
             ],
index 9541a03aff25e5326b603f3c268f11ff9e2c757d..b6ae41833777a8626d46514acb71df1f02d47405 100644 (file)
@@ -343,7 +343,7 @@ fn path_node(ids: ~[ast::Ident]) -> ast::Path {
         global: false,
         segments: ids.move_iter().map(|identifier| ast::PathSegment {
             identifier: identifier,
-            lifetime: None,
+            lifetimes: opt_vec::Empty,
             types: opt_vec::Empty,
         }).collect()
     }
@@ -355,7 +355,7 @@ fn path_node_global(ids: ~[ast::Ident]) -> ast::Path {
         global: true,
         segments: ids.move_iter().map(|identifier| ast::PathSegment {
             identifier: identifier,
-            lifetime: None,
+            lifetimes: opt_vec::Empty,
             types: opt_vec::Empty,
         }).collect()
     }
index ba27b5a5f41b12480fbaa327f8ecbb19bd177882..f2f200affe802a9351efb33db7f65cd2548820b2 100644 (file)
 pub mod middle {
     pub mod trans;
     pub mod ty;
+    pub mod ty_fold;
     pub mod subst;
     pub mod resolve;
+    pub mod resolve_lifetime;
     pub mod typeck;
     pub mod check_loop;
     pub mod check_match;
index 6294b6cb6e3128f6cfa400187cb1f8161266c6d4..05d40bbb6aea778b7fa68909cb43fae0dc3860ec 100644 (file)
@@ -193,6 +193,11 @@ pub fn from_uint(value : uint) -> Option<astencode_tag> {
 pub static tag_path_elt_pretty_name_ident: uint = 0x88;
 pub static tag_path_elt_pretty_name_extra: uint = 0x89;
 
+pub static tag_region_param_def: uint = 0x100;
+pub static tag_region_param_def_ident: uint = 0x101;
+pub static tag_region_param_def_def_id: uint = 0x102;
+
+
 pub struct LinkMeta {
     name: @str,
     vers: @str,
index 48fe21b334395312915dd373a48ab6b5530126a1..436b4c3df6bec8c4f36831d147e5933a5fd036bb 100644 (file)
@@ -199,12 +199,6 @@ pub fn get_trait_def(tcx: ty::ctxt, def: ast::DefId) -> ty::TraitDef {
     decoder::get_trait_def(cdata, def.node, tcx)
 }
 
-pub fn get_region_param(cstore: @mut metadata::cstore::CStore,
-                        def: ast::DefId) -> Option<ty::region_variance> {
-    let cdata = cstore::get_crate_data(cstore, def.crate);
-    return decoder::get_region_param(cdata, def.node);
-}
-
 pub fn get_field_type(tcx: ty::ctxt, class_id: ast::DefId,
                       def: ast::DefId) -> ty::ty_param_bounds_and_ty {
     let cstore = tcx.cstore;
@@ -224,7 +218,7 @@ pub fn get_field_type(tcx: ty::ctxt, class_id: ast::DefId,
     let ty = decoder::item_type(def, the_field, tcx, cdata);
     ty::ty_param_bounds_and_ty {
         generics: ty::Generics {type_param_defs: @~[],
-                                region_param: None},
+                                region_param_defs: @[]},
         ty: ty
     }
 }
index 56abaa27cce2c10fb4fa93f4f6a42eaa781666f5..3b4e29c97c0149003fa886846099588b0025ad14 100644 (file)
@@ -25,7 +25,7 @@
 use middle::typeck;
 use middle::astencode::vtable_decoder_helpers;
 
-
+use std::at_vec;
 use std::u64;
 use std::rt::io;
 use std::rt::io::extensions::u64_from_be_bytes;
@@ -252,9 +252,11 @@ fn item_trait_ref(doc: ebml::Doc, tcx: ty::ctxt, cdata: Cmd) -> ty::TraitRef {
     doc_trait_ref(tp, tcx, cdata)
 }
 
-fn item_ty_param_defs(item: ebml::Doc, tcx: ty::ctxt, cdata: Cmd,
+fn item_ty_param_defs(item: ebml::Doc,
+                      tcx: ty::ctxt,
+                      cdata: Cmd,
                       tag: uint)
-    -> @~[ty::TypeParameterDef] {
+                      -> @~[ty::TypeParameterDef] {
     let mut bounds = ~[];
     do reader::tagged_docs(item, tag) |p| {
         let bd = parse_type_param_def_data(
@@ -266,10 +268,23 @@ fn item_ty_param_defs(item: ebml::Doc, tcx: ty::ctxt, cdata: Cmd,
     @bounds
 }
 
-fn item_ty_region_param(item: ebml::Doc) -> Option<ty::region_variance> {
-    do reader::maybe_get_doc(item, tag_region_param).map |doc| {
-        let mut decoder = reader::Decoder(doc);
-        Decodable::decode(&mut decoder)
+fn item_region_param_defs(item_doc: ebml::Doc,
+                          tcx: ty::ctxt,
+                          cdata: Cmd)
+                          -> @[ty::RegionParameterDef] {
+    do at_vec::build(None) |push| {
+        do reader::tagged_docs(item_doc, tag_region_param_def) |rp_doc| {
+            let ident_str_doc = reader::get_doc(rp_doc,
+                                                tag_region_param_def_ident);
+            let ident = item_name(tcx.sess.intr(), ident_str_doc);
+            let def_id_doc = reader::get_doc(rp_doc,
+                                             tag_region_param_def_def_id);
+            let def_id = reader::with_doc_data(def_id_doc, parse_def_id);
+            let def_id = translate_def_id(cdata, def_id);
+            push(ty::RegionParameterDef { ident: ident,
+                                          def_id: def_id });
+            true
+        };
     }
 }
 
@@ -393,7 +408,7 @@ pub fn get_trait_def(cdata: Cmd,
     let item_doc = lookup_item(item_id, cdata.data);
     let tp_defs = item_ty_param_defs(item_doc, tcx, cdata,
                                      tag_items_data_item_ty_param_bounds);
-    let rp = item_ty_region_param(item_doc);
+    let rp_defs = item_region_param_defs(item_doc, tcx, cdata);
     let mut bounds = ty::EmptyBuiltinBounds();
     // Collect the builtin bounds from the encoded supertraits.
     // FIXME(#8559): They should be encoded directly.
@@ -407,7 +422,7 @@ pub fn get_trait_def(cdata: Cmd,
     };
     ty::TraitDef {
         generics: ty::Generics {type_param_defs: tp_defs,
-                                region_param: rp},
+                                region_param_defs: rp_defs},
         bounds: bounds,
         trait_ref: @item_trait_ref(item_doc, tcx, cdata)
     }
@@ -417,33 +432,27 @@ pub fn get_type(cdata: Cmd, id: ast::NodeId, tcx: ty::ctxt)
     -> ty::ty_param_bounds_and_ty {
 
     let item = lookup_item(id, cdata.data);
+
     let t = item_type(ast::DefId { crate: cdata.cnum, node: id }, item, tcx,
                       cdata);
-    let tp_defs = if family_has_type_params(item_family(item)) {
-        item_ty_param_defs(item, tcx, cdata, tag_items_data_item_ty_param_bounds)
-    } else { @~[] };
-    let rp = item_ty_region_param(item);
+
+    let tp_defs = item_ty_param_defs(item, tcx, cdata, tag_items_data_item_ty_param_bounds);
+    let rp_defs = item_region_param_defs(item, tcx, cdata);
+
     ty::ty_param_bounds_and_ty {
         generics: ty::Generics {type_param_defs: tp_defs,
-                                region_param: rp},
+                                region_param_defs: rp_defs},
         ty: t
     }
 }
 
-pub fn get_region_param(cdata: Cmd, id: ast::NodeId)
-    -> Option<ty::region_variance> {
-
-    let item = lookup_item(id, cdata.data);
-    return item_ty_region_param(item);
-}
-
 pub fn get_type_param_count(data: @~[u8], id: ast::NodeId) -> uint {
     item_ty_param_count(lookup_item(id, data))
 }
 
 pub fn get_impl_trait(cdata: Cmd,
-                       id: ast::NodeId,
-                       tcx: ty::ctxt) -> Option<@ty::TraitRef>
+                      id: ast::NodeId,
+                      tcx: ty::ctxt) -> Option<@ty::TraitRef>
 {
     let item_doc = lookup_item(id, cdata.data);
     do reader::maybe_get_doc(item_doc, tag_item_trait_ref).map |tp| {
@@ -1044,6 +1053,7 @@ pub fn get_method(intr: @ident_interner, cdata: Cmd, id: ast::NodeId,
     let name = item_name(intr, method_doc);
     let type_param_defs = item_ty_param_defs(method_doc, tcx, cdata,
                                              tag_item_method_tps);
+    let rp_defs = item_region_param_defs(method_doc, tcx, cdata);
     let transformed_self_ty = doc_transformed_self_ty(method_doc, tcx, cdata);
     let fty = doc_method_fty(method_doc, tcx, cdata);
     let vis = item_visibility(method_doc);
@@ -1054,7 +1064,7 @@ pub fn get_method(intr: @ident_interner, cdata: Cmd, id: ast::NodeId,
         name,
         ty::Generics {
             type_param_defs: type_param_defs,
-            region_param: None
+            region_param_defs: rp_defs,
         },
         transformed_self_ty,
         fty,
index 1ad7e416342f5bd5eac81c960141d2d1d6ecc308..76c49da5861e6e2a28b7958b445691f95d58137d 100644 (file)
@@ -121,17 +121,6 @@ pub fn encode_def_id(ebml_w: &mut writer::Encoder, id: DefId) {
     ebml_w.wr_tagged_str(tag_def_id, def_to_str(id));
 }
 
-fn encode_region_param(ecx: &EncodeContext,
-                       ebml_w: &mut writer::Encoder,
-                       it: @ast::item) {
-    let opt_rp = ecx.tcx.region_paramd_items.find(&it.id);
-    for rp in opt_rp.iter() {
-        ebml_w.start_tag(tag_region_param);
-        rp.encode(ebml_w);
-        ebml_w.end_tag();
-    }
-}
-
 #[deriving(Clone)]
 struct entry<T> {
     val: T,
@@ -205,11 +194,29 @@ fn encode_ty_type_param_defs(ebml_w: &mut writer::Encoder,
     }
 }
 
+fn encode_region_param_defs(ebml_w: &mut writer::Encoder,
+                            ecx: &EncodeContext,
+                            params: @[ty::RegionParameterDef]) {
+    for param in params.iter() {
+        ebml_w.start_tag(tag_region_param_def);
+
+        ebml_w.start_tag(tag_region_param_def_ident);
+        encode_name(ecx, ebml_w, param.ident);
+        ebml_w.end_tag();
+
+        ebml_w.wr_tagged_str(tag_region_param_def_def_id,
+                             def_to_str(param.def_id));
+
+        ebml_w.end_tag();
+    }
+}
+
 fn encode_bounds_and_type(ebml_w: &mut writer::Encoder,
                           ecx: &EncodeContext,
                           tpt: &ty::ty_param_bounds_and_ty) {
     encode_ty_type_param_defs(ebml_w, ecx, tpt.generics.type_param_defs,
                               tag_items_data_item_ty_param_bounds);
+    encode_region_param_defs(ebml_w, ecx, tpt.generics.region_param_defs);
     encode_type(ecx, ebml_w, tpt.ty);
 }
 
@@ -976,7 +983,6 @@ fn add_to_index(item: @item, ebml_w: &writer::Encoder,
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
-        encode_region_param(ecx, ebml_w, item);
         encode_visibility(ebml_w, vis);
         ebml_w.end_tag();
       }
@@ -994,7 +1000,6 @@ fn add_to_index(item: @item, ebml_w: &writer::Encoder,
         }
         (ecx.encode_inlined_item)(ecx, ebml_w, path, ii_item(item));
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
-        encode_region_param(ecx, ebml_w, item);
 
         // Encode inherent implementations for this enumeration.
         encode_inherent_implementations(ecx, ebml_w, def_id);
@@ -1030,7 +1035,6 @@ fn add_to_index(item: @item, ebml_w: &writer::Encoder,
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
-        encode_region_param(ecx, ebml_w, item);
         encode_visibility(ebml_w, vis);
 
         /* Encode def_ids for each field and method
@@ -1075,7 +1079,6 @@ fn add_to_index(item: @item, ebml_w: &writer::Encoder,
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'i');
-        encode_region_param(ecx, ebml_w, item);
         encode_bounds_and_type(ebml_w, ecx, &lookup_item_type(tcx, def_id));
         encode_name(ecx, ebml_w, item.ident);
         encode_attributes(ebml_w, item.attrs);
@@ -1135,7 +1138,6 @@ fn add_to_index(item: @item, ebml_w: &writer::Encoder,
         ebml_w.start_tag(tag_items_data_item);
         encode_def_id(ebml_w, def_id);
         encode_family(ebml_w, 'I');
-        encode_region_param(ecx, ebml_w, item);
         let trait_def = ty::lookup_trait_def(tcx, def_id);
         encode_ty_type_param_defs(ebml_w, ecx,
                                   trait_def.generics.type_param_defs,
index b365e7a48795e631e6109a7cf7b4b9a5967d1e4f..1636205c76d626ccde8cde1ad2311c8599aea8b2 100644 (file)
@@ -48,7 +48,10 @@ pub enum DefIdSource {
     TypeWithId,
 
     // Identifies a type parameter (`fn foo<X>() { ... }`).
-    TypeParameter
+    TypeParameter,
+
+    // Identifies a region parameter (`fn foo<'X>() { ... }`).
+    RegionParameter,
 }
 type conv_did<'self> =
     &'self fn(source: DefIdSource, ast::DefId) -> ast::DefId;
@@ -143,7 +146,7 @@ fn parse_path(st: &mut PState) -> @ast::Path {
                     segments: idents.move_iter().map(|identifier| {
                         ast::PathSegment {
                             identifier: identifier,
-                            lifetime: None,
+                            lifetimes: opt_vec::Empty,
                             types: opt_vec::Empty,
                         }
                     }).collect()
@@ -165,7 +168,7 @@ fn parse_sigil(st: &mut PState) -> ast::Sigil {
     }
 }
 
-fn parse_vstore(st: &mut PState) -> ty::vstore {
+fn parse_vstore(st: &mut PState, conv: conv_did) -> ty::vstore {
     assert_eq!(next(st), '/');
 
     let c = peek(st);
@@ -178,22 +181,22 @@ fn parse_vstore(st: &mut PState) -> ty::vstore {
     match next(st) {
       '~' => ty::vstore_uniq,
       '@' => ty::vstore_box,
-      '&' => ty::vstore_slice(parse_region(st)),
+      '&' => ty::vstore_slice(parse_region(st, conv)),
       c => st.tcx.sess.bug(format!("parse_vstore(): bad input '{}'", c))
     }
 }
 
-fn parse_trait_store(st: &mut PState) -> ty::TraitStore {
+fn parse_trait_store(st: &mut PState, conv: conv_did) -> ty::TraitStore {
     match next(st) {
         '~' => ty::UniqTraitStore,
         '@' => ty::BoxTraitStore,
-        '&' => ty::RegionTraitStore(parse_region(st)),
+        '&' => ty::RegionTraitStore(parse_region(st, conv)),
         c => st.tcx.sess.bug(format!("parse_trait_store(): bad input '{}'", c))
     }
 }
 
 fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
-    let regions = parse_region_substs(st);
+    let regions = parse_region_substs(st, |x,y| conv(x,y));
 
     let self_ty = parse_opt(st, |st| parse_ty(st, |x,y| conv(x,y)) );
 
@@ -209,13 +212,13 @@ fn parse_substs(st: &mut PState, conv: conv_did) -> ty::substs {
     };
 }
 
-fn parse_region_substs(st: &mut PState) -> ty::RegionSubsts {
+fn parse_region_substs(st: &mut PState, conv: conv_did) -> ty::RegionSubsts {
     match next(st) {
         'e' => ty::ErasedRegions,
         'n' => {
             let mut regions = opt_vec::Empty;
             while peek(st) != '.' {
-                let r = parse_region(st);
+                let r = parse_region(st, |x,y| conv(x,y));
                 regions.push(r);
             }
             assert_eq!(next(st), '.');
@@ -225,34 +228,51 @@ fn parse_region_substs(st: &mut PState) -> ty::RegionSubsts {
     }
 }
 
-fn parse_bound_region(st: &mut PState) -> ty::bound_region {
+fn parse_bound_region(st: &mut PState, conv: conv_did) -> ty::bound_region {
     match next(st) {
-      's' => ty::br_self,
-      'a' => {
-        let id = parse_uint(st);
-        assert_eq!(next(st), '|');
-        ty::br_anon(id)
-      }
-      '[' => ty::br_named(st.tcx.sess.ident_of(parse_str(st, ']'))),
-      'c' => {
-        let id = parse_uint(st) as int;
-        assert_eq!(next(st), '|');
-        ty::br_cap_avoid(id, @parse_bound_region(st))
-      },
-      _ => fail!("parse_bound_region: bad input")
+        'a' => {
+            let id = parse_uint(st);
+            assert_eq!(next(st), '|');
+            ty::br_anon(id)
+        }
+        '[' => {
+            let def = parse_def(st, RegionParameter, |x,y| conv(x,y));
+            let ident = st.tcx.sess.ident_of(parse_str(st, ']'));
+            ty::br_named(def, ident)
+        }
+        'f' => {
+            let id = parse_uint(st);
+            assert_eq!(next(st), '|');
+            ty::br_fresh(id)
+        }
+        _ => fail!("parse_bound_region: bad input")
     }
 }
 
-fn parse_region(st: &mut PState) -> ty::Region {
+fn parse_region(st: &mut PState, conv: conv_did) -> ty::Region {
     match next(st) {
       'b' => {
-        ty::re_bound(parse_bound_region(st))
+        assert_eq!(next(st), '[');
+        let id = parse_uint(st) as int;
+        assert_eq!(next(st), '|');
+        let br = parse_bound_region(st, |x,y| conv(x,y));
+        assert_eq!(next(st), ']');
+        ty::re_fn_bound(id, br)
+      }
+      'B' => {
+        assert_eq!(next(st), '[');
+        let node_id = parse_uint(st) as int;
+        assert_eq!(next(st), '|');
+        let index = parse_uint(st);
+        assert_eq!(next(st), '|');
+        let nm = st.tcx.sess.ident_of(parse_str(st, ']'));
+        ty::re_type_bound(node_id, index, nm)
       }
       'f' => {
         assert_eq!(next(st), '[');
         let id = parse_uint(st) as int;
         assert_eq!(next(st), '|');
-        let br = parse_bound_region(st);
+        let br = parse_bound_region(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
         ty::re_free(ty::FreeRegion {scope_id: id,
                                     bound_region: br})
@@ -331,14 +351,14 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
         assert_eq!(next(st), '[');
         let def = parse_def(st, NominalType, |x,y| conv(x,y));
         let substs = parse_substs(st, |x,y| conv(x,y));
-        let store = parse_trait_store(st);
+        let store = parse_trait_store(st, |x,y| conv(x,y));
         let mt = parse_mutability(st);
         let bounds = parse_bounds(st, |x,y| conv(x,y));
         assert_eq!(next(st), ']');
         return ty::mk_trait(st.tcx, def, substs, store, mt, bounds.builtin_bounds);
       }
       'p' => {
-        let did = parse_def(st, TypeParameter, conv);
+        let did = parse_def(st, TypeParameter, |x,y| conv(x,y));
         debug!("parsed ty_param: did={:?}", did);
         return ty::mk_param(st.tcx, parse_uint(st), did);
       }
@@ -356,12 +376,12 @@ fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
       }
       'U' => return ty::mk_unboxed_vec(st.tcx, parse_mt(st, conv)),
       'V' => {
-        let mt = parse_mt(st, conv);
-        let v = parse_vstore(st);
+        let mt = parse_mt(st, |x,y| conv(x,y));
+        let v = parse_vstore(st, |x,y| conv(x,y));
         return ty::mk_evec(st.tcx, mt, v);
       }
       'v' => {
-        let v = parse_vstore(st);
+        let v = parse_vstore(st, |x,y| conv(x,y));
         return ty::mk_estr(st.tcx, v);
       }
       'T' => {
@@ -495,7 +515,7 @@ fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
     let sigil = parse_sigil(st);
     let purity = parse_purity(next(st));
     let onceness = parse_onceness(next(st));
-    let region = parse_region(st);
+    let region = parse_region(st, |x,y| conv(x,y));
     let bounds = parse_bounds(st, |x,y| conv(x,y));
     let sig = parse_sig(st, |x,y| conv(x,y));
     ty::ClosureTy {
@@ -511,7 +531,7 @@ fn parse_closure_ty(st: &mut PState, conv: conv_did) -> ty::ClosureTy {
 fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
     let purity = parse_purity(next(st));
     let abi = parse_abi_set(st);
-    let sig = parse_sig(st, conv);
+    let sig = parse_sig(st, |x,y| conv(x,y));
     ty::BareFnTy {
         purity: purity,
         abis: abi,
@@ -521,22 +541,22 @@ fn parse_bare_fn_ty(st: &mut PState, conv: conv_did) -> ty::BareFnTy {
 
 fn parse_sig(st: &mut PState, conv: conv_did) -> ty::FnSig {
     assert_eq!(next(st), '[');
+    let id = parse_uint(st) as int;
+    assert_eq!(next(st), '|');
     let mut inputs = ~[];
     while peek(st) != ']' {
         inputs.push(parse_ty(st, |x,y| conv(x,y)));
     }
     st.pos += 1u; // eat the ']'
-    let variadic = if peek(st) == 'A' {
-        st.pos += 1; // eat the 'A'
-        true
-    } else { false };
-    let ret_ty = parse_ty(st, conv);
-    ty::FnSig {
-        bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
-        inputs: inputs,
-        output: ret_ty,
-        variadic: variadic
-    }
+    let variadic = match next(st) {
+        'V' => true,
+        'N' => false,
+    };
+    let ret_ty = parse_ty(st, |x,y| conv(x,y));
+    ty::FnSig {binder_id: id,
+               inputs: inputs,
+               output: ret_ty,
+               variadic: variadic}
 }
 
 // Rust metadata parsing
index 5397bf0e768d8d237ea32c3e48d5d8d1c874a4ff..af28162dbfd5dd4c7d56e10f42574dc7d470e46d 100644 (file)
@@ -155,18 +155,31 @@ fn enc_region_substs(w: @mut MemWriter, cx: @ctxt, substs: &ty::RegionSubsts) {
 
 fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) {
     match r {
-        ty::re_bound(br) => {
-            mywrite!(w, "b");
+        ty::re_fn_bound(id, br) => {
+            mywrite!(w, "b[{}|", id);
             enc_bound_region(w, cx, br);
+            mywrite!(w, "]");
+        }
+        ty::re_type_bound(node_id, index, ident) => {
+            mywrite!(w, "B[{}|{}|{}]",
+                     node_id,
+                     index,
+                     cx.tcx.sess.str_of(ident));
         }
         ty::re_free(ref fr) => {
             mywrite!(w, "f[{}|", fr.scope_id);
             enc_bound_region(w, cx, fr.bound_region);
             mywrite!(w, "]");
         }
-        ty::re_scope(nid) => mywrite!(w, "s{}|", nid),
-        ty::re_static => mywrite!(w, "t"),
-        ty::re_empty => mywrite!(w, "e"),
+        ty::re_scope(nid) => {
+            mywrite!(w, "s{}|", nid);
+        }
+        ty::re_static => {
+            mywrite!(w, "t");
+        }
+        ty::re_empty => {
+            mywrite!(w, "e");
+        }
         ty::re_infer(_) => {
             // these should not crop up after typeck
             cx.diag.handler().bug("Cannot encode region variables");
@@ -176,14 +189,17 @@ fn enc_region(w: @mut MemWriter, cx: @ctxt, r: ty::Region) {
 
 fn enc_bound_region(w: @mut MemWriter, cx: @ctxt, br: ty::bound_region) {
     match br {
-        ty::br_self => mywrite!(w, "s"),
-        ty::br_anon(idx) => mywrite!(w, "a{}|", idx),
-        ty::br_named(s) => mywrite!(w, "[{}]", cx.tcx.sess.str_of(s)),
-        ty::br_cap_avoid(id, br) => {
-            mywrite!(w, "c{}|", id);
-            enc_bound_region(w, cx, *br);
-        }
-        ty::br_fresh(id) => mywrite!(w, "{}", id),
+        ty::br_anon(idx) => {
+            mywrite!(w, "a{}|", idx);
+        }
+        ty::br_named(d, s) => {
+            mywrite!(w, "[{}|{}]",
+                     (cx.ds)(d),
+                     cx.tcx.sess.str_of(s));
+        }
+        ty::br_fresh(id) => {
+            mywrite!(w, "f{}|", id);
+        }
     }
 }
 
@@ -366,13 +382,15 @@ fn enc_closure_ty(w: @mut MemWriter, cx: @ctxt, ft: &ty::ClosureTy) {
 }
 
 fn enc_fn_sig(w: @mut MemWriter, cx: @ctxt, fsig: &ty::FnSig) {
-    mywrite!(w, "[");
+    mywrite!(w, "[{}|", fsig.binder_id);
     for ty in fsig.inputs.iter() {
         enc_ty(w, cx, *ty);
     }
     mywrite!(w, "]");
     if fsig.variadic {
-        mywrite!(w, "A");
+        mywrite!(w, "V");
+    } else {
+        mywrite!(w, "N");
     }
     enc_ty(w, cx, fsig.output);
 }
index cb8c7b3262fbf2ecfb195cfbe60cf7556b9bb585..e60b9382be49af8952fe47aea86ac489f6ba27de 100644 (file)
@@ -15,7 +15,8 @@
 use e = metadata::encoder;
 use metadata::decoder;
 use metadata::tydecode;
-use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
+use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
+                         RegionParameter};
 use metadata::tyencode;
 use middle::freevars::freevar_entry;
 use middle::typeck::{method_origin, method_map_entry};
@@ -234,6 +235,12 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ast::DefId {
     }
 }
 
+impl tr for Option<ast::DefId> {
+    fn tr(&self, xcx: @ExtendedDecodeContext) -> Option<ast::DefId> {
+        self.map(|d| xcx.tr_def_id(d))
+    }
+}
+
 impl tr for Span {
     fn tr(&self, xcx: @ExtendedDecodeContext) -> Span {
         xcx.tr_span(*self)
@@ -469,7 +476,11 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::AutoRef {
 impl tr for ty::Region {
     fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region {
         match *self {
-            ty::re_bound(br) => ty::re_bound(br.tr(xcx)),
+            ty::re_fn_bound(id, br) => ty::re_fn_bound(xcx.tr_id(id),
+                                                       br.tr(xcx)),
+            ty::re_type_bound(id, index, ident) => ty::re_type_bound(xcx.tr_id(id),
+                                                                     index,
+                                                                     ident),
             ty::re_scope(id) => ty::re_scope(xcx.tr_id(id)),
             ty::re_empty | ty::re_static | ty::re_infer(*) => *self,
             ty::re_free(ref fr) => {
@@ -483,10 +494,10 @@ fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::Region {
 impl tr for ty::bound_region {
     fn tr(&self, xcx: @ExtendedDecodeContext) -> ty::bound_region {
         match *self {
-            ty::br_anon(_) | ty::br_named(_) | ty::br_self |
+            ty::br_anon(_) |
             ty::br_fresh(_) => *self,
-            ty::br_cap_avoid(id, br) => ty::br_cap_avoid(xcx.tr_id(id),
-                                                         @br.tr(xcx))
+            ty::br_named(id, ident) => ty::br_named(xcx.tr_def_id(id),
+                                                    ident),
         }
     }
 }
@@ -821,8 +832,8 @@ fn emit_tpbt(&mut self,
                             this.emit_type_param_def(ecx, type_param_def);
                         }
                     }
-                    do this.emit_struct_field("region_param", 1) |this| {
-                        tpbt.generics.region_param.encode(this);
+                    do this.emit_struct_field("region_param_defs", 1) |this| {
+                        tpbt.generics.region_param_defs.encode(this);
                     }
                 }
             }
@@ -1086,6 +1097,8 @@ fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t {
         // are not used during trans.
 
         return do self.read_opaque |this, doc| {
+            debug!("read_ty({})", type_string(doc));
+
             let ty = tydecode::parse_ty_data(
                 *doc.data,
                 xcx.dcx.cdata.cnum,
@@ -1093,10 +1106,6 @@ fn read_ty(&mut self, xcx: @ExtendedDecodeContext) -> ty::t {
                 xcx.dcx.tcx,
                 |s, a| this.convert_def_id(xcx, s, a));
 
-            debug!("read_ty({}) = {}",
-                   type_string(doc),
-                   ty_to_str(xcx.dcx.tcx, ty));
-
             ty
         };
 
@@ -1139,8 +1148,8 @@ fn read_ty_param_bounds_and_ty(&mut self, xcx: @ExtendedDecodeContext)
                                     @this.read_to_vec(|this|
                                         this.read_type_param_def(xcx))
                             }),
-                            region_param:
-                                this.read_struct_field("region_param",
+                            region_param_defs:
+                                this.read_struct_field("region_param_defs",
                                                        1,
                                                        |this| {
                                     Decodable::decode(this)
@@ -1161,7 +1170,6 @@ fn convert_def_id(&mut self,
                       did: ast::DefId)
                       -> ast::DefId {
         /*!
-         *
          * Converts a def-id that appears in a type.  The correct
          * translation will depend on what kind of def-id this is.
          * This is a subtle point: type definitions are not
@@ -1172,10 +1180,25 @@ fn convert_def_id(&mut self,
          * However, *type parameters* are cloned along with the function
          * they are attached to.  So we should translate those def-ids
          * to refer to the new, cloned copy of the type parameter.
+         * We only see references to free type parameters in the body of
+         * an inlined function. In such cases, we need the def-id to
+         * be a local id so that the TypeContents code is able to lookup
+         * the relevant info in the ty_param_defs table.
+         *
+         * *Region parameters*, unfortunately, are another kettle of fish.
+         * In such cases, def_id's can appear in types to distinguish
+         * shadowed bound regions and so forth. It doesn't actually
+         * matter so much what we do to these, since regions are erased
+         * at trans time, but it's good to keep them consistent just in
+         * case. We translate them with `tr_def_id()` which will map
+         * the crate numbers back to the original source crate.
+         *
+         * It'd be really nice to refactor the type repr to not include
+         * def-ids so that all these distinctions were unnecessary.
          */
 
         let r = match source {
-            NominalType | TypeWithId => xcx.tr_def_id(did),
+            NominalType | TypeWithId | RegionParameter => xcx.tr_def_id(did),
             TypeParameter => xcx.tr_intern_def_id(did)
         };
         debug!("convert_def_id(source={:?}, did={:?})={:?}", source, did, r);
index dd161b189da27c59d809ebe273d22223a68f950c..729da749ec6916799b1f9f1b28fcd5e76b104f3a 100644 (file)
@@ -486,7 +486,8 @@ pub fn guarantee_valid(&mut self,
                     }
 
                     ty::re_empty |
-                    ty::re_bound(*) |
+                    ty::re_fn_bound(*) |
+                    ty::re_type_bound(*) |
                     ty::re_infer(*) => {
                         self.tcx().sess.span_bug(
                             cmt.span,
index fd5114889fddbe98045a60547db3936367d055d3..99f2d7a87002f6e59db24390da6c410acbe9fb5d 100644 (file)
@@ -540,7 +540,7 @@ pub fn check_cast_for_escaping_regions(
                 target_regions.push(r);
             }
         },
-        |_| true);
+        |_| ());
 
     // Check, based on the region associated with the trait, whether it can
     // possibly escape the enclosing fn item (note that all type parameters
@@ -582,7 +582,6 @@ pub fn check_cast_for_escaping_regions(
                 }
                 _ => {}
             }
-            true
         });
 
     fn is_re_scope(r: ty::Region) -> bool {
index 70aa05848f3669207b0e4f336082fc64f0a2f8a7..eeedd25adac28d5f23bd04d6bde3df977d40665c 100644 (file)
@@ -781,7 +781,7 @@ fn visit_view_item(&mut self, a: &ast::view_item, _: ()) {
                                 debug!("privacy - list {}", pid.node.id);
                                 let seg = ast::PathSegment {
                                     identifier: pid.node.name,
-                                    lifetime: None,
+                                    lifetimes: opt_vec::Empty,
                                     types: opt_vec::Empty,
                                 };
                                 let segs = ~[seg];
index 9f848b4c2276c335d20e8fba84dcc42d5318d691..23fef5e3516748e571b384bed4454be8af6f46cf 100644 (file)
@@ -4182,7 +4182,7 @@ fn resolve_type(&mut self, ty: &Ty) {
 
                             if path.segments
                                    .iter()
-                                   .any(|s| s.lifetime.is_some()) {
+                                   .any(|s| !s.lifetimes.is_empty()) {
                                 self.session.span_err(path.span,
                                                       "lifetime parameters \
                                                        are not allowed on \
index a13248f2480d123054f23442fb4760a3b2d66e6f..7654a46ec3639db7ce631e41013370cdf6a86c86 100644 (file)
@@ -173,35 +173,30 @@ impl Subst for ty::Generics {
     fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::Generics {
         ty::Generics {
             type_param_defs: self.type_param_defs.subst(tcx, substs),
-            region_param: self.region_param
+            region_param_defs: self.region_param_defs.subst(tcx, substs),
         }
     }
 }
 
+impl Subst for ty::RegionParameterDef {
+    fn subst(&self, _: ty::ctxt, _: &ty::substs) -> ty::RegionParameterDef {
+        *self
+    }
+}
+
 impl Subst for ty::Region {
-    fn subst(&self, tcx: ty::ctxt, substs: &ty::substs) -> ty::Region {
-        // Note: This routine only handles the self region, because it
-        // is only concerned with substitutions of regions that appear
-        // in types. Region substitution of the bound regions that
-        // appear in a function signature is done using the
-        // specialized routine
+    fn subst(&self, _tcx: ty::ctxt, substs: &ty::substs) -> ty::Region {
+        // Note: This routine only handles regions that are bound on
+        // type declarationss and other outer declarations, not those
+        // bound in *fn types*. Region substitution of the bound
+        // regions that appear in a function signature is done using
+        // the specialized routine
         // `middle::typeck::check::regionmanip::replace_bound_regions_in_fn_sig()`.
-        // As we transition to the new region syntax this distinction
-        // will most likely disappear.
         match self {
-            &ty::re_bound(ty::br_self) => {
+            &ty::re_type_bound(_, i, _) => {
                 match substs.regions {
                     ty::ErasedRegions => ty::re_static,
-                    ty::NonerasedRegions(ref regions) => {
-                        if regions.len() != 1 {
-                            tcx.sess.bug(
-                                format!("ty::Region\\#subst(): \
-                                      Reference to self region when \
-                                      given substs with no self region: {}",
-                                     substs.repr(tcx)));
-                        }
-                        *regions.get(0)
-                    }
+                    ty::NonerasedRegions(ref regions) => *regions.get(i),
                 }
             }
             _ => *self
index 9d6ad4d8bf6944d8e0ba13ab4d5c43bc1a5e9dcd..66fba347acc13c67b1f2329507675b1f244a5e26 100644 (file)
@@ -436,14 +436,17 @@ pub struct ClosureTy {
  * Signature of a function type, which I have arbitrarily
  * decided to use to refer to the input/output types.
  *
- * - `lifetimes` is the list of region names bound in this fn.
+ * - `binder_id` is the node id where this fn type appeared;
+ *   it is used to identify all the bound regions appearing
+ *   in the input/output types that are bound by this fn type
+ *   (vs some enclosing or enclosed fn type)
  * - `inputs` is the list of arguments and their modes.
  * - `output` is the return type.
  * - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
  */
 #[deriving(Clone, Eq, IterBytes)]
 pub struct FnSig {
-    bound_lifetime_names: OptVec<ast::Ident>,
+    binder_id: ast::NodeId,
     inputs: ~[t],
     output: t,
     variadic: bool
@@ -458,16 +461,13 @@ pub struct param_ty {
 /// Representation of regions:
 #[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
 pub enum Region {
-    /// Bound regions are found (primarily) in function types.  They indicate
-    /// region parameters that have yet to be replaced with actual regions
-    /// (analogous to type parameters, except that due to the monomorphic
-    /// nature of our type system, bound type parameters are always replaced
-    /// with fresh type variables whenever an item is referenced, so type
-    /// parameters only appear "free" in types.  Regions in contrast can
-    /// appear free or bound.).  When a function is called, all bound regions
-    /// tied to that function's node-id are replaced with fresh region
-    /// variables whose value is then inferred.
-    re_bound(bound_region),
+    // Region bound in a type declaration (type/enum/struct/trait),
+    // which will be substituted when an instance of the type is accessed
+    re_type_bound(/* param id */ ast::NodeId, /*index*/ uint, ast::Ident),
+
+    // Region bound in a fn scope, which will be substituted when the
+    // fn is called.
+    re_fn_bound(/* binder_id */ ast::NodeId, bound_region),
 
     /// When checking a function body, the types of all arguments and so forth
     /// that refer to bound region parameters are modified to refer to free
@@ -496,42 +496,32 @@ pub enum Region {
 impl Region {
     pub fn is_bound(&self) -> bool {
         match self {
-            &re_bound(*) => true,
+            &ty::re_type_bound(*) => true,
+            &ty::re_fn_bound(*) => true,
             _ => false
         }
     }
 }
 
-#[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
+#[deriving(Clone, Eq, TotalOrd, TotalEq, IterBytes, Encodable, Decodable, ToStr)]
 pub struct FreeRegion {
     scope_id: NodeId,
     bound_region: bound_region
 }
 
-#[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
+#[deriving(Clone, Eq, TotalEq, TotalOrd, IterBytes, Encodable, Decodable, ToStr)]
 pub enum bound_region {
-    /// The self region for structs, impls (&T in a type defn or &'self T)
-    br_self,
-
     /// An anonymous region parameter for a given fn (&T)
     br_anon(uint),
 
     /// Named region parameters for functions (a in &'a T)
-    br_named(ast::Ident),
+    ///
+    /// The def-id is needed to distinguish free regions in
+    /// the event of shadowing.
+    br_named(ast::DefId, ast::Ident),
 
     /// Fresh bound identifiers created during GLB computations.
     br_fresh(uint),
-
-    /**
-     * Handles capture-avoiding substitution in a rather subtle case.  If you
-     * have a closure whose argument types are being inferred based on the
-     * expected type, and the expected type includes bound regions, then we
-     * will wrap those bound regions in a br_cap_avoid() with the id of the
-     * fn expression.  This ensures that the names are not "captured" by the
-     * enclosing scope, which may define the same names.  For an example of
-     * where this comes up, see src/test/compile-fail/regions-ret-borrowed.rs
-     * and regions-ret-borrowed-1.rs. */
-    br_cap_avoid(ast::NodeId, @bound_region),
 }
 
 /**
@@ -868,12 +858,21 @@ pub struct TypeParameterDef {
     bounds: @ParamBounds
 }
 
-/// Information about the type/lifetime parametesr associated with an item.
+#[deriving(Encodable, Decodable, Clone)]
+pub struct RegionParameterDef {
+    ident: ast::Ident,
+    def_id: ast::DefId,
+}
+
+/// Information about the type/lifetime parameters associated with an item.
 /// Analogous to ast::Generics.
 #[deriving(Clone)]
 pub struct Generics {
+    /// List of type parameters declared on the item.
     type_param_defs: @~[TypeParameterDef],
-    region_param: Option<region_variance>,
+
+    /// List of region parameters declared on the item.
+    region_param_defs: @[RegionParameterDef],
 }
 
 impl Generics {
@@ -882,6 +881,33 @@ pub fn has_type_params(&self) -> bool {
     }
 }
 
+/// 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.
+///
+/// Note: This information might seem to be redundant with the data in
+/// `tcx.ty_param_defs`, but it is not. That table contains the
+/// parameter definitions from an "outside" perspective, but this
+/// struct will contain the bounds for a parameter as seen from inside
+/// the function body. Currently the only real distinction is that
+/// bound lifetime parameters are replaced with free ones, but in the
+/// future I hope to refine the representation of types so as to make
+/// more distinctions clearer.
+pub struct ParameterEnvironment {
+    /// A substitution that can be applied to move from
+    /// 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.
+    free_substs: ty::substs,
+
+    /// Bound on the Self parameter
+    self_param_bound: Option<@TraitRef>,
+
+    /// Bounds on each numbered type parameter
+    type_param_bounds: ~[ParamBounds],
+}
+
 /// A polytype.
 ///
 /// - `bounds`: The list of bounds for each type parameter.  The length of the
@@ -1255,14 +1281,17 @@ pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
     mk_t(cx, ty_bare_fn(fty))
 }
 
-pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
+pub fn mk_ctor_fn(cx: ctxt,
+                  binder_id: ast::NodeId,
+                  input_tys: &[ty::t],
+                  output: ty::t) -> t {
     let input_args = input_tys.map(|t| *t);
     mk_bare_fn(cx,
                BareFnTy {
                    purity: ast::impure_fn,
                    abis: AbiSet::Rust(),
                    sig: FnSig {
-                    bound_lifetime_names: opt_vec::Empty,
+                    binder_id: binder_id,
                     inputs: input_args,
                     output: output,
                     variadic: false
@@ -4662,3 +4691,79 @@ fn iter<T: IterBytes>(hash: &mut SipState, t: &T) {
 
     hash.result_u64()
 }
+
+pub fn construct_parameter_environment(
+    tcx: ctxt,
+    self_bound: Option<@TraitRef>,
+    item_type_params: &[TypeParameterDef],
+    method_type_params: &[TypeParameterDef],
+    item_region_params: &[RegionParameterDef],
+    free_id: ast::NodeId)
+    -> ParameterEnvironment
+{
+    /*! See `ParameterEnvironment` struct def'n for details */
+
+    //
+    // Construct the free substs.
+    //
+
+    // map Self => Self
+    let self_ty = self_bound.map(|t| ty::mk_self(tcx, t.def_id));
+
+    // map A => A
+    let num_item_type_params = item_type_params.len();
+    let num_method_type_params = method_type_params.len();
+    let num_type_params = num_item_type_params + num_method_type_params;
+    let type_params = vec::from_fn(num_type_params, |i| {
+            let def_id = if i < num_item_type_params {
+                item_type_params[i].def_id
+            } else {
+                method_type_params[i - num_item_type_params].def_id
+            };
+
+            ty::mk_param(tcx, i, def_id)
+        });
+
+    // map bound 'a => free 'a
+    let region_params = item_region_params.iter().
+        map(|r| ty::re_free(ty::FreeRegion {
+                scope_id: free_id,
+                bound_region: ty::br_named(r.def_id, r.ident)})).
+        collect();
+
+    let free_substs = substs {
+        self_ty: self_ty,
+        tps: type_params,
+        regions: ty::NonerasedRegions(region_params)
+    };
+
+    //
+    // Compute the bounds on Self and the type parameters.
+    //
+
+    let self_bound_substd = self_bound.map(|b| b.subst(tcx, &free_substs));
+    let type_param_bounds_substd = vec::from_fn(num_type_params, |i| {
+        if i < num_item_type_params {
+            (*item_type_params[i].bounds).subst(tcx, &free_substs)
+        } else {
+            let j = i - num_item_type_params;
+            (*method_type_params[j].bounds).subst(tcx, &free_substs)
+        }
+    });
+
+    ty::ParameterEnvironment {
+        free_substs: free_substs,
+        self_param_bound: self_bound_substd,
+        type_param_bounds: type_param_bounds_substd,
+    }
+}
+
+impl substs {
+    pub fn empty() -> substs {
+        substs {
+            self_ty: None,
+            tps: ~[],
+            regions: NonerasedRegions(opt_vec::Empty)
+        }
+    }
+}
index 11d995762ee72083c59815c1f35ee0773b97e837..0c0abaa5d76cf8036f92bae071eef4539c20231c 100644 (file)
@@ -154,13 +154,11 @@ pub fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
 fn ast_path_substs<AC:AstConv,RS:RegionScope>(
     this: &AC,
     rscope: &RS,
-    def_id: ast::DefId,
     decl_generics: &ty::Generics,
     self_ty: Option<ty::t>,
     path: &ast::Path) -> ty::substs
 {
     /*!
-     *
      * Given a path `path` that refers to an item `I` with the
      * declared generics `decl_generics`, returns an appropriate
      * set of substitutions for this particular reference to `I`.
@@ -171,30 +169,28 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
     // If the type is parameterized by the this region, then replace this
     // region with the current anon region binding (in other words,
     // whatever & would get replaced with).
-    let regions = match (&decl_generics.region_param,
-                         &path.segments.last().lifetime) {
-        (&None, &None) => {
-            opt_vec::Empty
-        }
-        (&None, &Some(_)) => {
+    let expected_num_region_params = decl_generics.region_param_defs.len();
+    let supplied_num_region_params = path.segments.last().lifetimes.len();
+    let regions = if expected_num_region_params == supplied_num_region_params {
+        path.segments.last().lifetimes.map(
+            |l| ast_region_to_region(this.tcx(), l))
+    } else {
+        let anon_regions =
+            rscope.anon_regions(path.span, expected_num_region_params);
+
+        if supplied_num_region_params != 0 || anon_regions.is_none() {
             tcx.sess.span_err(
                 path.span,
-                format!("no region bound is allowed on `{}`, \
-                      which is not declared as containing region pointers",
-                     ty::item_path_str(tcx, def_id)));
-            opt_vec::Empty
-        }
-        (&Some(_), &None) => {
-            let res = rscope.anon_region(path.span);
-            let r = get_region_reporting_err(this.tcx(), path.span, &None, res);
-            opt_vec::with(r)
+                format!("wrong number of lifetime parameters: \
+                        expected {} but found {}",
+                        expected_num_region_params,
+                        supplied_num_region_params));
         }
-        (&Some(_), &Some(_)) => {
-            opt_vec::with(
-                ast_region_to_region(this,
-                                     rscope,
-                                     path.span,
-                                     &path.segments.last().lifetime))
+
+        match anon_regions {
+            Some(v) => opt_vec::from(v),
+            None => opt_vec::from(vec::from_fn(expected_num_region_params,
+                                               |_| ty::re_static)) // hokey
         }
     };
 
@@ -234,7 +230,7 @@ pub fn ast_path_to_substs_and_ty<AC:AstConv,
         ty: decl_ty
     } = this.get_item_ty(did);
 
-    let substs = ast_path_substs(this, rscope, did, &generics, None, path);
+    let substs = ast_path_substs(this, rscope, &generics, None, path);
     let ty = ty::subst(tcx, &substs, decl_ty);
     ty_param_substs_and_ty { substs: substs, ty: ty }
 }
@@ -252,7 +248,6 @@ pub fn ast_path_to_trait_ref<AC:AstConv,RS:RegionScope>(
         ast_path_substs(
             this,
             rscope,
-            trait_def.trait_ref.def_id,
             &trait_def.generics,
             self_ty,
             path);
@@ -304,6 +299,7 @@ fn mk_pointer<AC:AstConv,RS:RegionScope>(
         constr: &fn(ty::mt) -> ty::t) -> ty::t
     {
         let tcx = this.tcx();
+        debug!("mk_pointer(vst={:?})", vst);
 
         match a_seq_ty.ty.node {
             ast::ty_vec(ref mt) => {
@@ -311,6 +307,7 @@ fn mk_pointer<AC:AstConv,RS:RegionScope>(
                 if a_seq_ty.mutbl == ast::MutMutable {
                     mt = ty::mt { ty: mt.ty, mutbl: a_seq_ty.mutbl };
                 }
+                debug!("&[]: vst={:?}", vst);
                 return ty::mk_evec(tcx, mt, vst);
             }
             ast::ty_path(ref path, ref bounds, id) => {
@@ -369,7 +366,7 @@ fn check_path_args(tcx: ty::ctxt,
         }
 
         if (flags & NO_REGIONS) != 0u {
-            if path.segments.last().lifetime.is_some() {
+            if !path.segments.last().lifetimes.is_empty() {
                 tcx.sess.span_err(
                     path.span,
                     "region parameters are not allowed on this type");
@@ -422,8 +419,8 @@ fn check_path_args(tcx: ty::ctxt,
           if bf.decl.variadic && !bf.abis.is_c() {
             tcx.sess.span_err(ast_ty.span, "variadic function must have C calling convention");
           }
-          ty::mk_bare_fn(tcx, ty_of_bare_fn(this, rscope, bf.purity,
-                                            bf.abis, &bf.lifetimes, &bf.decl))
+          ty::mk_bare_fn(tcx, ty_of_bare_fn(this, ast_ty.id, bf.purity,
+                                            bf.abis, &bf.decl))
       }
       ast::ty_closure(ref f) => {
         if f.sigil == ast::ManagedSigil {
@@ -440,6 +437,7 @@ fn check_path_args(tcx: ty::ctxt,
           });
           let fn_decl = ty_of_closure(this,
                                       rscope,
+                                      ast_ty.id,
                                       f.sigil,
                                       f.purity,
                                       f.onceness,
@@ -447,7 +445,6 @@ fn check_path_args(tcx: ty::ctxt,
                                       &f.region,
                                       &f.decl,
                                       None,
-                                      &f.lifetimes,
                                       ast_ty.span);
           ty::mk_closure(tcx, fn_decl)
       }
@@ -594,9 +591,8 @@ struct SelfInfo {
 
 pub fn ty_of_method<AC:AstConv>(
     this: &AC,
-    rscope: &RS,
+    id: ast::NodeId,
     purity: ast::purity,
-    lifetimes: &OptVec<ast::Lifetime>,
     untransformed_self_ty: ty::t,
     explicit_self: ast::explicit_self,
     decl: &ast::fn_decl) -> (Option<ty::t>, ty::BareFnTy)
@@ -606,33 +602,31 @@ pub fn ty_of_method<AC:AstConv>(
         explicit_self: explicit_self
     };
     let (a, b) = ty_of_method_or_bare_fn(
-        this, rscope, purity, AbiSet::Rust(), lifetimes, Some(&self_info), decl);
+        this, id, purity, AbiSet::Rust(), Some(&self_info), decl);
     (a.unwrap(), b)
 }
 
-pub fn ty_of_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
+pub fn ty_of_bare_fn<AC:AstConv>(
     this: &AC,
-    rscope: &RS,
+    id: ast::NodeId,
     purity: ast::purity,
     abi: AbiSet,
-    lifetimes: &OptVec<ast::Lifetime>,
     decl: &ast::fn_decl) -> ty::BareFnTy
 {
-    let (_, b) = ty_of_method_or_bare_fn(
-        this, rscope, purity, abi, lifetimes, None, decl);
+    let (_, b) = ty_of_method_or_bare_fn(this, id, purity,
+                                         abi, None, decl);
     b
 }
 
-fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
+fn ty_of_method_or_bare_fn<AC:AstConv>(
     this: &AC,
-    rscope: &RS,
+    id: ast::NodeId,
     purity: ast::purity,
     abi: AbiSet,
-    lifetimes: &OptVec<ast::Lifetime>,
     opt_self_info: Option<&SelfInfo>,
     decl: &ast::fn_decl) -> (Option<Option<ty::t>>, ty::BareFnTy)
 {
-    debug!("ty_of_bare_fn");
+    debug!("ty_of_method_or_bare_fn");
 
     // new region names that appear inside of the fn decl are bound to
     // that function type
@@ -653,12 +647,10 @@ fn ty_of_method_or_bare_fn<AC:AstConv,RS:RegionScope + Clone + 'static>(
             ty::BareFnTy {
                 purity: purity,
                 abis: abi,
-                sig: ty::FnSig {
-                    bound_lifetime_names: bound_lifetime_names,
-                    inputs: input_tys,
-                    output: output_ty,
-                    variadic: decl.variadic
-                }
+                sig: ty::FnSig {binder_id: id,
+                                inputs: input_tys,
+                                output: output_ty,
+                                variadic: decl.variadic}
             });
 
     fn transform_self_ty<AC:AstConv,RS:RegionScope>(
@@ -697,6 +689,7 @@ fn transform_self_ty<AC:AstConv,RS:RegionScope>(
 pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
     this: &AC,
     rscope: &RS,
+    id: ast::NodeId,
     sigil: ast::Sigil,
     purity: ast::purity,
     onceness: ast::Onceness,
@@ -704,17 +697,10 @@ pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
     opt_lifetime: &Option<ast::Lifetime>,
     decl: &ast::fn_decl,
     expected_sig: Option<ty::FnSig>,
-    lifetimes: &OptVec<ast::Lifetime>,
     span: Span)
     -> ty::ClosureTy
 {
-    // The caller should not both provide explicit bound lifetime
-    // names and expected types.  Either we infer the bound lifetime
-    // names or they are provided, but not both.
-    assert!(lifetimes.is_empty() || expected_sig.is_none());
-
     debug!("ty_of_fn_decl");
-    let _i = indenter();
 
     // resolve the function bound region in the original region
     // scope `rscope`, not the scope of the function parameters
@@ -763,12 +749,10 @@ pub fn ty_of_closure<AC:AstConv,RS:RegionScope>(
         onceness: onceness,
         region: bound_region,
         bounds: bounds,
-        sig: ty::FnSig {
-            bound_lifetime_names: bound_lifetime_names,
-            inputs: input_tys,
-            output: output_ty,
-            variadic: decl.variadic
-        }
+        sig: ty::FnSig {binder_id: id,
+                        inputs: input_tys,
+                        output: output_ty,
+                        variadic: decl.variadic}
     }
 }
 
index af1d5ce3cc608afc5b62ea8944b027566d468921..870b29882fd6eb167309d3e5a92a56009476f930 100644 (file)
@@ -85,7 +85,6 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
 use middle::ty;
 use middle::typeck::check::{FnCtxt, impl_self_ty};
 use middle::typeck::check::{structurally_resolved_type};
-use middle::typeck::check::vtable::VtableContext;
 use middle::typeck::check::vtable;
 use middle::typeck::check;
 use middle::typeck::infer;
@@ -99,7 +98,6 @@ trait `ToStr` imported, and I call `to_str()` on a value of type `T`,
 use std::hashmap::HashSet;
 use std::result;
 use std::vec;
-use extra::list::Nil;
 use syntax::ast::{DefId, sty_value, sty_region, sty_box};
 use syntax::ast::{sty_uniq, sty_static, NodeId};
 use syntax::ast::{MutMutable, MutImmutable};
@@ -265,8 +263,7 @@ fn search(&self, self_ty: ty::t) -> Option<method_map_entry> {
         self.search_for_autosliced_method(self_ty, autoderefs)
     }
 
-    fn deref(&self, ty: ty::t)
-                 -> Option<ty::t> {
+    fn deref(&self, ty: ty::t) -> Option<ty::t> {
         match ty::deref(self.tcx(), ty, false) {
             None => None,
             Some(t) => {
@@ -327,11 +324,10 @@ fn push_bound_candidates(&self, self_ty: ty::t) {
                 ty_param(p) => {
                     self.push_inherent_candidates_from_param(self_ty, p);
                 }
-                ty_self(self_did) => {
+                ty_self(*) => {
                     // Call is of the form "self.foo()" and appears in one
                     // of a trait's default method implementations.
-                    self.push_inherent_candidates_from_self(
-                        self_ty, self_did);
+                    self.push_inherent_candidates_from_self(self_ty);
                 }
                 _ => { /* No bound methods in these types */ }
             }
@@ -448,32 +444,20 @@ fn push_inherent_candidates_from_param(&self,
                                            param_ty: param_ty) {
         debug!("push_inherent_candidates_from_param(param_ty={:?})",
                param_ty);
-        let _indenter = indenter();
-
-        let tcx = self.tcx();
-        let type_param_def = match tcx.ty_param_defs.find(&param_ty.def_id.node) {
-            Some(t) => t,
-            None => {
-                tcx.sess.span_bug(
-                    self.expr.span,
-                    format!("No param def for {:?}", param_ty));
-            }
-        };
-
         self.push_inherent_candidates_from_bounds(
-            rcvr_ty, type_param_def.bounds.trait_bounds,
+            rcvr_ty,
+            self.fcx.inh.param_env.type_param_bounds[param_ty.idx].trait_bounds,
             param_numbered(param_ty.idx));
     }
 
 
     fn push_inherent_candidates_from_self(&self,
-                                              self_ty: ty::t,
-                                              did: DefId) {
-        let tcx = self.tcx();
-
-        let trait_ref = ty::lookup_trait_def(tcx, did).trait_ref;
+                                          rcvr_ty: ty::t) {
+        debug!("push_inherent_candidates_from_self()");
         self.push_inherent_candidates_from_bounds(
-            self_ty, &[trait_ref], param_self);
+            rcvr_ty,
+            [self.fcx.inh.param_env.self_param_bound.unwrap()],
+            param_self)
     }
 
     fn push_inherent_candidates_from_bounds(&self,
@@ -574,10 +558,7 @@ fn push_candidates_from_impl(&self,
         // determine the `self` of the impl with fresh
         // variables for each parameter:
         let location_info = &vtable::location_info_for_expr(self.self_expr);
-        let vcx = VtableContext {
-            ccx: self.fcx.ccx,
-            infcx: self.fcx.infcx()
-        };
+        let vcx = self.fcx.vtable_context();
         let ty::ty_param_substs_and_ty {
             substs: impl_substs,
             ty: impl_ty
@@ -1010,7 +991,7 @@ fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
         };
         let (_, opt_transformed_self_ty, fn_sig) =
             replace_bound_regions_in_fn_sig(
-                tcx, @Nil, Some(transformed_self_ty), &bare_fn_ty.sig,
+                tcx, Some(transformed_self_ty), &bare_fn_ty.sig,
                 |br| self.fcx.infcx().next_region_var(
                     infer::BoundRegionInFnCall(self.expr.span, br)));
         let transformed_self_ty = opt_transformed_self_ty.unwrap();
index 32284584b65837e03a54da2710679401ae2eb0ff..982bc493417677c053a34e361653e046dcfa4717 100644 (file)
 use middle::pat_util::pat_id_map;
 use middle::pat_util;
 use middle::lint::unreachable_code;
+use middle::subst::Subst;
 use middle::ty::{FnSig, VariantInfo};
 use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
 use middle::ty::{substs, param_ty, Disr, ExprTyProvider};
 use middle::ty;
+use middle::ty_fold::TypeFolder;
 use middle::typeck::astconv::AstConv;
 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
 use middle::typeck::astconv;
 use middle::typeck::CrateCtxt;
 use middle::typeck::infer::{resolve_type, force_tvar};
 use middle::typeck::infer;
-use middle::typeck::rscope::bound_self_region;
-use middle::typeck::rscope::{RegionError};
 use middle::typeck::rscope::RegionScope;
-use middle::typeck::{isr_alist, lookup_def_ccx};
+use middle::typeck::{lookup_def_ccx};
 use middle::typeck::no_params;
 use middle::typeck::{require_same_types, method_map, vtable_map};
 use util::common::{block_query, indenter, loop_query};
-use util::ppaux::{bound_region_ptr_to_str};
+use util::ppaux::UserString;
 use util::ppaux;
 
-
 use std::hashmap::HashMap;
 use std::result;
 use std::util::replace;
 use std::vec;
-use extra::list::Nil;
 use syntax::abi::AbiSet;
 use syntax::ast::{provided, required};
 use syntax::ast;
 use syntax::opt_vec::OptVec;
 use syntax::opt_vec;
 use syntax::parse::token;
-use syntax::parse::token::special_idents;
 use syntax::print::pprust;
 use syntax::visit;
 use syntax::visit::Visitor;
@@ -157,9 +154,10 @@ pub struct SelfInfo {
 /// Here, the function `foo()` and the closure passed to
 /// `bar()` will each have their own `FnCtxt`, but they will
 /// share the inherited fields.
-pub struct inherited {
+pub struct Inherited {
     infcx: @mut infer::InferCtxt,
     locals: @mut HashMap<ast::NodeId, ty::t>,
+    param_env: ty::ParameterEnvironment,
 
     // Temporary tables:
     node_types: @mut HashMap<ast::NodeId, ty::t>,
@@ -249,22 +247,25 @@ pub struct FnCtxt {
     // function return type.
     fn_kind: FnKind,
 
-    in_scope_regions: isr_alist,
-
-    inh: @inherited,
+    inh: @Inherited,
 
     ccx: @mut CrateCtxt,
 }
 
-pub fn blank_inherited(ccx: @mut CrateCtxt) -> @inherited {
-    @inherited {
-        infcx: infer::new_infer_ctxt(ccx.tcx),
-        locals: @mut HashMap::new(),
-        node_types: @mut HashMap::new(),
-        node_type_substs: @mut HashMap::new(),
-        adjustments: @mut HashMap::new(),
-        method_map: @mut HashMap::new(),
-        vtable_map: @mut HashMap::new(),
+impl Inherited {
+    fn new(tcx: ty::ctxt,
+           param_env: ty::ParameterEnvironment)
+           -> Inherited {
+        Inherited {
+            infcx: infer::new_infer_ctxt(tcx),
+            locals: @mut HashMap::new(),
+            param_env: param_env,
+            node_types: @mut HashMap::new(),
+            node_type_substs: @mut HashMap::new(),
+            adjustments: @mut HashMap::new(),
+            method_map: @mut HashMap::new(),
+            vtable_map: @mut HashMap::new(),
+        }
     }
 }
 
@@ -272,17 +273,19 @@ pub fn blank_inherited(ccx: @mut CrateCtxt) -> @inherited {
 pub fn blank_fn_ctxt(ccx: @mut CrateCtxt,
                      rty: ty::t,
                      region_bnd: ast::NodeId)
-                  -> @mut FnCtxt {
-// It's kind of a kludge to manufacture a fake function context
-// and statement context, but we might as well do write the code only once
+                     -> @mut FnCtxt {
+    // It's kind of a kludge to manufacture a fake function context
+    // and statement context, but we might as well do write the code only once
+    let param_env = ty::ParameterEnvironment { free_substs: substs::empty(),
+                                               self_param_bound: None,
+                                               type_param_bounds: ~[] };
     @mut FnCtxt {
         err_count_on_creation: ccx.tcx.sess.err_count(),
         ret_ty: rty,
         ps: PurityState::function(ast::impure_fn, 0),
         region_lb: region_bnd,
-        in_scope_regions: @Nil,
         fn_kind: Vanilla,
-        inh: blank_inherited(ccx),
+        inh: @Inherited::new(ccx.tcx, param_env),
         ccx: ccx
     }
 }
@@ -315,14 +318,15 @@ pub fn check_bare_fn(ccx: @mut CrateCtxt,
                      decl: &ast::fn_decl,
                      body: &ast::Block,
                      id: ast::NodeId,
-                     self_info: Option<SelfInfo>) {
-    let fty = ty::node_id_to_type(ccx.tcx, id);
+                     self_info: Option<SelfInfo>,
+                     fty: ty::t,
+                     param_env: ty::ParameterEnvironment) {
     match ty::get(fty).sty {
         ty::ty_bare_fn(ref fn_ty) => {
             let fcx =
                 check_fn(ccx, self_info, fn_ty.purity,
                          &fn_ty.sig, decl, id, body, Vanilla,
-                         @Nil, blank_inherited(ccx));;
+                         @Inherited::new(ccx.tcx, param_env));
 
             vtable::resolve_in_block(fcx, body);
             regionck::regionck_fn(fcx, body);
@@ -411,39 +415,35 @@ pub fn check_fn(ccx: @mut CrateCtxt,
                 id: ast::NodeId,
                 body: &ast::Block,
                 fn_kind: FnKind,
-                inherited_isr: isr_alist,
-                inherited: @inherited) -> @mut FnCtxt
+                inherited: @Inherited) -> @mut FnCtxt
 {
     /*!
-     *
      * Helper used by check_bare_fn and check_expr_fn.  Does the
      * grungy work of checking a function body and returns the
      * function context used for that purpose, since in the case of a
      * fn item there is still a bit more to do.
      *
      * - ...
-     * - inherited_isr: regions in scope from the enclosing fn (if any)
      * - inherited: other fields inherited from the enclosing fn (if any)
      */
 
     let tcx = ccx.tcx;
     let err_count_on_creation = tcx.sess.err_count();
 
-    // ______________________________________________________________________
     // First, we have to replace any bound regions in the fn and self
     // types with free ones.  The free region references will be bound
     // the node_id of the body block.
-    let (isr, opt_self_info, fn_sig) = {
+    let (opt_self_info, fn_sig) = {
         let opt_self_ty = opt_self_info.map(|i| i.self_ty);
-        let (isr, opt_self_ty, fn_sig) =
+        let (_, opt_self_ty, fn_sig) =
             replace_bound_regions_in_fn_sig(
-                tcx, inherited_isr, opt_self_ty, fn_sig,
+                tcx, opt_self_ty, fn_sig,
                 |br| ty::re_free(ty::FreeRegion {scope_id: body.id,
                                                  bound_region: br}));
         let opt_self_info =
             opt_self_info.map(
                 |si| SelfInfo {self_ty: opt_self_ty.unwrap(), .. si});
-        (isr, opt_self_info, fn_sig)
+        (opt_self_info, fn_sig)
     };
 
     relate_free_regions(tcx, opt_self_info.map(|s| s.self_ty), &fn_sig);
@@ -456,7 +456,6 @@ pub fn check_fn(ccx: @mut CrateCtxt,
            ppaux::ty_to_str(tcx, ret_ty),
            opt_self_info.map(|si| ppaux::ty_to_str(tcx, si.self_ty)));
 
-    // ______________________________________________________________________
     // Create the function context.  This is either derived from scratch or,
     // in the case of function expressions, based on the outer context.
     let fcx: @mut FnCtxt = {
@@ -465,7 +464,6 @@ pub fn check_fn(ccx: @mut CrateCtxt,
             ret_ty: ret_ty,
             ps: PurityState::function(purity, id),
             region_lb: body.id,
-            in_scope_regions: isr,
             fn_kind: fn_kind,
             inh: inherited,
             ccx: ccx
@@ -536,26 +534,6 @@ fn gather_locals(fcx: @mut FnCtxt,
     }
 }
 
-pub fn check_method(ccx: @mut CrateCtxt,
-                    method: @ast::method)
-{
-    let method_def_id = local_def(method.id);
-    let method_ty = ty::method(ccx.tcx, method_def_id);
-    let opt_self_info = method_ty.transformed_self_ty.map(|ty| {
-        SelfInfo {self_ty: ty,
-                  self_id: method.self_id,
-                  span: method.explicit_self.span}
-    });
-
-    check_bare_fn(
-        ccx,
-        &method.decl,
-        &method.body,
-        method.id,
-        opt_self_info
-    );
-}
-
 pub fn check_no_duplicate_fields(tcx: ty::ctxt,
                                  fields: ~[(ast::Ident, Span)]) {
     let mut field_names = HashMap::new();
@@ -566,7 +544,7 @@ pub fn check_no_duplicate_fields(tcx: ty::ctxt,
         match orig_sp {
             Some(orig_sp) => {
                 tcx.sess.span_err(sp, format!("Duplicate field name {} in record type declaration",
-                                           tcx.sess.str_of(id)));
+                                              tcx.sess.str_of(id)));
                 tcx.sess.span_note(orig_sp, "First declaration of this field occurred here");
                 break;
             }
@@ -603,18 +581,32 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
                             it.id);
       }
       ast::item_fn(ref decl, _, _, _, ref body) => {
-        check_bare_fn(ccx, decl, body, it.id, None);
+        let fn_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
+
+            // FIXME -- this won't fly for the case where people reference
+            // a lifetime from within a type parameter. That's actually fairly
+            // tricky.
+        let param_env = ty::construct_parameter_environment(
+                ccx.tcx,
+                None,
+                *fn_tpt.generics.type_param_defs,
+                [],
+                [],
+                body.id);
+
+        check_bare_fn(ccx, decl, body, it.id, None, fn_tpt.ty, param_env);
       }
-      ast::item_impl(_, _, _, ref ms) => {
-        let rp = ccx.tcx.region_paramd_items.find(&it.id).map(|x| *x);
-        debug!("item_impl {} with id {} rp {:?}",
-               ccx.tcx.sess.str_of(it.ident), it.id, rp);
+      ast::item_impl(_, ref opt_trait_ref, _, ref ms) => {
+        debug!("item_impl {} with id {}", ccx.tcx.sess.str_of(it.ident), it.id);
+
+        let impl_tpt = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
         for m in ms.iter() {
-            check_method(ccx, *m);
+            check_method_body(ccx, &impl_tpt.generics, None, *m);
         }
         vtable::resolve_impl(ccx, it);
       }
       ast::item_trait(_, _, ref trait_methods) => {
+        let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_method in (*trait_methods).iter() {
             match *trait_method {
               required(*) => {
@@ -622,7 +614,8 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
                 // bodies to check.
               }
               provided(m) => {
-                check_method(ccx, m);
+                check_method_body(ccx, &trait_def.generics,
+                                  Some(trait_def.trait_ref), m);
               }
             }
         }
@@ -662,6 +655,58 @@ pub fn check_item(ccx: @mut CrateCtxt, it: @ast::item) {
     }
 }
 
+fn check_method_body(ccx: @mut CrateCtxt,
+                     item_generics: &ty::Generics,
+                     self_bound: Option<@ty::TraitRef>,
+                     method: @ast::method) {
+    /*!
+     * Type checks a method body.
+     *
+     * # Parameters
+     * - `item_generics`: generics defined on the impl/trait that contains
+     *   the method
+     * - `self_bound`: bound for the `Self` type parameter, if any
+     * - `method`: the method definition
+     */
+
+    debug!("check_method_body(item_generics={}, \
+            self_bound={}, \
+            method.id={})",
+            item_generics.repr(ccx.tcx),
+            self_bound.repr(ccx.tcx),
+            method.id);
+    let method_def_id = local_def(method.id);
+    let method_ty = ty::method(ccx.tcx, method_def_id);
+    let method_generics = &method_ty.generics;
+
+    let param_env =
+        ty::construct_parameter_environment(
+            ccx.tcx,
+            self_bound,
+            *item_generics.type_param_defs,
+            *method_generics.type_param_defs,
+            item_generics.region_param_defs,
+            method.body.id);
+
+    // Compute the self type and fty from point of view of inside fn
+    let opt_self_info = method_ty.transformed_self_ty.map(|ty| {
+        SelfInfo {self_ty: ty.subst(ccx.tcx, &param_env.free_substs),
+                  self_id: method.self_id,
+                  span: method.explicit_self.span}
+    });
+    let fty = ty::node_id_to_type(ccx.tcx, method.id);
+    let fty = fty.subst(ccx.tcx, &param_env.free_substs);
+
+    check_bare_fn(
+        ccx,
+        &method.decl,
+        &method.body,
+        method.id,
+        opt_self_info,
+        fty,
+        param_env);
+}
+
 impl AstConv for FnCtxt {
     fn tcx(&self) -> ty::ctxt { self.ccx.tcx }
 
@@ -682,48 +727,26 @@ impl FnCtxt {
     pub fn infcx(&self) -> @mut infer::InferCtxt {
         self.inh.infcx
     }
+
     pub fn err_count_since_creation(&self) -> uint {
         self.ccx.tcx.sess.err_count() - self.err_count_on_creation
     }
-    pub fn search_in_scope_regions(&self,
-                                   span: Span,
-                                   br: ty::bound_region)
-                                   -> Result<ty::Region, RegionError> {
-        let in_scope_regions = self.in_scope_regions;
-        match in_scope_regions.find(br) {
-            Some(r) => result::Ok(r),
-            None => {
-                let blk_br = ty::br_named(special_idents::blk);
-                if br == blk_br {
-                    result::Ok(self.block_region())
-                } else {
-                    result::Err(RegionError {
-                        msg: {
-                            format!("named region `{}` not in scope here",
-                                 bound_region_ptr_to_str(self.tcx(), br))
-                        },
-                        replacement: {
-                            self.infcx().next_region_var(
-                                infer::BoundRegionError(span))
-                        }
-                    })
-                }
-            }
+
+    pub fn vtable_context<'a>(&'a self) -> VtableContext<'a> {
+        VtableContext {
+            infcx: self.infcx(),
+            param_env: &self.inh.param_env
         }
     }
 }
 
-impl RegionScope for FnCtxt {
-    fn anon_region(&self, span: Span) -> Result<ty::Region, RegionError> {
-        result::Ok(self.infcx().next_region_var(infer::MiscVariable(span)))
-    }
-    fn self_region(&self, span: Span) -> Result<ty::Region, RegionError> {
-        self.search_in_scope_regions(span, ty::br_self)
-    }
-    fn named_region(&self,
+impl RegionScope for @mut infer::InferCtxt {
+    fn anon_regions(&self,
                     span: Span,
-                    id: ast::Ident) -> Result<ty::Region, RegionError> {
-        self.search_in_scope_regions(span, ty::br_named(id))
+                    count: uint) -> Option<~[ty::Region]> {
+        Some(vec::from_fn(
+                count,
+                |_| self.next_region_var(infer::MiscVariable(span))))
     }
 }
 
@@ -805,7 +828,7 @@ pub fn write_error(@mut self, node_id: ast::NodeId) {
     }
 
     pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
-        ast_ty_to_ty(self, self, ast_t)
+        ast_ty_to_ty(self, &self.infcx(), ast_t)
     }
 
     pub fn pat_to_str(&self, pat: @ast::Pat) -> ~str {
@@ -817,7 +840,7 @@ pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
             Some(&t) => t,
             None => {
                 self.tcx().sess.bug(format!("no type for expr in fcx {}",
-                                         self.tag()));
+                                            self.tag()));
             }
         }
     }
@@ -828,10 +851,10 @@ pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
             None => {
                 self.tcx().sess.bug(
                     format!("no type for node {}: {} in fcx {}",
-                         id, ast_map::node_id_to_str(
-                             self.tcx().items, id,
-                             token::get_ident_interner()),
-                         self.tag()));
+                            id, ast_map::node_id_to_str(
+                                self.tcx().items, id,
+                                token::get_ident_interner()),
+                            self.tag()));
             }
         }
     }
@@ -842,10 +865,9 @@ pub fn node_ty_substs(&self, id: ast::NodeId) -> ty::substs {
             None => {
                 self.tcx().sess.bug(
                     format!("no type substs for node {}: {} in fcx {}",
-                         id, ast_map::node_id_to_str(
-                             self.tcx().items, id,
-                             token::get_ident_interner()),
-                         self.tag()));
+                            id, ast_map::node_id_to_str(self.tcx().items, id,
+                                                        token::get_ident_interner()),
+                            self.tag()));
             }
         }
     }
@@ -924,20 +946,6 @@ pub fn with_region_lb<R>(@mut self, lb: ast::NodeId, f: &fn() -> R)
         v
     }
 
-    pub fn region_var_if_parameterized(&self,
-                                       rp: Option<ty::region_variance>,
-                                       span: Span)
-                                       -> OptVec<ty::Region> {
-        match rp {
-            None => opt_vec::Empty,
-            Some(_) => {
-                opt_vec::with(
-                    self.infcx().next_region_var(
-                        infer::BoundRegionInTypeOrImpl(span)))
-            }
-        }
-    }
-
     pub fn type_error_message(&self,
                               sp: Span,
                               mk_msg: &fn(~str) -> ~str,
@@ -1105,20 +1113,22 @@ pub fn impl_self_ty(vcx: &VtableContext,
                  -> ty_param_substs_and_ty {
     let tcx = vcx.tcx();
 
-    let (n_tps, region_param, raw_ty) = {
+    let (n_tps, n_rps, raw_ty) = {
         let ity = ty::lookup_item_type(tcx, did);
-        (ity.generics.type_param_defs.len(), ity.generics.region_param, ity.ty)
+        (ity.generics.type_param_defs.len(),
+         ity.generics.region_param_defs.len(),
+         ity.ty)
     };
 
-    let regions = ty::NonerasedRegions(if region_param.is_some() {
-        opt_vec::with(vcx.infcx.next_region_var(
-            infer::BoundRegionInTypeOrImpl(location_info.span)))
-    } else {
-        opt_vec::Empty
-    });
+    let rps =
+        vcx.infcx.next_region_vars(
+            infer::BoundRegionInTypeOrImpl(location_info.span),
+            n_rps);
     let tps = vcx.infcx.next_ty_vars(n_tps);
 
-    let substs = substs {regions: regions, self_ty: None, tps: tps};
+    let substs = substs {regions: ty::NonerasedRegions(opt_vec::from(rps)),
+                         self_ty: None,
+                         tps: tps};
     let substd_ty = ty::subst(tcx, &substs, raw_ty);
 
     ty_param_substs_and_ty { substs: substs, ty: substd_ty }
@@ -1174,22 +1184,21 @@ fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt,
     // Verify that no lifetimes or type parameters are present anywhere
     // except the final two elements of the path.
     for i in range(0, path.segments.len() - 2) {
-        match path.segments[i].lifetime {
-            None => {}
-            Some(lifetime) => {
-                function_context.tcx()
-                                .sess
-                                .span_err(lifetime.span,
-                                          "lifetime parameters may not \
-                                           appear here")
-            }
+        for lifetime in path.segments[i].lifetimes.iter() {
+            function_context.tcx()
+                .sess
+                .span_err(lifetime.span,
+                          "lifetime parameters may not \
+                          appear here");
+            break;
         }
 
         for typ in path.segments[i].types.iter() {
             function_context.tcx()
                             .sess
                             .span_err(typ.span,
-                                      "type parameters may not appear here")
+                                      "type parameters may not appear here");
+            break;
         }
     }
 
@@ -1197,7 +1206,7 @@ fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt,
     // rest of typechecking will (attempt to) infer everything.
     if path.segments
            .iter()
-           .all(|s| s.lifetime.is_none() && s.types.is_empty()) {
+           .all(|s| s.lifetimes.is_empty() && s.types.is_empty()) {
         return
     }
 
@@ -1219,26 +1228,17 @@ fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt,
 
             // Make sure lifetime parameterization agrees with the trait or
             // implementation type.
-            match (generics.region_param, trait_segment.lifetime) {
-                (Some(_), None) => {
-                    function_context.tcx()
-                                    .sess
-                                    .span_err(path.span,
-                                              format!("this {} has a lifetime \
-                                                    parameter but no \
-                                                    lifetime was specified",
-                                                   name))
-                }
-                (None, Some(_)) => {
-                    function_context.tcx()
-                                    .sess
-                                    .span_err(path.span,
-                                              format!("this {} has no lifetime \
-                                                    parameter but a lifetime \
-                                                    was specified",
-                                                   name))
-                }
-                (Some(_), Some(_)) | (None, None) => {}
+            let trait_region_parameter_count = generics.region_param_defs.len();
+            let supplied_region_parameter_count = trait_segment.lifetimes.len();
+            if trait_region_parameter_count != supplied_region_parameter_count
+                && supplied_region_parameter_count != 0 {
+                function_context.tcx()
+                    .sess
+                    .span_err(path.span,
+                              format!("expected {} lifetime parameter(s), \
+                                      found {} lifetime parameter(s)",
+                                      trait_region_parameter_count,
+                                      supplied_region_parameter_count));
             }
 
             // Make sure the number of type parameters supplied on the trait
@@ -1276,15 +1276,13 @@ fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt,
             // Verify that no lifetimes or type parameters are present on
             // the penultimate segment of the path.
             let segment = &path.segments[path.segments.len() - 2];
-            match segment.lifetime {
-                None => {}
-                Some(lifetime) => {
-                    function_context.tcx()
-                                    .sess
-                                    .span_err(lifetime.span,
-                                              "lifetime parameters may not
-                                               appear here")
-                }
+            for lifetime in segment.lifetimes.iter() {
+                function_context.tcx()
+                    .sess
+                    .span_err(lifetime.span,
+                              "lifetime parameters may not
+                              appear here");
+                break;
             }
             for typ in segment.types.iter() {
                 function_context.tcx()
@@ -1292,10 +1290,7 @@ fn check_type_parameter_positions_in_path(function_context: @mut FnCtxt,
                                 .span_err(typ.span,
                                           "type parameters may not appear \
                                            here");
-                function_context.tcx()
-                                .sess
-                                .span_note(typ.span,
-                                           format!("this is a {:?}", def));
+                break;
             }
         }
     }
@@ -1556,7 +1551,7 @@ fn check_call(fcx: @mut FnCtxt,
         // In that case, we check each argument against "error" in order to
         // set up all the node type bindings.
         let error_fn_sig = FnSig {
-            bound_lifetime_names: opt_vec::Empty,
+            binder_id: ast::CRATE_NODE_ID,
             inputs: err_args(args.len()),
             output: ty::mk_err(),
             variadic: false
@@ -1577,7 +1572,6 @@ fn check_call(fcx: @mut FnCtxt,
         // signature with region variables
         let (_, _, fn_sig) =
             replace_bound_regions_in_fn_sig(fcx.tcx(),
-                                            @Nil,
                                             None,
                                             fn_sig,
                                             |br| fcx.infcx()
@@ -1908,10 +1902,10 @@ fn check_expr_fn(fcx: @mut FnCtxt,
                      expected: Option<ty::t>) {
         let tcx = fcx.ccx.tcx;
 
-        // Find the expected input/output types (if any).  Careful to
-        // avoid capture of bound regions in the expected type.  See
-        // def'n of br_cap_avoid() for a more lengthy explanation of
-        // what's going on here.
+        // Find the expected input/output types (if any). Substitute
+        // fresh bound regions for any bound regions we find in the
+        // expected types so as to avoid capture.
+        //
         // Also try to pick up inferred purity and sigil, defaulting
         // to impure and block. Note that we only will use those for
         // block syntax lambdas; that is, lambdas without explicit
@@ -1927,11 +1921,10 @@ fn check_expr_fn(fcx: @mut FnCtxt,
              expected_bounds) = {
             match expected_sty {
                 Some(ty::ty_closure(ref cenv)) => {
-                    let id = expr.id;
                     let (_, _, sig) =
                         replace_bound_regions_in_fn_sig(
-                            tcx, @Nil, None, &cenv.sig,
-                            |br| ty::re_bound(ty::br_cap_avoid(id, @br)));
+                            tcx, None, &cenv.sig,
+                            |_| fcx.inh.infcx.fresh_bound_region(expr.id));
                     (Some(sig), cenv.purity, cenv.sigil,
                      cenv.onceness, cenv.bounds)
                 }
@@ -1952,7 +1945,8 @@ fn check_expr_fn(fcx: @mut FnCtxt,
 
         // construct the function type
         let fn_ty = astconv::ty_of_closure(fcx,
-                                           fcx,
+                                           &fcx.infcx(),
+                                           expr.id,
                                            sigil,
                                            purity,
                                            expected_onceness,
@@ -1960,13 +1954,12 @@ fn check_expr_fn(fcx: @mut FnCtxt,
                                            &None,
                                            decl,
                                            expected_sig,
-                                           &opt_vec::Empty,
                                            expr.span);
 
         let fty_sig;
         let fty = if error_happened {
             fty_sig = FnSig {
-                bound_lifetime_names: opt_vec::Empty,
+                binder_id: ast::CRATE_NODE_ID,
                 inputs: fn_ty.sig.inputs.map(|_| ty::mk_err()),
                 output: ty::mk_err(),
                 variadic: false
@@ -1989,7 +1982,7 @@ fn check_expr_fn(fcx: @mut FnCtxt,
                                            sigil);
 
         check_fn(fcx.ccx, None, inherited_purity, &fty_sig,
-                 decl, id, body, fn_kind, fcx.in_scope_regions, fcx.inh);
+                 decl, id, body, fn_kind, fcx.inh);
     }
 
 
@@ -2168,50 +2161,18 @@ fn check_struct_constructor(fcx: @mut FnCtxt,
 
         // Look up the number of type parameters and the raw type, and
         // determine whether the class is region-parameterized.
-        let type_parameter_count;
-        let region_parameterized;
-        let raw_type;
-        if class_id.crate == ast::LOCAL_CRATE {
-            region_parameterized =
-                tcx.region_paramd_items.find(&class_id.node).
-                    map(|x| *x);
-            match tcx.items.find(&class_id.node) {
-                Some(&ast_map::node_item(@ast::item {
-                        node: ast::item_struct(_, ref generics),
-                        _
-                    }, _)) => {
-
-                    type_parameter_count = generics.ty_params.len();
-
-                    let self_region =
-                        bound_self_region(region_parameterized);
-
-                    raw_type = ty::mk_struct(tcx, class_id, substs {
-                        regions: ty::NonerasedRegions(self_region),
-                        self_ty: None,
-                        tps: ty::ty_params_to_tys(
-                            tcx,
-                            generics)
-                    });
-                }
-                _ => {
-                    tcx.sess.span_bug(span,
-                                      "resolve didn't map this to a class");
-                }
-            }
-        } else {
-            let item_type = ty::lookup_item_type(tcx, class_id);
-            type_parameter_count = item_type.generics.type_param_defs.len();
-            region_parameterized = item_type.generics.region_param;
-            raw_type = item_type.ty;
-        }
+        let item_type = ty::lookup_item_type(tcx, class_id);
+        let type_parameter_count = item_type.generics.type_param_defs.len();
+        let region_parameter_count = item_type.generics.region_param_defs.len();
+        let raw_type = item_type.ty;
 
         // Generate the struct type.
-        let regions =
-            fcx.region_var_if_parameterized(region_parameterized, span);
+        let regions = fcx.infcx().next_region_vars(
+            infer::BoundRegionInTypeOrImpl(span),
+            region_parameter_count);
         let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
         let substitutions = substs {
-            regions: ty::NonerasedRegions(regions),
+            regions: ty::NonerasedRegions(opt_vec::from(regions)),
             self_ty: None,
             tps: type_parameters
         };
@@ -2258,48 +2219,18 @@ fn check_struct_enum_variant(fcx: @mut FnCtxt,
 
         // Look up the number of type parameters and the raw type, and
         // determine whether the enum is region-parameterized.
-        let type_parameter_count;
-        let region_parameterized;
-        let raw_type;
-        if enum_id.crate == ast::LOCAL_CRATE {
-            region_parameterized =
-                tcx.region_paramd_items.find(&enum_id.node).map(|x| *x);
-            match tcx.items.find(&enum_id.node) {
-                Some(&ast_map::node_item(@ast::item {
-                        node: ast::item_enum(_, ref generics),
-                        _
-                    }, _)) => {
-
-                    type_parameter_count = generics.ty_params.len();
-
-                    let regions = bound_self_region(region_parameterized);
-
-                    raw_type = ty::mk_enum(tcx, enum_id, substs {
-                        regions: ty::NonerasedRegions(regions),
-                        self_ty: None,
-                        tps: ty::ty_params_to_tys(
-                            tcx,
-                            generics)
-                    });
-                }
-                _ => {
-                    tcx.sess.span_bug(span,
-                                      "resolve didn't map this to an enum");
-                }
-            }
-        } else {
-            let item_type = ty::lookup_item_type(tcx, enum_id);
-            type_parameter_count = item_type.generics.type_param_defs.len();
-            region_parameterized = item_type.generics.region_param;
-            raw_type = item_type.ty;
-        }
+        let item_type = ty::lookup_item_type(tcx, enum_id);
+        let type_parameter_count = item_type.generics.type_param_defs.len();
+        let region_parameter_count = item_type.generics.region_param_defs.len();
+        let raw_type = item_type.ty;
 
         // Generate the enum type.
-        let regions =
-            fcx.region_var_if_parameterized(region_parameterized, span);
+        let regions = fcx.infcx().next_region_vars(
+            infer::BoundRegionInTypeOrImpl(span),
+            region_parameter_count);
         let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
         let substitutions = substs {
-            regions: ty::NonerasedRegions(regions),
+            regions: ty::NonerasedRegions(opt_vec::from(regions)),
             self_ty: None,
             tps: type_parameters
         };
@@ -3445,28 +3376,25 @@ pub fn instantiate_path(fcx: @mut FnCtxt,
            ty_param_count,
            ty_substs_len);
 
-    // determine the region bound, using the value given by the user
+    // determine the region parameters, using the value given by the user
     // (if any) and otherwise using a fresh region variable
-    let regions = match pth.segments.last().lifetime {
-        Some(_) => { // user supplied a lifetime parameter...
-            match tpt.generics.region_param {
-                None => { // ...but the type is not lifetime parameterized!
-                    fcx.ccx.tcx.sess.span_err
-                        (span, "this item is not region-parameterized");
-                    opt_vec::Empty
-                }
-                Some(_) => { // ...and the type is lifetime parameterized, ok.
-                    opt_vec::with(
-                        ast_region_to_region(fcx,
-                                             fcx,
-                                             span,
-                                             &pth.segments.last().lifetime))
-                }
-            }
-        }
-        None => { // no lifetime parameter supplied, insert default
-            fcx.region_var_if_parameterized(tpt.generics.region_param, span)
+    let num_expected_regions = tpt.generics.region_param_defs.len();
+    let num_supplied_regions = pth.segments.last().lifetimes.len();
+    let regions = if num_expected_regions == num_supplied_regions {
+        pth.segments.last().lifetimes.map(
+            |l| ast_region_to_region(fcx.tcx(), l))
+    } else {
+        if num_supplied_regions != 0 {
+            fcx.ccx.tcx.sess.span_err(
+                span,
+                format!("expected {} lifetime parameter(s), \
+                        found {} lifetime parameter(s)",
+                        num_expected_regions, num_supplied_regions));
         }
+
+        opt_vec::from(fcx.infcx().next_region_vars(
+                infer::BoundRegionInTypeOrImpl(span),
+                num_expected_regions))
     };
 
     // Special case: If there is a self parameter, omit it from the list of
@@ -3642,18 +3570,14 @@ pub fn check_bounds_are_used(ccx: @mut CrateCtxt,
     if tps.len() == 0u { return; }
     let mut tps_used = vec::from_elem(tps.len(), false);
 
-    ty::walk_regions_and_ty(
-        ccx.tcx, ty,
-        |_r| {},
-        |t| {
+    ty::walk_ty(ty, |t| {
             match ty::get(t).sty {
-              ty::ty_param(param_ty {idx, _}) => {
-                  debug!("Found use of ty param \\#{}", idx);
-                  tps_used[idx] = true;
-              }
-              _ => ()
+                ty::ty_param(param_ty {idx, _}) => {
+                    debug!("Found use of ty param \\#{}", idx);
+                    tps_used[idx] = true;
+                }
+                _ => ()
             }
-            true
         });
 
     for (i, b) in tps_used.iter().enumerate() {
@@ -3680,19 +3604,19 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
         //We only care about the operation here
         match split[1] {
             "cxchg" => (0, ~[ty::mk_mut_rptr(tcx,
-                                             ty::re_bound(ty::br_anon(0)),
+                                             ty::re_fn_bound(it.id, ty::br_anon(0)),
                                              ty::mk_int()),
                         ty::mk_int(),
                         ty::mk_int()
                         ], ty::mk_int()),
             "load" => (0,
                ~[
-                  ty::mk_imm_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int())
+                  ty::mk_imm_rptr(tcx, ty::re_fn_bound(it.id, ty::br_anon(0)), ty::mk_int())
                ],
               ty::mk_int()),
             "store" => (0,
                ~[
-                  ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
+                  ty::mk_mut_rptr(tcx, ty::re_fn_bound(it.id, ty::br_anon(0)), ty::mk_int()),
                   ty::mk_int()
                ],
                ty::mk_nil()),
@@ -3700,7 +3624,7 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or"   | "xor"  | "max"  |
             "min"  | "umax" | "umin" => {
                 (0, ~[ty::mk_mut_rptr(tcx,
-                                      ty::re_bound(ty::br_anon(0)),
+                                      ty::re_fn_bound(it.id, ty::br_anon(0)),
                                       ty::mk_int()), ty::mk_int() ], ty::mk_int())
             }
             "fence" => {
@@ -3726,7 +3650,7 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
             "move_val" | "move_val_init" => {
                 (1u,
                  ~[
-                    ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), param(ccx, 0)),
+                    ty::mk_mut_rptr(tcx, ty::re_fn_bound(it.id, ty::br_anon(0)), param(ccx, 0)),
                     param(ccx, 0u)
                   ],
                ty::mk_nil())
@@ -3738,7 +3662,7 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
             "atomic_xchg_rel" | "atomic_xadd_rel" | "atomic_xsub_rel" => {
               (0,
                ~[
-                  ty::mk_mut_rptr(tcx, ty::re_bound(ty::br_anon(0)), ty::mk_int()),
+                  ty::mk_mut_rptr(tcx, ty::re_fn_bound(it.id, ty::br_anon(0)), ty::mk_int()),
                   ty::mk_int()
                ],
                ty::mk_int())
@@ -3761,7 +3685,7 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
                   Ok(t) => t,
                   Err(s) => { tcx.sess.span_fatal(it.span, s); }
               };
-              let region = ty::re_bound(ty::br_anon(0));
+              let region = ty::re_fn_bound(it.id, ty::br_anon(0));
               let visitor_object_ty = match ty::visitor_object_ty(tcx, region) {
                   Ok((_, vot)) => vot,
                   Err(s) => { tcx.sess.span_fatal(it.span, s); }
@@ -3953,12 +3877,10 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
     let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
         purity: ast::unsafe_fn,
         abis: AbiSet::Intrinsic(),
-        sig: FnSig {
-            bound_lifetime_names: opt_vec::Empty,
-            inputs: inputs,
-            output: output,
-            variadic: false
-        }
+        sig: FnSig {binder_id: it.id,
+                    inputs: inputs,
+                    output: output,
+                    variadic: false}
     });
     let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
     let i_n_tps = i_ty.generics.type_param_defs.len();
@@ -3974,3 +3896,4 @@ fn param(ccx: @mut CrateCtxt, n: uint) -> ty::t {
                      ppaux::ty_to_str(ccx.tcx, fty)));
     }
 }
+
index c0aa669d920ab4bd3f826b49bda78b6b93fe6afc..cd94e040ac371ee3dd82631d1eb9f0f0728dbd7b 100644 (file)
@@ -535,8 +535,14 @@ fn constrain_call(rcx: &mut Rcx,
     //! appear in the arguments appropriately.
 
     let tcx = rcx.fcx.tcx();
-    debug!("constrain_call(call_expr={}, implicitly_ref_args={:?})",
-           call_expr.repr(tcx), implicitly_ref_args);
+    debug!("constrain_call(call_expr={}, \
+            receiver={}, \
+            arg_exprs={}, \
+            implicitly_ref_args={:?})",
+            call_expr.repr(tcx),
+            receiver.repr(tcx),
+            arg_exprs.repr(tcx),
+            implicitly_ref_args);
     let callee_ty = rcx.resolve_node_type(callee_id);
     if ty::type_is_error(callee_ty) {
         // Bail, as function type is unknown
@@ -552,6 +558,8 @@ fn constrain_call(rcx: &mut Rcx,
     let callee_region = ty::re_scope(callee_scope);
 
     for &arg_expr in arg_exprs.iter() {
+        debug!("Argument");
+
         // ensure that any regions appearing in the argument type are
         // valid for at least the lifetime of the function:
         constrain_regions_in_type_of_node(
@@ -569,6 +577,7 @@ fn constrain_call(rcx: &mut Rcx,
 
     // as loop above, but for receiver
     for &r in receiver.iter() {
+        debug!("Receiver");
         constrain_regions_in_type_of_node(
             rcx, r.id, callee_region, infer::CallRcvr(r.span));
         if implicitly_ref_args {
@@ -727,9 +736,9 @@ fn constrain_regions_in_type(
            ty_to_str(tcx, ty));
 
     do relate_nested_regions(tcx, Some(minimum_lifetime), ty) |r_sub, r_sup| {
-        debug!("relate(r_sub={}, r_sup={})",
-               region_to_str(tcx, "", false, r_sub),
-               region_to_str(tcx, "", false, r_sup));
+        debug!("relate_nested_regions(r_sub={}, r_sup={})",
+                r_sub.repr(tcx),
+                r_sup.repr(tcx));
 
         if r_sup.is_bound() || r_sub.is_bound() {
             // a bound region is one which appears inside an fn type.
index 9ba709f7651064645aec7e79bad309e21ef1347f..ea7b2faf2734286da0bc984f355b3668131e31b0 100644 (file)
 
 // #[warn(deprecated_mode)];
 
-
 use middle::ty;
-
-use middle::typeck::isr_alist;
-use util::common::indenter;
-use util::ppaux::region_to_str;
+use middle::ty_fold;
+use middle::ty_fold::TypeFolder;
+use std::hashmap::HashMap;
+use util::ppaux::Repr;
 use util::ppaux;
 
-use extra::list::Cons;
-
 // Helper functions related to manipulating region types.
 
 pub fn replace_bound_regions_in_fn_sig(
     tcx: ty::ctxt,
-    isr: isr_alist,
     opt_self_ty: Option<ty::t>,
     fn_sig: &ty::FnSig,
     mapf: &fn(ty::bound_region) -> ty::Region)
-    -> (isr_alist, Option<ty::t>, ty::FnSig)
+    -> (HashMap<ty::bound_region,ty::Region>, Option<ty::t>, ty::FnSig)
 {
-    let mut all_tys = ty::tys_in_fn_sig(fn_sig);
-
-    for &t in opt_self_ty.iter() { all_tys.push(t) }
-
-    debug!("replace_bound_regions_in_fn_sig(self_ty={:?}, fn_sig={}, \
-            all_tys={:?})",
-           opt_self_ty.map(|t| ppaux::ty_to_str(tcx, t)),
-           ppaux::fn_sig_to_str(tcx, fn_sig),
-           all_tys.map(|t| ppaux::ty_to_str(tcx, *t)));
-    let _i = indenter();
-
-    let isr = do create_bound_region_mapping(tcx, isr, all_tys) |br| {
-        debug!("br={:?}", br);
-        mapf(br)
-    };
-    let new_fn_sig = ty::fold_sig(fn_sig, |t| {
-        replace_bound_regions(tcx, isr, t)
-    });
-    let new_self_ty = opt_self_ty.map(|t| replace_bound_regions(tcx, isr, t));
-
-    debug!("result of replace_bound_regions_in_fn_sig: \
-            new_self_ty={:?}, \
-            fn_sig={}",
-           new_self_ty.map(|t| ppaux::ty_to_str(tcx, t)),
-           ppaux::fn_sig_to_str(tcx, &new_fn_sig));
-
-    return (isr, new_self_ty, new_fn_sig);
-
-    // Takes `isr`, a (possibly empty) mapping from in-scope region
-    // names ("isr"s) to their corresponding regions; `tys`, a list of
-    // types, and `to_r`, a closure that takes a bound_region and
-    // returns a region.  Returns an updated version of `isr`,
-    // extended with the in-scope region names from all of the bound
-    // regions appearing in the types in the `tys` list (if they're
-    // not in `isr` already), with each of those in-scope region names
-    // mapped to a region that's the result of applying `to_r` to
-    // itself.
-    fn create_bound_region_mapping(
-        tcx: ty::ctxt,
-        isr: isr_alist,
-        tys: ~[ty::t],
-        to_r: &fn(ty::bound_region) -> ty::Region) -> isr_alist {
-
-        // Takes `isr` (described above), `to_r` (described above),
-        // and `r`, a region.  If `r` is anything other than a bound
-        // region, or if it's a bound region that already appears in
-        // `isr`, then we return `isr` unchanged.  If `r` is a bound
-        // region that doesn't already appear in `isr`, we return an
-        // updated isr_alist that now contains a mapping from `r` to
-        // the result of calling `to_r` on it.
-        fn append_isr(isr: isr_alist,
-                      to_r: &fn(ty::bound_region) -> ty::Region,
-                      r: ty::Region) -> isr_alist {
-            match r {
-              ty::re_empty | ty::re_free(*) | ty::re_static | ty::re_scope(_) |
-              ty::re_infer(_) => {
-                isr
-              }
-              ty::re_bound(br) => {
-                match isr.find(br) {
-                  Some(_) => isr,
-                  None => @Cons((br, to_r(br)), isr)
-                }
-              }
-            }
-        }
-
-        // For each type `ty` in `tys`...
-        do tys.iter().fold(isr) |isr, ty| {
-            let mut isr = isr;
-
-            // Using fold_regions is inefficient, because it
-            // constructs new types, but it avoids code duplication in
-            // terms of locating all the regions within the various
-            // kinds of types.  This had already caused me several
-            // bugs so I decided to switch over.
-            do ty::fold_regions(tcx, *ty) |r, in_fn| {
-                if !in_fn { isr = append_isr(isr, |br| to_r(br), r); }
-                r
-            };
-
-            isr
-        }
-    }
-
-    // Takes `isr`, a mapping from in-scope region names ("isr"s) to
-    // their corresponding regions; and `ty`, a type.  Returns an
-    // updated version of `ty`, in which bound regions in `ty` have
-    // been replaced with the corresponding bindings in `isr`.
-    fn replace_bound_regions(
-        tcx: ty::ctxt,
-        isr: isr_alist,
-        ty: ty::t) -> ty::t {
-
-        do ty::fold_regions(tcx, ty) |r, in_fn| {
-            let r1 = match r {
-              // As long as we are not within a fn() type, `&T` is
-              // mapped to the free region anon_r.  But within a fn
-              // type, it remains bound.
-              ty::re_bound(ty::br_anon(_)) if in_fn => r,
-
-              ty::re_bound(br) => {
-                match isr.find(br) {
-                  // In most cases, all named, bound regions will be
-                  // mapped to some free region.
-                  Some(fr) => fr,
-
-                  // But in the case of a fn() type, there may be
-                  // named regions within that remain bound:
-                  None if in_fn => r,
-                  None => {
-                    tcx.sess.bug(
-                        format!("Bound region not found in \
-                              in_scope_regions list: {}",
-                             region_to_str(tcx, "", false, r)));
-                  }
+    debug!("replace_bound_regions_in_fn_sig(self_ty={}, fn_sig={})",
+            opt_self_ty.repr(tcx),
+            fn_sig.repr(tcx));
+
+    let mut map = HashMap::new();
+    let (fn_sig, opt_self_ty) = {
+        let mut f = ty_fold::RegionFolder::regions(tcx, |r| {
+                debug!("region r={}", r.to_str());
+                match r {
+                ty::re_fn_bound(s, br) if s == fn_sig.binder_id => {
+                    *map.find_or_insert_with(br, |_| mapf(br))
                 }
-              }
-
-              // Free regions like these just stay the same:
-              ty::re_empty |
-              ty::re_static |
-              ty::re_scope(_) |
-              ty::re_free(*) |
-              ty::re_infer(_) => r
-            };
-            r1
-        }
-    }
+                _ => r
+            }});
+        (ty_fold::super_fold_sig(&mut f, fn_sig),
+         ty_fold::fold_opt_ty(&mut f, opt_self_ty))
+    };
+    debug!("resulting map: {}", map.to_str());
+    (map, opt_self_ty, fn_sig)
 }
 
 pub fn relate_nested_regions(
@@ -168,7 +54,6 @@ pub fn relate_nested_regions(
     relate_op: &fn(ty::Region, ty::Region))
 {
     /*!
-     *
      * This rather specialized function walks each region `r` that appear
      * in `ty` and invokes `relate_op(r_encl, r)` for each one.  `r_encl`
      * here is the region of any enclosing `&'r T` pointer.  If there is
@@ -194,41 +79,66 @@ pub fn relate_nested_regions(
      * Hence, in the second example above, `'r2` must be a subregion of `'r3`.
      */
 
-    let mut the_stack = ~[];
-    for &r in opt_region.iter() { the_stack.push(r); }
-    walk_ty(tcx, &mut the_stack, ty, relate_op);
+    let mut rr = RegionRelator { tcx: tcx,
+                                 stack: ~[],
+                                 relate_op: relate_op };
+    match opt_region {
+        Some(o_r) => { rr.stack.push(o_r); }
+        None => {}
+    }
+    rr.fold_ty(ty);
 
-    fn walk_ty(tcx: ty::ctxt,
-               the_stack: &mut ~[ty::Region],
-               ty: ty::t,
-               relate_op: &fn(ty::Region, ty::Region))
-    {
-        match ty::get(ty).sty {
-            ty::ty_rptr(r, ref mt) |
-            ty::ty_evec(ref mt, ty::vstore_slice(r)) => {
-                relate(*the_stack, r, |x,y| relate_op(x,y));
-                the_stack.push(r);
-                walk_ty(tcx, the_stack, mt.ty, |x,y| relate_op(x,y));
-                the_stack.pop();
-            }
-            _ => {
-                ty::fold_regions_and_ty(
-                    tcx,
-                    ty,
-                    |r| { relate(     *the_stack, r, |x,y| relate_op(x,y)); r },
-                    |t| { walk_ty(tcx, the_stack, t, |x,y| relate_op(x,y)); t },
-                    |t| { walk_ty(tcx, the_stack, t, |x,y| relate_op(x,y)); t });
+    struct RegionRelator<'self> {
+        tcx: ty::ctxt,
+        stack: ~[ty::Region],
+        relate_op: &'self fn(ty::Region, ty::Region),
+    }
+
+    // FIXME we should define more precisely when a
+    //       region is considered "nested" and take variance into account.
+    //
+    //       I can't decide whether skipping closure parameter types and
+    //       so on is necessary or not. What is the difference, after all,
+    //       between `&'a |&'b T|` and `&'a Fn<&'b T>`? And yet in the
+    //       latter case I'm inclined to think we should probably track
+    //       the relationship (but then again maybe we should just skip
+    //       all such cases until it "proves necessary")
+
+    impl<'self> TypeFolder for RegionRelator<'self> {
+        fn tcx(&self) -> ty::ctxt {
+            self.tcx
+        }
+
+        fn fold_ty(&mut self, ty: ty::t) -> ty::t {
+            match ty::get(ty).sty {
+                ty::ty_rptr(r, ref mt) |
+                ty::ty_evec(ref mt, ty::vstore_slice(r)) => {
+                    self.relate(r);
+                    self.stack.push(r);
+                    ty_fold::super_fold_ty(self, mt.ty);
+                    self.stack.pop();
+                }
+
+                _ => {
+                    ty_fold::super_fold_ty(self, ty);
+                }
             }
+
+            ty
+        }
+
+        fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+            self.relate(r);
+            r
         }
     }
 
-    fn relate(the_stack: &[ty::Region],
-              r_sub: ty::Region,
-              relate_op: &fn(ty::Region, ty::Region))
-    {
-        for &r in the_stack.iter() {
-            if !r.is_bound() && !r_sub.is_bound() {
-                relate_op(r, r_sub);
+    impl<'self> RegionRelator<'self> {
+        fn relate(&mut self, r_sub: ty::Region) {
+            for &r in self.stack.iter() {
+                if !r.is_bound() && !r_sub.is_bound() {
+                    (self.relate_op)(r, r_sub);
+                }
             }
         }
     }
index 3c4ff35b768db42b24e60fd8491b29e7a2be7a79..ae76c9ed6dd49d6ac96ae329e6c7b2d1b309570b 100644 (file)
@@ -11,6 +11,7 @@
 
 use middle::ty::param_ty;
 use middle::ty;
+use middle::ty_fold::TypeFolder;
 use middle::typeck::check::{FnCtxt, impl_self_ty};
 use middle::typeck::check::{structurally_resolved_type};
 use middle::typeck::infer::fixup_err_to_str;
@@ -68,13 +69,13 @@ pub struct LocationInfo {
 
 /// A vtable context includes an inference context, a crate context, and a
 /// callback function to call in case of type error.
-pub struct VtableContext {
-    ccx: @mut CrateCtxt,
-    infcx: @mut infer::InferCtxt
+pub struct VtableContext<'self> {
+    infcx: @mut infer::InferCtxt,
+    param_env: &'self ty::ParameterEnvironment,
 }
 
-impl VtableContext {
-    pub fn tcx(&self) -> ty::ctxt { self.ccx.tcx }
+impl<'self> VtableContext<'self> {
+    pub fn tcx(&self) -> ty::ctxt { self.infcx.tcx }
 }
 
 fn has_trait_bounds(type_param_defs: &[ty::TypeParameterDef]) -> bool {
@@ -95,7 +96,6 @@ fn lookup_vtables(vcx: &VtableContext,
            substs.repr(vcx.tcx()));
     let _i = indenter();
 
-
     // We do this backwards for reasons discussed above.
     assert_eq!(substs.tps.len(), type_param_defs.len());
     let mut result =
@@ -233,8 +233,6 @@ fn lookup_vtable(vcx: &VtableContext,
            vcx.infcx.trait_ref_to_str(trait_ref));
     let _i = indenter();
 
-    let tcx = vcx.tcx();
-
     let ty = match fixup_ty(vcx, location_info, ty, is_early) {
         Some(ty) => ty,
         None => {
@@ -250,18 +248,21 @@ fn lookup_vtable(vcx: &VtableContext,
     // If the type is self or a param, we look at the trait/supertrait
     // bounds to see if they include the trait we are looking for.
     let vtable_opt = match ty::get(ty).sty {
-        ty::ty_param(param_ty {idx: n, def_id: did}) => {
-            let type_param_def = tcx.ty_param_defs.get(&did.node);
-            lookup_vtable_from_bounds(vcx, location_info,
-                                      type_param_def.bounds.trait_bounds,
+        ty::ty_param(param_ty {idx: n, _}) => {
+            let type_param_bounds: &[@ty::TraitRef] =
+                vcx.param_env.type_param_bounds[n].trait_bounds;
+            lookup_vtable_from_bounds(vcx,
+                                      location_info,
+                                      type_param_bounds,
                                       param_numbered(n),
                                       trait_ref)
         }
 
-        ty::ty_self(trait_id) => {
-            let self_trait_ref = ty::lookup_trait_def(tcx, trait_id).trait_ref;
-            lookup_vtable_from_bounds(vcx, location_info,
-                                      &[self_trait_ref],
+        ty::ty_self(_) => {
+            let self_param_bound = vcx.param_env.self_param_bound.unwrap();
+            lookup_vtable_from_bounds(vcx,
+                                      location_info,
+                                      [self_param_bound],
                                       param_self,
                                       trait_ref)
         }
@@ -285,7 +286,7 @@ fn lookup_vtable_from_bounds(vcx: &VtableContext,
                              bounds: &[@ty::TraitRef],
                              param: param_index,
                              trait_ref: @ty::TraitRef)
-    -> Option<vtable_origin> {
+                             -> Option<vtable_origin> {
     let tcx = vcx.tcx();
 
     let mut n_bound = 0;
@@ -317,8 +318,7 @@ fn search_for_vtable(vcx: &VtableContext,
                      ty: ty::t,
                      trait_ref: @ty::TraitRef,
                      is_early: bool)
-    -> Option<vtable_origin>
-{
+                     -> Option<vtable_origin> {
     let tcx = vcx.tcx();
 
     let mut found = ~[];
@@ -494,7 +494,8 @@ fn fixup_substs(vcx: &VtableContext,
 fn fixup_ty(vcx: &VtableContext,
             location_info: &LocationInfo,
             ty: ty::t,
-            is_early: bool) -> Option<ty::t> {
+            is_early: bool)
+            -> Option<ty::t> {
     let tcx = vcx.tcx();
     match resolve_type(vcx.infcx, ty, resolve_and_force_all_but_regions) {
         Ok(new_type) => Some(new_type),
@@ -515,8 +516,7 @@ fn connect_trait_tps(vcx: &VtableContext,
                      location_info: &LocationInfo,
                      impl_substs: &ty::substs,
                      trait_ref: @ty::TraitRef,
-                     impl_did: ast::DefId)
-{
+                     impl_did: ast::DefId) {
     let tcx = vcx.tcx();
 
     let impl_trait_ref = match ty::impl_trait_ref(tcx, impl_did) {
@@ -571,7 +571,7 @@ pub fn early_resolve_expr(ex: @ast::Expr,
             if has_trait_bounds(*item_ty.generics.type_param_defs) {
                 debug!("early_resolve_expr: looking up vtables for type params {}",
                        item_ty.generics.type_param_defs.repr(fcx.tcx()));
-                let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
+                let vcx = fcx.vtable_context();
                 let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
                                            *item_ty.generics.type_param_defs,
                                            substs, is_early);
@@ -599,7 +599,7 @@ pub fn early_resolve_expr(ex: @ast::Expr,
                    ex.repr(fcx.tcx()));
             if has_trait_bounds(*type_param_defs) {
                 let substs = fcx.node_ty_substs(callee_id);
-                let vcx = VtableContext { ccx: fcx.ccx, infcx: fcx.infcx() };
+                let vcx = fcx.vtable_context();
                 let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
                                            *type_param_defs, &substs, is_early);
                 if !is_early {
@@ -642,10 +642,7 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
                       (&ty::ty_rptr(_, mt), ty::RegionTraitStore(*)) => {
                           let location_info =
                               &location_info_for_expr(ex);
-                          let vcx = VtableContext {
-                              ccx: fcx.ccx,
-                              infcx: fcx.infcx()
-                          };
+                          let vcx = fcx.vtable_context();
                           let target_trait_ref = @ty::TraitRef {
                               def_id: target_def_id,
                               substs: ty::substs {
@@ -726,48 +723,58 @@ fn resolve_expr(fcx: @mut FnCtxt,
     visit::walk_expr(&mut fcx, ex, ());
 }
 
-pub fn resolve_impl(ccx: @mut CrateCtxt, impl_item: @ast::item) {
-    let def_id = ast_util::local_def(impl_item.id);
-    match ty::impl_trait_ref(ccx.tcx, def_id) {
-        None => {},
-        Some(trait_ref) => {
-            let infcx = infer::new_infer_ctxt(ccx.tcx);
-            let vcx = VtableContext { ccx: ccx, infcx: infcx };
-            let loc_info = location_info_for_item(impl_item);
-
-            // First, check that the impl implements any trait bounds
-            // on the trait.
-            let trait_def = ty::lookup_trait_def(ccx.tcx, trait_ref.def_id);
-            let vtbls = lookup_vtables(&vcx,
-                                       &loc_info,
-                                       *trait_def.generics.type_param_defs,
-                                       &trait_ref.substs,
-                                       false);
-
-            // Now, locate the vtable for the impl itself. The real
-            // purpose of this is to check for supertrait impls,
-            // but that falls out of doing this.
-            let param_bounds = ty::ParamBounds {
-                builtin_bounds: ty::EmptyBuiltinBounds(),
-                trait_bounds: ~[trait_ref]
-            };
-            let t = ty::node_id_to_type(ccx.tcx, impl_item.id);
-            debug!("=== Doing a self lookup now.");
-            // Right now, we don't have any place to store this.
-            // We will need to make one so we can use this information
-            // for compiling default methods that refer to supertraits.
-            let self_vtable_res =
-                lookup_vtables_for_param(&vcx, &loc_info, None,
-                                         &param_bounds, t, false);
-
-
-            let res = impl_res {
-                trait_vtables: vtbls,
-                self_vtables: self_vtable_res
-            };
-            ccx.tcx.impl_vtables.insert(def_id, res);
-        }
-    }
+pub fn resolve_impl(ccx: @mut CrateCtxt,
+                    impl_item: @ast::item,
+                    impl_generics: &ty::Generics,
+                    impl_trait_ref: &ty::TraitRef) {
+    let param_env = ty::construct_parameter_environment(
+        ccx.tcx,
+        None,
+        *impl_generics.type_param_defs,
+        [],
+        impl_generics.region_param_defs,
+        impl_item.id);
+
+    let impl_trait_ref = @impl_trait_ref.subst(ccx.tcx, &param_env.free_substs);
+
+    let infcx = infer::new_infer_ctxt(ccx.tcx);
+    let vcx = VtableContext { infcx: infcx, param_env: &param_env };
+    let loc_info = location_info_for_item(impl_item);
+
+    // First, check that the impl implements any trait bounds
+    // on the trait.
+    let trait_def = ty::lookup_trait_def(ccx.tcx, impl_trait_ref.def_id);
+    let vtbls = lookup_vtables(&vcx,
+                               &loc_info,
+                               *trait_def.generics.type_param_defs,
+                               &impl_trait_ref.substs,
+                               false);
+
+    // Now, locate the vtable for the impl itself. The real
+    // purpose of this is to check for supertrait impls,
+    // but that falls out of doing this.
+    let param_bounds = ty::ParamBounds {
+        builtin_bounds: ty::EmptyBuiltinBounds(),
+        trait_bounds: ~[impl_trait_ref]
+    };
+    let t = ty::node_id_to_type(ccx.tcx, impl_item.id);
+    let t = t.subst(ccx.tcx, &param_env.free_substs);
+    debug!("=== Doing a self lookup now.");
+
+    // Right now, we don't have any place to store this.
+    // We will need to make one so we can use this information
+    // for compiling default methods that refer to supertraits.
+    let self_vtable_res =
+        lookup_vtables_for_param(&vcx, &loc_info, None,
+                                 &param_bounds, t, false);
+
+
+    let res = impl_res {
+        trait_vtables: vtbls,
+        self_vtables: self_vtable_res
+    };
+    let impl_def_id = ast_util::local_def(impl_item.id);
+    ccx.tcx.impl_vtables.insert(impl_def_id, res);
 }
 
 impl visit::Visitor<()> for @mut FnCtxt {
index 795074fa61904dbe7356ee5b12f083ebd827fd90..b959c80db38a81a6267668b439962abf83455598 100644 (file)
@@ -357,8 +357,8 @@ pub fn instantiate_default_methods(&self,
                     @vec::append(
                         (*impl_poly_type.generics.type_param_defs).clone(),
                         *new_method_ty.generics.type_param_defs),
-                region_param:
-                    impl_poly_type.generics.region_param
+                region_param_defs:
+                    impl_poly_type.generics.region_param_defs
             };
             let new_polytype = ty::ty_param_bounds_and_ty {
                 generics: new_generics,
@@ -482,20 +482,17 @@ pub fn polytypes_unify(&self,
     pub fn universally_quantify_polytype(&self,
                                          polytype: ty_param_bounds_and_ty)
                                          -> UniversalQuantificationResult {
-        let regions = match polytype.generics.region_param {
-            None => opt_vec::Empty,
-            Some(_) => {
-                opt_vec::with(
-                    self.inference_context.next_region_var(
-                        infer::BoundRegionInCoherence))
-            }
-        };
+        let region_parameter_count = polytype.generics.region_param_defs.len();
+        let region_parameters =
+            self.inference_context.next_region_vars(
+                infer::BoundRegionInCoherence,
+                region_parameter_count);
 
         let bounds_count = polytype.generics.type_param_defs.len();
         let type_parameters = self.inference_context.next_ty_vars(bounds_count);
 
         let substitutions = substs {
-            regions: ty::NonerasedRegions(regions),
+            regions: ty::NonerasedRegions(opt_vec::from(region_parameters)),
             self_ty: None,
             tps: type_parameters
         };
index 353639051097a966b80ba764b6a32ee8fc3c28eb..c1908e69f1e09681f05dc903d958b28cd782d4fb 100644 (file)
 use middle::typeck::astconv::{AstConv, ty_of_arg};
 use middle::typeck::astconv::{ast_ty_to_ty};
 use middle::typeck::astconv;
-use middle::typeck::infer;
 use middle::typeck::rscope::*;
-use middle::typeck::rscope;
 use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
-use util::common::pluralize;
 use util::ppaux;
-use util::ppaux::UserString;
 
-use std::result;
 use std::vec;
 use syntax::abi::AbiSet;
 use syntax::ast::{RegionTyParamBound, TraitTyParamBound};
 use syntax::ast_util::{local_def, split_trait_methods};
 use syntax::codemap::Span;
 use syntax::codemap;
-use syntax::print::pprust::{path_to_str, explicit_self_to_str};
+use syntax::print::pprust::{path_to_str};
 use syntax::visit;
 use syntax::opt_vec::OptVec;
-use syntax::opt_vec;
 use syntax::parse::token::special_idents;
 
 struct CollectItemTypesVisitor {
@@ -97,19 +91,11 @@ fn collect_intrinsic_type(ccx: &CrateCtxt,
 }
 
 pub trait ToTy {
-    fn to_ty<RS:RegionScope + Clone + 'static>(
-             &self,
-             rs: &RS,
-             ast_ty: &ast::Ty)
-             -> ty::t;
+    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t;
 }
 
 impl ToTy for CrateCtxt {
-    fn to_ty<RS:RegionScope + Clone + 'static>(
-             &self,
-             rs: &RS,
-             ast_ty: &ast::Ty)
-             -> ty::t {
+    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> ty::t {
         ast_ty_to_ty(self, rs, ast_ty)
     }
 }
@@ -149,59 +135,45 @@ fn ty_infer(&self, span: Span) -> ty::t {
 pub fn get_enum_variant_types(ccx: &CrateCtxt,
                               enum_ty: ty::t,
                               variants: &[ast::variant],
-                              generics: &ast::Generics,
-                              rp: Option<ty::region_variance>) {
+                              generics: &ast::Generics) {
     let tcx = ccx.tcx;
 
     // Create a set of parameter types shared among all the variants.
     for variant in variants.iter() {
-        let region_parameterization =
-            RegionParameterization::from_variance_and_generics(rp, generics);
-
         // Nullary enum constructors get turned into constants; n-ary enum
         // constructors get turned into functions.
-        let result_ty;
-        match variant.node.kind {
+        let scope = variant.node.id;
+        let result_ty = match variant.node.kind {
             ast::tuple_variant_kind(ref args) if args.len() > 0 => {
-                let rs = TypeRscope(region_parameterization);
+                let rs = ExplicitRscope;
                 let input_tys = args.map(|va| ccx.to_ty(&rs, &va.ty));
-                result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
+                ty::mk_ctor_fn(tcx, scope, input_tys, enum_ty)
             }
 
             ast::tuple_variant_kind(_) => {
-                result_ty = Some(enum_ty);
+                enum_ty
             }
 
             ast::struct_variant_kind(struct_def) => {
                 let tpt = ty_param_bounds_and_ty {
-                    generics: ty_generics(ccx, rp, generics, 0),
+                    generics: ty_generics(ccx, generics, 0),
                     ty: enum_ty
                 };
 
-                convert_struct(ccx,
-                               rp,
-                               struct_def,
-                               generics,
-                               tpt,
-                               variant.node.id);
+                convert_struct(ccx, struct_def, tpt, variant.node.id);
 
                 let input_tys = struct_def.fields.map(
                     |f| ty::node_id_to_type(ccx.tcx, f.node.id));
-                result_ty = Some(ty::mk_ctor_fn(tcx, input_tys, enum_ty));
+                ty::mk_ctor_fn(tcx, scope, input_tys, enum_ty)
             }
         };
 
-        match result_ty {
-            None => {}
-            Some(result_ty) => {
-                let tpt = ty_param_bounds_and_ty {
-                    generics: ty_generics(ccx, rp, generics, 0),
-                    ty: result_ty
-                };
-                tcx.tcache.insert(local_def(variant.node.id), tpt);
-                write_ty_to_tcx(tcx, variant.node.id, result_ty);
-            }
-        }
+        let tpt = ty_param_bounds_and_ty {
+            generics: ty_generics(ccx, generics, 0),
+            ty: result_ty
+        };
+        tcx.tcache.insert(local_def(variant.node.id), tpt);
+        write_ty_to_tcx(tcx, variant.node.id, result_ty);
     }
 }
 
@@ -209,13 +181,13 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                             trait_id: ast::NodeId)
 {
     let tcx = ccx.tcx;
-    let region_paramd = tcx.region_paramd_items.find(&trait_id).map(|x| *x);
     match tcx.items.get_copy(&trait_id) {
         ast_map::node_item(@ast::item {
             node: ast::item_trait(ref generics, _, ref ms),
             _
         }, _) => {
-            let trait_ty_generics = ty_generics(ccx, region_paramd, generics, 0);
+            let trait_ty_generics =
+                ty_generics(ccx, generics, 0);
 
             // For each method, construct a suitable ty::Method and
             // store it into the `tcx.methods` table:
@@ -223,14 +195,14 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                 let ty_method = @match m {
                     &ast::required(ref m) => {
                         ty_method_of_trait_method(
-                            ccx, trait_id, region_paramd, generics,
+                            ccx, trait_id, &trait_ty_generics,
                             &m.id, &m.ident, &m.explicit_self,
                             &m.generics, &m.purity, &m.decl)
                     }
 
                     &ast::provided(ref m) => {
                         ty_method_of_trait_method(
-                            ccx, trait_id, region_paramd, generics,
+                            ccx, trait_id, &trait_ty_generics,
                             &m.id, &m.ident, &m.explicit_self,
                             &m.generics, &m.purity, &m.decl)
                     }
@@ -264,13 +236,13 @@ fn make_static_method_ty(ccx: &CrateCtxt,
                              trait_ty_generics: &ty::Generics) {
         // If declaration is
         //
-        //     trait<A,B,C> {
-        //        fn foo<D,E,F>(...) -> Self;
+        //     trait<'a,'b,'c,A,B,C> {
+        //        fn foo<'d,'e,'f,D,E,F>(...) -> Self;
         //     }
         //
         // and we will create a function like
         //
-        //     fn foo<A',B',C',D',E',F',G'>(...) -> D' {}
+        //     fn foo<'a,'b,'c,'d,'e,'f,A',B',C',D',E',F',G'>(...) -> D' {}
         //
         // Note that `Self` is replaced with an explicit type
         // parameter D' that is sandwiched in between the trait params
@@ -307,12 +279,19 @@ fn make_static_method_ty(ccx: &CrateCtxt,
                          m.generics.type_param_defs[i].def_id)
         };
 
+        // Convert the regions 'a, 'b, 'c defined on the trait into
+        // bound regions on the fn.
+        let rps_from_trait = trait_ty_generics.region_param_defs.iter().map(|d| {
+            ty::re_fn_bound(m.fty.sig.binder_id,
+                            ty::br_named(d.def_id, d.ident))
+        }).collect();
+
         // build up the substitution from
         //     A,B,C => A',B',C'
         //     Self => D'
         //     D,E,F => E',F',G'
         let substs = substs {
-            regions: ty::NonerasedRegions(opt_vec::Empty),
+            regions: ty::NonerasedRegions(rps_from_trait),
             self_ty: Some(self_param),
             tps: non_shifted_trait_tps + shifted_method_tps
         };
@@ -357,7 +336,7 @@ fn make_static_method_ty(ccx: &CrateCtxt,
                           ty_param_bounds_and_ty {
                               generics: ty::Generics {
                                   type_param_defs: @new_type_param_defs,
-                                  region_param: trait_ty_generics.region_param
+                                  region_param_defs: @[], // fn items
                               },
                               ty: ty
                           });
@@ -365,8 +344,7 @@ fn make_static_method_ty(ccx: &CrateCtxt,
 
     fn ty_method_of_trait_method(this: &CrateCtxt,
                                  trait_id: ast::NodeId,
-                                 trait_rp: Option<ty::region_variance>,
-                                 trait_generics: &ast::Generics,
+                                 trait_generics: &ty::Generics,
                                  m_id: &ast::NodeId,
                                  m_ident: &ast::Ident,
                                  m_explicit_self: &ast::explicit_self,
@@ -375,14 +353,14 @@ fn ty_method_of_trait_method(this: &CrateCtxt,
                                  m_decl: &ast::fn_decl) -> ty::Method
     {
         let trait_self_ty = ty::mk_self(this.tcx, local_def(trait_id));
-        let rscope = MethodRscope::new(m_explicit_self.node, trait_rp, trait_generics);
         let (transformed_self_ty, fty) =
-            astconv::ty_of_method(this, &rscope, *m_purity, &m_generics.lifetimes,
+            astconv::ty_of_method(this, *m_id, *m_purity,
                                   trait_self_ty, *m_explicit_self, m_decl);
-        let num_trait_type_params = trait_generics.ty_params.len();
+        let num_trait_type_params = trait_generics.type_param_defs.len();
         ty::Method::new(
             *m_ident,
-            ty_generics(this, None, m_generics, num_trait_type_params),
+            // FIXME -- what about lifetime parameters here?
+            ty_generics(this, m_generics, num_trait_type_params),
             transformed_self_ty,
             fty,
             m_explicit_self.node,
@@ -398,9 +376,8 @@ fn ty_method_of_trait_method(this: &CrateCtxt,
 pub fn ensure_supertraits(ccx: &CrateCtxt,
                           id: ast::NodeId,
                           sp: codemap::Span,
-                          rp: Option<ty::region_variance>,
-                          ast_trait_refs: &[ast::trait_ref],
-                          generics: &ast::Generics) -> ty::BuiltinBounds
+                          ast_trait_refs: &[ast::trait_ref])
+                          -> ty::BuiltinBounds
 {
     let tcx = ccx.tcx;
 
@@ -416,8 +393,7 @@ pub fn ensure_supertraits(ccx: &CrateCtxt,
         // FIXME(#8559): Need to instantiate the trait_ref whether or not it's a
         // builtin trait, so that the trait's node id appears in the tcx trait_ref
         // map. This is only needed for metadata; see the similar fixme in encoder.rs.
-        let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, rp,
-                                              generics, self_ty);
+        let trait_ref = instantiate_trait_ref(ccx, ast_trait_ref, self_ty);
         if !ty::try_add_builtin_trait(ccx.tcx, trait_def_id, &mut bounds) {
 
             // FIXME(#5527) Could have same trait multiple times
@@ -720,91 +696,68 @@ pub fn check_methods_against_trait(ccx: &CrateCtxt,
 } // fn
 
 pub fn convert_field(ccx: &CrateCtxt,
-                     rp: Option<ty::region_variance>,
-                     type_param_defs: @~[ty::TypeParameterDef],
-                     v: &ast::struct_field,
-                     generics: &ast::Generics) {
-    let region_parameterization =
-        RegionParameterization::from_variance_and_generics(rp, generics);
-    let tt = ccx.to_ty(&TypeRscope(region_parameterization), &v.node.ty);
+                     struct_generics: &ty::Generics,
+                     v: &ast::struct_field) {
+    let tt = ccx.to_ty(&ExplicitRscope, &v.node.ty);
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
     /* add the field to the tcache */
     ccx.tcx.tcache.insert(local_def(v.node.id),
                           ty::ty_param_bounds_and_ty {
-                              generics: ty::Generics {
-                                  type_param_defs: type_param_defs,
-                                  region_param: rp
-                              },
+                              generics: struct_generics.clone(),
                               ty: tt
                           });
 }
 
-pub struct ConvertedMethod {
-    mty: @ty::Method,
-    id: ast::NodeId,
-    span: Span,
-    body_id: ast::NodeId
-}
-
-pub fn convert_methods(ccx: &CrateCtxt,
-                       container: MethodContainer,
-                       ms: &[@ast::method],
-                       untransformed_rcvr_ty: ty::t,
-                       rcvr_ty_generics: &ty::Generics,
-                       rcvr_ast_generics: &ast::Generics,
-                       rcvr_visibility: ast::visibility)
-                    -> ~[ConvertedMethod]
+fn convert_methods(ccx: &CrateCtxt,
+                   container: MethodContainer,
+                   ms: &[@ast::method],
+                   untransformed_rcvr_ty: ty::t,
+                   rcvr_ty_generics: &ty::Generics,
+                   rcvr_ast_generics: &ast::Generics,
+                   rcvr_visibility: ast::visibility)
 {
     let tcx = ccx.tcx;
-    return ms.iter().map(|m| {
+    for m in ms.iter() {
         let num_rcvr_ty_params = rcvr_ty_generics.type_param_defs.len();
-        let m_ty_generics =
-            ty_generics(ccx, rcvr_ty_generics.region_param, &m.generics,
-                        num_rcvr_ty_params);
+        let m_ty_generics = ty_generics(ccx, &m.generics, num_rcvr_ty_params);
         let mty = @ty_of_method(ccx,
                                 container,
                                 *m,
-                                rcvr_ty_generics.region_param,
                                 untransformed_rcvr_ty,
                                 rcvr_ast_generics,
-                                rcvr_visibility,
-                                &m.generics);
+                                rcvr_visibility);
         let fty = ty::mk_bare_fn(tcx, mty.fty.clone());
+        debug!("method {} (id {}) has type {}",
+                m.ident.repr(ccx.tcx),
+                m.id,
+                fty.repr(ccx.tcx));
         tcx.tcache.insert(
             local_def(m.id),
 
             // n.b.: the type of a method is parameterized by both
-            // the tps on the receiver and those on the method itself
+            // the parameters on the receiver and those on the method itself
             ty_param_bounds_and_ty {
                 generics: ty::Generics {
                     type_param_defs: @vec::append(
                         (*rcvr_ty_generics.type_param_defs).clone(),
                         *m_ty_generics.type_param_defs),
-                    region_param: rcvr_ty_generics.region_param
+                    region_param_defs: rcvr_ty_generics.region_param_defs,
                 },
                 ty: fty
             });
         write_ty_to_tcx(tcx, m.id, fty);
         tcx.methods.insert(mty.def_id, mty);
-        ConvertedMethod {mty: mty, id: m.id,
-                         span: m.span, body_id: m.body.id}
-    }).collect();
+    }
 
     fn ty_of_method(ccx: &CrateCtxt,
                     container: MethodContainer,
                     m: &ast::method,
-                    rp: Option<ty::region_variance>,
                     untransformed_rcvr_ty: ty::t,
                     rcvr_generics: &ast::Generics,
-                    rcvr_visibility: ast::visibility,
-                    method_generics: &ast::Generics) -> ty::Method
+                    rcvr_visibility: ast::visibility) -> ty::Method
     {
-        let rscope = MethodRscope::new(m.explicit_self.node,
-                                       rp,
-                                       rcvr_generics);
         let (transformed_self_ty, fty) =
-            astconv::ty_of_method(ccx, &rscope, m.purity,
-                                  &method_generics.lifetimes,
+            astconv::ty_of_method(ccx, m.id, m.purity,
                                   untransformed_rcvr_ty,
                                   m.explicit_self, &m.decl);
 
@@ -817,7 +770,8 @@ fn ty_of_method(ccx: &CrateCtxt,
         let num_rcvr_type_params = rcvr_generics.ty_params.len();
         ty::Method::new(
             m.ident,
-            ty_generics(ccx, None, &m.generics, num_rcvr_type_params),
+            // FIXME region param
+            ty_generics(ccx, &m.generics, num_rcvr_type_params),
             transformed_self_ty,
             fty,
             m.explicit_self.node,
@@ -845,27 +799,22 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
 
 pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
     let tcx = ccx.tcx;
-    let rp = tcx.region_paramd_items.find(&it.id).map(|x| *x);
-    debug!("convert: item {} with id {} rp {:?}",
-           tcx.sess.str_of(it.ident), it.id, rp);
+    debug!("convert: item {} with id {}", tcx.sess.str_of(it.ident), it.id);
     match it.node {
-      // These don't define types.
-      ast::item_foreign_mod(_) | ast::item_mod(_) => {}
-      ast::item_enum(ref enum_definition, ref generics) => {
-        ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
-        let tpt = ty_of_item(ccx, it);
-        write_ty_to_tcx(tcx, it.id, tpt.ty);
-        get_enum_variant_types(ccx,
-                               tpt.ty,
-                               enum_definition.variants,
-                               generics,
-                               rp);
-      }
+        // These don't define types.
+        ast::item_foreign_mod(_) | ast::item_mod(_) => {}
+        ast::item_enum(ref enum_definition, ref generics) => {
+            ensure_no_ty_param_bounds(ccx, it.span, generics, "enumeration");
+            let tpt = ty_of_item(ccx, it);
+            write_ty_to_tcx(tcx, it.id, tpt.ty);
+            get_enum_variant_types(ccx,
+                                   tpt.ty,
+                                   enum_definition.variants,
+                                   generics);
+        }
       ast::item_impl(ref generics, ref opt_trait_ref, ref selfty, ref ms) => {
-        let i_ty_generics = ty_generics(ccx, rp, generics, 0);
-        let region_parameterization =
-            RegionParameterization::from_variance_and_generics(rp, generics);
-        let selfty = ccx.to_ty(&TypeRscope(region_parameterization), selfty);
+        let i_ty_generics = ty_generics(ccx, generics, 0);
+        let selfty = ccx.to_ty(&ExplicitRscope, selfty);
         write_ty_to_tcx(tcx, it.id, selfty);
         tcx.tcache.insert(local_def(it.id),
                           ty_param_bounds_and_ty {
@@ -883,17 +832,19 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
             it.vis
         };
 
-        let cms = convert_methods(ccx,
-                                  ImplContainer(local_def(it.id)),
-                                  *ms,
-                                  selfty,
-                                  &i_ty_generics,
-                                  generics,
-                                  parent_visibility);
-        for t in opt_trait_ref.iter() {
+        convert_methods(ccx,
+                        ImplContainer(local_def(it.id)),
+                        *ms,
+                        selfty,
+                        &i_ty_generics,
+                        generics,
+                        parent_visibility);
+
+        for trait_ref in opt_trait_ref.iter() {
+            let trait_ref = instantiate_trait_ref(ccx, trait_ref, selfty);
+
             // Prevent the builtin kind traits from being manually implemented.
-            let trait_def_id = ty::trait_ref_to_def_id(tcx, t);
-            if tcx.lang_items.to_builtin_kind(trait_def_id).is_some() {
+            if tcx.lang_items.to_builtin_kind(trait_ref.def_id).is_some() {
                 tcx.sess.span_err(it.span,
                     "cannot provide an explicit implementation \
                      for a builtin kind");
@@ -903,21 +854,19 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
         }
       }
       ast::item_trait(ref generics, _, ref trait_methods) => {
-          let _trait_def = trait_def_of_item(ccx, it);
+          let trait_def = trait_def_of_item(ccx, it);
 
           // Run convert_methods on the provided methods.
           let (_, provided_methods) =
               split_trait_methods(*trait_methods);
           let untransformed_rcvr_ty = ty::mk_self(tcx, local_def(it.id));
-          let (ty_generics, _) = mk_item_substs(ccx, generics, rp,
-                                                Some(untransformed_rcvr_ty));
-          let _ = convert_methods(ccx,
-                                  TraitContainer(local_def(it.id)),
-                                  provided_methods,
-                                  untransformed_rcvr_ty,
-                                  &ty_generics,
-                                  generics,
-                                  it.vis);
+          convert_methods(ccx,
+                          TraitContainer(local_def(it.id)),
+                          provided_methods,
+                          untransformed_rcvr_ty,
+                          &trait_def.generics,
+                          generics,
+                          it.vis);
 
           // We need to do this *after* converting methods, since
           // convert_methods produces a tcache entry that is wrong for
@@ -932,7 +881,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
         write_ty_to_tcx(tcx, it.id, tpt.ty);
         tcx.tcache.insert(local_def(it.id), tpt);
 
-        convert_struct(ccx, rp, struct_def, generics, tpt, it.id);
+        convert_struct(ccx, struct_def, tpt, it.id);
       }
       ast::item_ty(_, ref generics) => {
         ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
@@ -950,18 +899,16 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::item) {
 }
 
 pub fn convert_struct(ccx: &CrateCtxt,
-                      rp: Option<ty::region_variance>,
                       struct_def: &ast::struct_def,
-                      generics: &ast::Generics,
                       tpt: ty::ty_param_bounds_and_ty,
                       id: ast::NodeId) {
     let tcx = ccx.tcx;
 
     // Write the type of each of the members
     for f in struct_def.fields.iter() {
-       convert_field(ccx, rp, tpt.generics.type_param_defs, *f, generics);
+       convert_field(ccx, &tpt.generics, *f);
     }
-    let (_, substs) = mk_item_substs(ccx, generics, rp, None);
+    let substs = mk_item_substs(ccx, &tpt.generics, None);
     let selfty = ty::mk_struct(tcx, local_def(id), substs);
 
     // If this struct is enum-like or tuple-like, create the type of its
@@ -979,7 +926,7 @@ pub fn convert_struct(ccx: &CrateCtxt,
                     struct_def.fields.map(
                         |field| ccx.tcx.tcache.get(
                             &local_def(field.node.id)).ty);
-                let ctor_fn_ty = ty::mk_ctor_fn(tcx, inputs, selfty);
+                let ctor_fn_ty = ty::mk_ctor_fn(tcx, ctor_id, inputs, selfty);
                 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
                 tcx.tcache.insert(local_def(ctor_id), ty_param_bounds_and_ty {
                     generics: tpt.generics,
@@ -1014,8 +961,6 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: &ast::foreign_item) {
 
 pub fn instantiate_trait_ref(ccx: &CrateCtxt,
                              ast_trait_ref: &ast::trait_ref,
-                             rp: Option<ty::region_variance>,
-                             generics: &ast::Generics,
                              self_ty: ty::t) -> @ty::TraitRef
 {
     /*!
@@ -1024,9 +969,7 @@ pub fn instantiate_trait_ref(ccx: &CrateCtxt,
      * trait. Fails if the type is a type other than an trait type.
      */
 
-    let rp = RegionParameterization::from_variance_and_generics(rp, generics);
-
-    let rscope = TypeRscope(rp);
+    let rscope = ExplicitRscope; // FIXME
 
     match lookup_def_tcx(ccx.tcx, ast_trait_ref.path.span, ast_trait_ref.ref_id) {
         ast::DefTrait(trait_did) => {
@@ -1066,14 +1009,12 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::item) -> @ty::TraitDef {
       Some(&def) => return def,
       _ => {}
     }
-    let rp = tcx.region_paramd_items.find(&it.id).map(|x| *x);
     match it.node {
         ast::item_trait(ref generics, ref supertraits, _) => {
             let self_ty = ty::mk_self(tcx, def_id);
-            let (ty_generics, substs) = mk_item_substs(ccx, generics, rp,
-                                                       Some(self_ty));
-            let bounds = ensure_supertraits(ccx, it.id, it.span, rp,
-                                            *supertraits, generics);
+            let ty_generics = ty_generics(ccx, generics, 0);
+            let substs = mk_item_substs(ccx, &ty_generics, Some(self_ty));
+            let bounds = ensure_supertraits(ccx, it.id, it.span, *supertraits);
             let trait_ref = @ty::TraitRef {def_id: def_id,
                                            substs: substs};
             let trait_def = @ty::TraitDef {generics: ty_generics,
@@ -1091,93 +1032,89 @@ pub fn trait_def_of_item(ccx: &CrateCtxt, it: &ast::item) -> @ty::TraitDef {
 }
 
 pub fn ty_of_item(ccx: &CrateCtxt, it: &ast::item)
-               -> ty::ty_param_bounds_and_ty {
+                  -> ty::ty_param_bounds_and_ty {
     let def_id = local_def(it.id);
     let tcx = ccx.tcx;
     match tcx.tcache.find(&def_id) {
-      Some(&tpt) => return tpt,
-      _ => {}
+        Some(&tpt) => return tpt,
+        _ => {}
     }
-    let rp = tcx.region_paramd_items.find(&it.id).map(|x| *x);
     match it.node {
-      ast::item_static(ref t, _, _) => {
-        let typ = ccx.to_ty(&EmptyRscope, t);
-        let tpt = no_params(typ);
-        tcx.tcache.insert(local_def(it.id), tpt);
-        return tpt;
-      }
-      ast::item_fn(ref decl, purity, abi, ref generics, _) => {
-        assert!(rp.is_none());
-        let ty_generics = ty_generics(ccx, None, generics, 0);
-        let tofd = astconv::ty_of_bare_fn(ccx,
-                                          &EmptyRscope,
-                                          purity,
-                                          abi,
-                                          &generics.lifetimes,
-                                          decl);
-        let tpt = ty_param_bounds_and_ty {
-            generics: ty::Generics {
-                type_param_defs: ty_generics.type_param_defs,
-                region_param: None
-            },
-            ty: ty::mk_bare_fn(ccx.tcx, tofd)
-        };
-        debug!("type of {} (id {}) is {}",
-               tcx.sess.str_of(it.ident),
-               it.id,
-               ppaux::ty_to_str(tcx, tpt.ty));
-        ccx.tcx.tcache.insert(local_def(it.id), tpt);
-        return tpt;
-      }
-      ast::item_ty(ref t, ref generics) => {
-        match tcx.tcache.find(&local_def(it.id)) {
-          Some(&tpt) => return tpt,
-          None => { }
+        ast::item_static(ref t, _, _) => {
+            let typ = ccx.to_ty(&ExplicitRscope, t);
+            let tpt = no_params(typ);
+            tcx.tcache.insert(local_def(it.id), tpt);
+            return tpt;
         }
-
-        let rp = tcx.region_paramd_items.find(&it.id).map(|x| *x);
-        let region_parameterization =
-            RegionParameterization::from_variance_and_generics(rp, generics);
-        let tpt = {
-            let ty = ccx.to_ty(&TypeRscope(region_parameterization), t);
-            ty_param_bounds_and_ty {
-                generics: ty_generics(ccx, rp, generics, 0),
-                ty: ty
+        ast::item_fn(ref decl, purity, abi, ref generics, _) => {
+            let ty_generics = ty_generics(ccx, generics, 0);
+            let tofd = astconv::ty_of_bare_fn(ccx,
+                                              it.id,
+                                              purity,
+                                              abi,
+                                              decl);
+            let tpt = ty_param_bounds_and_ty {
+                generics: ty::Generics {
+                    type_param_defs: ty_generics.type_param_defs,
+                    region_param_defs: @[],
+                },
+                ty: ty::mk_bare_fn(ccx.tcx, tofd)
+            };
+            debug!("type of {} (id {}) is {}",
+                    tcx.sess.str_of(it.ident),
+                    it.id,
+                    ppaux::ty_to_str(tcx, tpt.ty));
+            ccx.tcx.tcache.insert(local_def(it.id), tpt);
+            return tpt;
+        }
+        ast::item_ty(ref t, ref generics) => {
+            match tcx.tcache.find(&local_def(it.id)) {
+                Some(&tpt) => return tpt,
+                None => { }
             }
-        };
 
-        tcx.tcache.insert(local_def(it.id), tpt);
-        return tpt;
-      }
-      ast::item_enum(_, ref generics) => {
-        // Create a new generic polytype.
-        let (ty_generics, substs) = mk_item_substs(ccx, generics, rp, None);
-        let t = ty::mk_enum(tcx, local_def(it.id), substs);
-        let tpt = ty_param_bounds_and_ty {
-            generics: ty_generics,
-            ty: t
-        };
-        tcx.tcache.insert(local_def(it.id), tpt);
-        return tpt;
-      }
-      ast::item_trait(*) => {
-          tcx.sess.span_bug(
-              it.span,
-              format!("Invoked ty_of_item on trait"));
-      }
-      ast::item_struct(_, ref generics) => {
-          let (ty_generics, substs) = mk_item_substs(ccx, generics, rp, None);
-          let t = ty::mk_struct(tcx, local_def(it.id), substs);
-          let tpt = ty_param_bounds_and_ty {
-              generics: ty_generics,
-              ty: t
-          };
-          tcx.tcache.insert(local_def(it.id), tpt);
-          return tpt;
-      }
-      ast::item_impl(*) | ast::item_mod(_) |
-      ast::item_foreign_mod(_) => fail!(),
-      ast::item_mac(*) => fail!("item macros unimplemented")
+            let tpt = {
+                let ty = ccx.to_ty(&ExplicitRscope, t);
+                ty_param_bounds_and_ty {
+                    generics: ty_generics(ccx, generics, 0),
+                    ty: ty
+                }
+            };
+
+            tcx.tcache.insert(local_def(it.id), tpt);
+            return tpt;
+        }
+        ast::item_enum(_, ref generics) => {
+            // Create a new generic polytype.
+            let ty_generics = ty_generics(ccx, generics, 0);
+            let substs = mk_item_substs(ccx, &ty_generics, None);
+            let t = ty::mk_enum(tcx, local_def(it.id), substs);
+            let tpt = ty_param_bounds_and_ty {
+                generics: ty_generics,
+                ty: t
+            };
+            tcx.tcache.insert(local_def(it.id), tpt);
+            return tpt;
+        }
+        ast::item_trait(*) => {
+            tcx.sess.span_bug(
+                it.span,
+                format!("Invoked ty_of_item on trait"));
+        }
+        ast::item_struct(_, ref generics) => {
+            let ty_generics = ty_generics(ccx, generics, 0);
+            let substs = mk_item_substs(ccx, &ty_generics, None);
+            let t = ty::mk_struct(tcx, local_def(it.id), substs);
+            let tpt = ty_param_bounds_and_ty {
+                generics: ty_generics,
+                ty: t
+            };
+            tcx.tcache.insert(local_def(it.id), tpt);
+            return tpt;
+        }
+        ast::item_impl(*) | ast::item_mod(_) |
+        ast::item_foreign_mod(_) => fail!(),
+        ast::item_mac(*) => fail!("item macros unimplemented")
     }
 }
 
@@ -1197,28 +1134,29 @@ pub fn ty_of_foreign_item(ccx: &CrateCtxt,
             ty::ty_param_bounds_and_ty {
                 generics: ty::Generics {
                     type_param_defs: @~[],
-                    region_param: None,
+                    region_param_defs: @[],
                 },
-                ty: ast_ty_to_ty(ccx, &EmptyRscope, t)
+                ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
             }
         }
     }
 }
 
 pub fn ty_generics(ccx: &CrateCtxt,
-                   rp: Option<ty::region_variance>,
                    generics: &ast::Generics,
                    base_index: uint) -> ty::Generics {
     return ty::Generics {
-        region_param: rp,
+        region_param_defs: generics.lifetimes.iter().map(|l| {
+                ty::RegionParameterDef { ident: l.ident,
+                                         def_id: local_def(l.id) }
+            }).collect(),
         type_param_defs: @generics.ty_params.mapi_to_vec(|offset, param| {
             match ccx.tcx.ty_param_defs.find(&param.id) {
                 Some(&def) => def,
                 None => {
                     let param_ty = ty::param_ty {idx: base_index + offset,
                                                  def_id: local_def(param.id)};
-                    let bounds = @compute_bounds(ccx, rp, generics,
-                                                 param_ty, &param.bounds);
+                    let bounds = @compute_bounds(ccx, param_ty, &param.bounds);
                     let def = ty::TypeParameterDef {
                         ident: param.ident,
                         def_id: local_def(param.id),
@@ -1234,13 +1172,10 @@ pub fn ty_generics(ccx: &CrateCtxt,
 
     fn compute_bounds(
         ccx: &CrateCtxt,
-        rp: Option<ty::region_variance>,
-        generics: &ast::Generics,
         param_ty: ty::param_ty,
         ast_bounds: &OptVec<ast::TyParamBound>) -> ty::ParamBounds
     {
         /*!
-         *
          * Translate the AST's notion of ty param bounds (which are an
          * enum consisting of a newtyped Ty or a region) to ty's
          * notion of ty param bounds, which can either be user-defined
@@ -1256,7 +1191,7 @@ fn compute_bounds(
             match *ast_bound {
                 TraitTyParamBound(ref b) => {
                     let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
-                    let trait_ref = instantiate_trait_ref(ccx, b, rp, generics, ty);
+                    let trait_ref = instantiate_trait_ref(ccx, b, ty);
                     if !ty::try_add_builtin_trait(
                         ccx.tcx, trait_ref.def_id,
                         &mut param_bounds.builtin_bounds)
@@ -1282,9 +1217,8 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
                              ast_generics: &ast::Generics,
                              abis: AbiSet)
                           -> ty::ty_param_bounds_and_ty {
-    let ty_generics = ty_generics(ccx, None, ast_generics, 0);
-    let region_param_names = RegionParamNames::from_generics(ast_generics);
-    let rb = in_binding_rscope(&EmptyRscope, region_param_names);
+    let ty_generics = ty_generics(ccx, ast_generics, 0);
+    let rb = BindingRscope::new(def_id.node);
     let input_tys = decl.inputs.map(|a| ty_of_arg(ccx, &rb, a, None) );
     let output_ty = ast_ty_to_ty(ccx, &rb, &decl.output);
 
@@ -1293,12 +1227,10 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
         ty::BareFnTy {
             abis: abis,
             purity: ast::unsafe_fn,
-            sig: ty::FnSig {
-                bound_lifetime_names: opt_vec::Empty,
-                inputs: input_tys,
-                output: output_ty,
-                variadic: decl.variadic
-            }
+            sig: ty::FnSig {binder_id: def_id.node,
+                            inputs: input_tys,
+                            output: output_ty,
+                            variadic: decl.variadic}
         });
     let tpt = ty_param_bounds_and_ty {
         generics: ty_generics,
@@ -1309,19 +1241,18 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
 }
 
 pub fn mk_item_substs(ccx: &CrateCtxt,
-                      ast_generics: &ast::Generics,
-                      rp: Option<ty::region_variance>,
-                      self_ty: Option<ty::t>) -> (ty::Generics, ty::substs)
+                      ty_generics: &ty::Generics,
+                      self_ty: Option<ty::t>) -> ty::substs
 {
-    let mut i = 0;
-    let ty_generics = ty_generics(ccx, rp, ast_generics, 0);
-    let params = ast_generics.ty_params.map_to_vec(|atp| {
-        let t = ty::mk_param(ccx.tcx, i, local_def(atp.id));
-        i += 1u;
-        t
-    });
-    let regions = rscope::bound_self_region(rp);
-    (ty_generics, substs {regions: ty::NonerasedRegions(regions),
-                          self_ty: self_ty,
-                          tps: params})
+    let params: ~[ty::t] =
+        ty_generics.type_param_defs.iter().enumerate().map(
+            |(i, t)| ty::mk_param(ccx.tcx, i, t.def_id)).collect();
+
+    let regions: OptVec<ty::Region> =
+        ty_generics.region_param_defs.iter().enumerate().map(
+            |(i, l)| ty::re_type_bound(l.def_id.node, i, l.ident)).collect();
+
+    substs {regions: ty::NonerasedRegions(regions),
+            self_ty: self_ty,
+            tps: params}
 }
index 5d0f44ae7e3563fef8d0ec92583d2d81f1d14ce2..d6d1618de71005f24fe1557f80864b318f0bf438 100644 (file)
@@ -429,23 +429,20 @@ fn argvecs<C:Combine>(this: &C, a_args: &[ty::t], b_args: &[ty::t]) -> cres<~[ty
         return Err(ty::terr_variadic_mismatch(expected_found(this, a.variadic, b.variadic)));
     }
 
-    do argvecs(this, a.inputs, b.inputs)
-            .and_then |inputs| {
-        do this.tys(a.output, b.output).and_then |output| {
-            Ok(FnSig {
-                bound_lifetime_names: opt_vec::Empty, // FIXME(#4846)
-                inputs: inputs.clone(),
-                output: output,
-                variadic: a.variadic
-            })
-        }
-    }
+    let inputs = if_ok!(argvecs(this, a.inputs, b.inputs));
+    let output = if_ok!(this.tys(a.output, b.output));
+    Ok(FnSig {binder_id: a.binder_id,
+              inputs: inputs,
+              output: output,
+              variadic: a.variadic})
 }
 
-pub fn super_tys<C:Combine>(
-    this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
+pub fn super_tys<C:Combine>(this: &C, a: ty::t, b: ty::t) -> cres<ty::t> {
     let tcx = this.infcx().tcx;
-    return match (&ty::get(a).sty, &ty::get(b).sty) {
+    let a_sty = &ty::get(a).sty;
+    let b_sty = &ty::get(b).sty;
+    debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
+    return match (a_sty, b_sty) {
       // The "subtype" ought to be handling cases involving bot or var:
       (&ty::ty_bot, _) |
       (_, &ty::ty_bot) |
@@ -494,6 +491,7 @@ pub fn super_tys<C:Combine>(
             unify_float_variable(this, !this.a_is_expected(), v_id, v)
         }
 
+      (&ty::ty_char, _) |
       (&ty::ty_nil, _) |
       (&ty::ty_bool, _) |
       (&ty::ty_int(_), _) |
index 87c7373b005d56db747c766d029bab7cc9aca04d..78e0bd17ecaa824f09f323e42be59480247ee35e 100644 (file)
 use middle::typeck::infer::{cres, InferCtxt};
 use middle::typeck::infer::{TypeTrace, Subtype};
 use middle::typeck::infer::fold_regions_in_sig;
-use middle::typeck::isr_alist;
 use syntax::ast::{Many, Once, extern_fn, impure_fn, MutImmutable, MutMutable};
-use syntax::ast::{unsafe_fn};
+use syntax::ast::{unsafe_fn, NodeId};
 use syntax::ast::{Onceness, purity};
+use std::hashmap::HashMap;
 use util::common::{indenter};
 use util::ppaux::mt_to_str;
 
-use extra::list;
-
 pub struct Glb(CombineFields);  // "greatest lower bound" (common subtype)
 
 impl Combine for Glb {
@@ -132,14 +130,14 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         let snapshot = self.infcx.region_vars.start_snapshot();
 
         // Instantiate each bound region with a fresh region variable.
-        let (a_with_fresh, a_isr) =
+        let (a_with_fresh, a_map) =
             self.infcx.replace_bound_regions_with_fresh_regions(
                 self.trace, a);
-        let a_vars = var_ids(self, a_isr);
-        let (b_with_fresh, b_isr) =
+        let a_vars = var_ids(self, &a_map);
+        let (b_with_fresh, b_map) =
             self.infcx.replace_bound_regions_with_fresh_regions(
                 self.trace, b);
-        let b_vars = var_ids(self, b_isr);
+        let b_vars = var_ids(self, &b_map);
 
         // Collect constraints.
         let sig0 = if_ok!(super_fn_sigs(self, &a_with_fresh, &b_with_fresh));
@@ -152,20 +150,23 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
             fold_regions_in_sig(
                 self.infcx.tcx,
                 &sig0,
-                |r, _in_fn| generalize_region(self, snapshot,
-                                              new_vars, a_isr, a_vars, b_vars,
-                                              r));
+                |r| generalize_region(self, snapshot,
+                                      new_vars, sig0.binder_id,
+                                      &a_map, a_vars, b_vars,
+                                      r));
         debug!("sig1 = {}", sig1.inf_str(self.infcx));
         return Ok(sig1);
 
         fn generalize_region(this: &Glb,
                              snapshot: uint,
                              new_vars: &[RegionVid],
-                             a_isr: isr_alist,
+                             new_binder_id: NodeId,
+                             a_map: &HashMap<ty::bound_region, ty::Region>,
                              a_vars: &[RegionVid],
                              b_vars: &[RegionVid],
                              r0: ty::Region) -> ty::Region {
             if !is_var_in_set(new_vars, r0) {
+                assert!(!r0.is_bound());
                 return r0;
             }
 
@@ -177,13 +178,13 @@ fn generalize_region(this: &Glb,
             for r in tainted.iter() {
                 if is_var_in_set(a_vars, *r) {
                     if a_r.is_some() {
-                        return fresh_bound_variable(this);
+                        return fresh_bound_variable(this, new_binder_id);
                     } else {
                         a_r = Some(*r);
                     }
                 } else if is_var_in_set(b_vars, *r) {
                     if b_r.is_some() {
-                        return fresh_bound_variable(this);
+                        return fresh_bound_variable(this, new_binder_id);
                     } else {
                         b_r = Some(*r);
                     }
@@ -192,57 +193,57 @@ fn generalize_region(this: &Glb,
                 }
             }
 
-                // NB---I do not believe this algorithm computes
-                // (necessarily) the GLB.  As written it can
-                // spuriously fail.  In particular, if there is a case
-                // like: &fn(fn(&a)) and fn(fn(&b)), where a and b are
-                // free, it will return fn(&c) where c = GLB(a,b).  If
-                // however this GLB is not defined, then the result is
-                // an error, even though something like
-                // "fn<X>(fn(&X))" where X is bound would be a
-                // subtype of both of those.
-                //
-                // The problem is that if we were to return a bound
-                // variable, we'd be computing a lower-bound, but not
-                // necessarily the *greatest* lower-bound.
+            // NB---I do not believe this algorithm computes
+            // (necessarily) the GLB.  As written it can
+            // spuriously fail.  In particular, if there is a case
+            // like: &fn(fn(&a)) and fn(fn(&b)), where a and b are
+            // free, it will return fn(&c) where c = GLB(a,b).  If
+            // however this GLB is not defined, then the result is
+            // an error, even though something like
+            // "fn<X>(fn(&X))" where X is bound would be a
+            // subtype of both of those.
+            //
+            // The problem is that if we were to return a bound
+            // variable, we'd be computing a lower-bound, but not
+            // necessarily the *greatest* lower-bound.
+            //
+            // Unfortunately, this problem is non-trivial to solve,
+            // because we do not know at the time of computing the GLB
+            // whether a GLB(a,b) exists or not, because we haven't
+            // run region inference (or indeed, even fully computed
+            // the region hierarchy!). The current algorithm seems to
+            // works ok in practice.
 
             if a_r.is_some() && b_r.is_some() && only_new_vars {
                 // Related to exactly one bound variable from each fn:
-                return rev_lookup(this, a_isr, a_r.unwrap());
+                return rev_lookup(this, a_map, new_binder_id, a_r.unwrap());
             } else if a_r.is_none() && b_r.is_none() {
                 // Not related to bound variables from either fn:
+                assert!(!r0.is_bound());
                 return r0;
             } else {
                 // Other:
-                return fresh_bound_variable(this);
+                return fresh_bound_variable(this, new_binder_id);
             }
         }
 
         fn rev_lookup(this: &Glb,
-                      a_isr: isr_alist,
+                      a_map: &HashMap<ty::bound_region, ty::Region>,
+                      new_binder_id: NodeId,
                       r: ty::Region) -> ty::Region
         {
-            let mut ret = None;
-            do list::each(a_isr) |pair| {
-                let (a_br, a_r) = *pair;
-                if a_r == r {
-                    ret = Some(ty::re_bound(a_br));
-                    false
-                } else {
-                    true
+            for (a_br, a_r) in a_map.iter() {
+                if *a_r == r {
+                    return ty::re_fn_bound(new_binder_id, *a_br);
                 }
-            };
-
-            match ret {
-                Some(x) => x,
-                None => this.infcx.tcx.sess.span_bug(
-                            this.trace.origin.span(),
-                            format!("could not find original bound region for {:?}", r))
             }
+            this.infcx.tcx.sess.span_bug(
+                this.trace.origin.span(),
+                format!("could not find original bound region for {:?}", r))
         }
 
-        fn fresh_bound_variable(this: &Glb) -> ty::Region {
-            this.infcx.region_vars.new_bound()
+        fn fresh_bound_variable(this: &Glb, binder_id: NodeId) -> ty::Region {
+            this.infcx.region_vars.new_bound(binder_id)
         }
     }
 }
index 8a32a305b3a0e6b7b7aff8942d7d1106f4825d6b..9aaa4be1181f7db762e566d1a872c180537f4436 100644 (file)
@@ -35,7 +35,6 @@
 
 use middle::ty::{RegionVid, TyVar, Vid};
 use middle::ty;
-use middle::typeck::isr_alist;
 use middle::typeck::infer::*;
 use middle::typeck::infer::combine::*;
 use middle::typeck::infer::glb::Glb;
 use middle::typeck::infer::unify::*;
 use middle::typeck::infer::sub::Sub;
 use middle::typeck::infer::to_str::InferStr;
+use std::hashmap::HashMap;
 use util::common::indenter;
 
-use extra::list;
-
 pub trait LatticeValue {
     fn sub(cf: &CombineFields, a: &Self, b: &Self) -> ures;
     fn lub(cf: &CombineFields, a: &Self, b: &Self) -> cres<Self>;
@@ -366,14 +364,13 @@ fn ty_bot(&self, _t: ty::t) -> cres<ty::t> {
     }
 }
 
-pub fn super_lattice_tys<L:LatticeDir + TyLatticeDir + Combine>(
-    this: &L,
-    a: ty::t,
-    b: ty::t) -> cres<ty::t> {
+pub fn super_lattice_tys<L:LatticeDir+TyLatticeDir+Combine>(this: &L,
+                                                            a: ty::t,
+                                                            b: ty::t)
+                                                            -> cres<ty::t> {
     debug!("{}.lattice_tys({}, {})", this.tag(),
            a.inf_str(this.infcx()),
            b.inf_str(this.infcx()));
-    let _r = indenter();
 
     if a == b {
         return Ok(a);
@@ -524,20 +521,17 @@ pub fn lattice_var_and_t<L:LatticeDir + Combine,
 // Random utility functions used by LUB/GLB when computing LUB/GLB of
 // fn types
 
-pub fn var_ids<T:Combine>(this: &T, isr: isr_alist) -> ~[RegionVid] {
-    let mut result = ~[];
-    do list::each(isr) |pair| {
-        match pair.second() {
-            ty::re_infer(ty::ReVar(r)) => { result.push(r); }
+pub fn var_ids<T:Combine>(this: &T,
+                          map: &HashMap<ty::bound_region, ty::Region>)
+                          -> ~[RegionVid] {
+    map.iter().map(|(_, r)| match *r {
+            ty::re_infer(ty::ReVar(r)) => { r }
             r => {
                 this.infcx().tcx.sess.span_bug(
                     this.trace().origin.span(),
                     format!("Found non-region-vid: {:?}", r));
             }
-        }
-        true
-    };
-    result
+        }).collect()
 }
 
 pub fn is_var_in_set(new_vars: &[RegionVid], r: ty::Region) -> bool {
index 42793d956df063fc1a0ee6db98ee49ff39d40a66..ad649f379b58ca9086681f6d2eeaa373e217c0be 100644 (file)
 use middle::typeck::infer::{cres, InferCtxt};
 use middle::typeck::infer::fold_regions_in_sig;
 use middle::typeck::infer::{TypeTrace, Subtype};
-use middle::typeck::isr_alist;
-use util::ppaux::mt_to_str;
-
-use extra::list;
-use syntax::ast::{Many, Once, extern_fn, impure_fn};
+use std::hashmap::HashMap;
+use syntax::ast::{Many, Once, extern_fn, impure_fn, NodeId};
 use syntax::ast::{unsafe_fn};
 use syntax::ast::{Onceness, purity};
+use util::ppaux::mt_to_str;
 
 pub struct Lub(CombineFields);  // least-upper-bound: common supertype
 
@@ -125,7 +123,7 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         let snapshot = self.infcx.region_vars.start_snapshot();
 
         // Instantiate each bound region with a fresh region variable.
-        let (a_with_fresh, a_isr) =
+        let (a_with_fresh, a_map) =
             self.infcx.replace_bound_regions_with_fresh_regions(
                 self.trace, a);
         let (b_with_fresh, _) =
@@ -143,17 +141,20 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
             fold_regions_in_sig(
                 self.infcx.tcx,
                 &sig0,
-                |r, _in_fn| generalize_region(self, snapshot, new_vars,
-                                              a_isr, r));
+                |r| generalize_region(self, snapshot, new_vars,
+                                      sig0.binder_id, &a_map, r));
         return Ok(sig1);
 
         fn generalize_region(this: &Lub,
                              snapshot: uint,
                              new_vars: &[RegionVid],
-                             a_isr: isr_alist,
-                             r0: ty::Region) -> ty::Region {
+                             new_scope: NodeId,
+                             a_map: &HashMap<ty::bound_region, ty::Region>,
+                             r0: ty::Region)
+                             -> ty::Region {
             // Regions that pre-dated the LUB computation stay as they are.
             if !is_var_in_set(new_vars, r0) {
+                assert!(!r0.is_bound());
                 debug!("generalize_region(r0={:?}): not new variable", r0);
                 return r0;
             }
@@ -167,6 +168,7 @@ fn generalize_region(this: &Lub,
                 debug!("generalize_region(r0={:?}): \
                         non-new-variables found in {:?}",
                        r0, tainted);
+                assert!(!r0.is_bound());
                 return r0;
             }
 
@@ -175,27 +177,19 @@ fn generalize_region(this: &Lub,
             // in both A and B.  Replace the variable with the "first"
             // bound region from A that we find it to be associated
             // with.
-            let mut ret = None;
-            do list::each(a_isr) |pair| {
-                let (a_br, a_r) = *pair;
-                if tainted.iter().any(|x| x == &a_r) {
+            for (a_br, a_r) in a_map.iter() {
+                if tainted.iter().any(|x| x == a_r) {
                     debug!("generalize_region(r0={:?}): \
                             replacing with {:?}, tainted={:?}",
-                           r0, a_br, tainted);
-                    ret = Some(ty::re_bound(a_br));
-                    false
-                } else {
-                    true
+                           r0, *a_br, tainted);
+                    return ty::re_fn_bound(new_scope, *a_br);
                 }
-            };
-
-            match ret {
-                Some(x) => x,
-                None => this.infcx.tcx.sess.span_bug(
-                            this.trace.origin.span(),
-                            format!("Region {:?} is not associated with \
-                                  any bound region from A!", r0))
             }
+
+            this.infcx.tcx.sess.span_bug(
+                this.trace.origin.span(),
+                format!("Region {:?} is not associated with \
+                        any bound region from A!", r0))
         }
     }
 
index 487eb4c32890e9f267c8aebcf57dbe9fb163f7e8..121b32f4145a4e73daae8c2dc1e2cb3fc81368db 100644 (file)
 pub use middle::typeck::infer::resolve::{resolve_nested_tvar};
 pub use middle::typeck::infer::resolve::{resolve_rvar};
 
+use extra::smallintmap::SmallIntMap;
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, Vid};
 use middle::ty;
+use middle::ty_fold;
+use middle::ty_fold::TypeFolder;
 use middle::typeck::check::regionmanip::{replace_bound_regions_in_fn_sig};
 use middle::typeck::infer::coercion::Coerce;
 use middle::typeck::infer::combine::{Combine, CombineFields, eq_tys};
 use middle::typeck::infer::to_str::InferStr;
 use middle::typeck::infer::unify::{ValsAndBindings, Root};
 use middle::typeck::infer::error_reporting::ErrorReporting;
-use middle::typeck::isr_alist;
-use util::common::indent;
-use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str, Repr,
-                  UserString};
-
+use std::hashmap::HashMap;
 use std::result;
 use std::vec;
-use extra::list::Nil;
-use extra::smallintmap::SmallIntMap;
 use syntax::ast::{MutImmutable, MutMutable};
 use syntax::ast;
 use syntax::codemap;
 use syntax::codemap::Span;
+use util::common::indent;
+use util::ppaux::{bound_region_to_str, ty_to_str, trait_ref_to_str, Repr,
+                  UserString};
 
 pub mod doc;
 pub mod macros;
@@ -225,8 +225,6 @@ pub enum RegionVariableOrigin {
     BoundRegionInTypeOrImpl(Span),
 
     BoundRegionInCoherence,
-
-    BoundRegionError(Span),
 }
 
 pub enum fixup_err {
@@ -568,15 +566,16 @@ pub fn commit<T,E>(@mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
     /// Execute `f`, unroll bindings on failure
     pub fn try<T,E>(@mut self, f: &fn() -> Result<T,E>) -> Result<T,E> {
         debug!("try()");
-        do indent {
-            let snapshot = self.start_snapshot();
-            let r = f();
-            match r {
-              Ok(_) => (),
-              Err(_) => self.rollback_to(&snapshot)
+        let snapshot = self.start_snapshot();
+        let r = f();
+        match r {
+            Ok(_) => { debug!("success"); }
+            Err(ref e) => {
+                debug!("error: {:?}", *e);
+                self.rollback_to(&snapshot)
             }
-            r
         }
+        r
     }
 
     /// Execute `f` then unroll any bindings it creates
@@ -642,6 +641,17 @@ pub fn next_region_var(&mut self, origin: RegionVariableOrigin) -> ty::Region {
         ty::re_infer(ty::ReVar(self.region_vars.new_region_var(origin)))
     }
 
+    pub fn next_region_vars(&mut self,
+                            origin: RegionVariableOrigin,
+                            count: uint)
+                            -> ~[ty::Region] {
+        vec::from_fn(count, |_| self.next_region_var(origin))
+    }
+
+    pub fn fresh_bound_region(&mut self, binder_id: ast::NodeId) -> ty::Region {
+        self.region_vars.new_bound(binder_id)
+    }
+
     pub fn resolve_regions(@mut self) {
         let errors = self.region_vars.resolve_regions();
         self.report_region_errors(&errors); // see error_reporting.rs
@@ -787,9 +797,11 @@ pub fn report_mismatched_types(@mut self,
     pub fn replace_bound_regions_with_fresh_regions(&mut self,
                                                     trace: TypeTrace,
                                                     fsig: &ty::FnSig)
-                                                    -> (ty::FnSig, isr_alist) {
-        let(isr, _, fn_sig) =
-            replace_bound_regions_in_fn_sig(self.tcx, @Nil, None, fsig, |br| {
+                                                    -> (ty::FnSig,
+                                                        HashMap<ty::bound_region,
+                                                                ty::Region>) {
+        let (map, _, fn_sig) =
+            replace_bound_regions_in_fn_sig(self.tcx, None, fsig, |br| {
                 let rvar = self.next_region_var(
                     BoundRegionInFnType(trace.origin.span(), br));
                 debug!("Bound region {} maps to {:?}",
@@ -797,18 +809,16 @@ pub fn replace_bound_regions_with_fresh_regions(&mut self,
                        rvar);
                 rvar
             });
-        (fn_sig, isr)
+        (fn_sig, map)
     }
 }
 
 pub fn fold_regions_in_sig(
     tcx: ty::ctxt,
     fn_sig: &ty::FnSig,
-    fldr: &fn(r: ty::Region, in_fn: bool) -> ty::Region) -> ty::FnSig
+    fldr: &fn(r: ty::Region) -> ty::Region) -> ty::FnSig
 {
-    do ty::fold_sig(fn_sig) |t| {
-        ty::fold_regions(tcx, t, |r, in_fn| fldr(r, in_fn))
-    }
+    ty_fold::RegionFolder::regions(tcx, fldr).fold_sig(fn_sig)
 }
 
 impl TypeTrace {
@@ -910,7 +920,6 @@ pub fn span(&self) -> Span {
             BoundRegionInFnType(a, _) => a,
             BoundRegionInTypeOrImpl(a) => a,
             BoundRegionInCoherence => codemap::dummy_sp(),
-            BoundRegionError(a) => a,
         }
     }
 }
@@ -931,7 +940,6 @@ fn repr(&self, tcx: ty::ctxt) -> ~str {
             BoundRegionInTypeOrImpl(a) => format!("BoundRegionInTypeOrImpl({})",
                                                a.repr(tcx)),
             BoundRegionInCoherence => format!("BoundRegionInCoherence"),
-            BoundRegionError(a) => format!("BoundRegionError({})", a.repr(tcx)),
         }
     }
 }
index 68c5ec3b7d66dc73aa5004965bdbedbc60de09b6..effd34da0de9d767b83780bc6739e5975fdbe36d 100644 (file)
@@ -13,7 +13,8 @@
 
 use middle::ty;
 use middle::ty::{FreeRegion, Region, RegionVid};
-use middle::ty::{re_empty, re_static, re_infer, re_free, re_bound};
+use middle::ty::{re_empty, re_static, re_infer, re_free, re_type_bound,
+                 re_fn_bound};
 use middle::ty::{re_scope, ReVar, ReSkolemized, br_fresh};
 use middle::typeck::infer::cres;
 use middle::typeck::infer::{RegionVariableOrigin, SubregionOrigin};
@@ -192,24 +193,33 @@ pub fn new_skolemized(&mut self, br: ty::bound_region) -> Region {
         re_infer(ReSkolemized(sc, br))
     }
 
-    pub fn new_bound(&mut self) -> Region {
+    pub fn new_bound(&mut self, binder_id: ast::NodeId) -> Region {
         // Creates a fresh bound variable for use in GLB computations.
         // See discussion of GLB computation in the large comment at
         // the top of this file for more details.
         //
-        // This computation is mildly wrong in the face of rollover.
-        // It's conceivable, if unlikely, that one might wind up with
-        // accidental capture for nested functions in that case, if
-        // the outer function had bound regions created a very long
-        // time before and the inner function somehow wound up rolling
-        // over such that supposedly fresh identifiers were in fact
-        // shadowed.  We should convert our bound_region
-        // representation to use deBruijn indices or something like
-        // that to eliminate that possibility.
+        // This computation is potentially wrong in the face of
+        // rollover.  It's conceivable, if unlikely, that one might
+        // wind up with accidental capture for nested functions in
+        // that case, if the outer function had bound regions created
+        // a very long time before and the inner function somehow
+        // wound up rolling over such that supposedly fresh
+        // identifiers were in fact shadowed. For now, we just assert
+        // that there is no rollover -- eventually we should try to be
+        // robust against this possibility, either by checking the set
+        // of bound identifiers that appear in a given expression and
+        // ensure that we generate one that is distinct, or by
+        // changing the representation of bound regions in a fn
+        // declaration
 
         let sc = self.bound_count;
         self.bound_count += 1;
-        re_bound(br_fresh(sc))
+
+        if sc >= self.bound_count {
+            self.tcx.sess.bug("Rollover in RegionInference new_bound()");
+        }
+
+        re_fn_bound(binder_id, br_fresh(sc))
     }
 
     pub fn add_constraint(&mut self,
@@ -236,6 +246,16 @@ pub fn make_subregion(&mut self,
 
         debug!("RegionVarBindings: make_subregion({:?}, {:?})", sub, sup);
         match (sub, sup) {
+          (re_type_bound(*), _) |
+          (re_fn_bound(*), _) |
+          (_, re_type_bound(*)) |
+          (_, re_fn_bound(*)) => {
+            self.tcx.sess.span_bug(
+                origin.span(),
+                format!("Cannot relate bound region: {} <= {}",
+                        sub.repr(self.tcx),
+                        sup.repr(self.tcx)));
+          }
           (re_infer(ReVar(sub_id)), re_infer(ReVar(sup_id))) => {
             self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
           }
@@ -245,16 +265,6 @@ pub fn make_subregion(&mut self,
           (re_infer(ReVar(sub_id)), r) => {
             self.add_constraint(ConstrainVarSubReg(sub_id, r), origin);
           }
-          (re_bound(br), _) => {
-            self.tcx.sess.span_bug(
-                origin.span(),
-                format!("Cannot relate bound region as subregion: {:?}", br));
-          }
-          (_, re_bound(br)) => {
-            self.tcx.sess.span_bug(
-                origin.span(),
-                format!("Cannot relate bound region as superregion: {:?}", br));
-          }
           _ => {
             self.add_constraint(ConstrainRegSubReg(sub, sup), origin);
           }
@@ -485,6 +495,16 @@ fn is_subregion_of(&self, sub: Region, sup: Region) -> bool {
 
     fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
         match (a, b) {
+          (re_fn_bound(*), _) |
+          (_, re_fn_bound(*)) |
+          (re_type_bound(*), _) |
+          (_, re_type_bound(*)) => {
+            self.tcx.sess.bug(
+                format!("Cannot relate bound region: LUB({}, {})",
+                        a.repr(self.tcx),
+                        b.repr(self.tcx)));
+          }
+
           (re_static, _) | (_, re_static) => {
             re_static // nothing lives longer than static
           }
@@ -536,12 +556,7 @@ fn lub_concrete_regions(&self, a: Region, b: Region) -> Region {
           // For these types, we cannot define any additional
           // relationship:
           (re_infer(ReSkolemized(*)), _) |
-          (_, re_infer(ReSkolemized(*))) |
-          (re_bound(_), re_bound(_)) |
-          (re_bound(_), re_free(_)) |
-          (re_bound(_), re_scope(_)) |
-          (re_free(_), re_bound(_)) |
-          (re_scope(_), re_bound(_)) => {
+          (_, re_infer(ReSkolemized(*))) => {
             if a == b {a} else {re_static}
           }
         }
@@ -584,6 +599,16 @@ fn glb_concrete_regions(&self,
                          -> cres<Region> {
         debug!("glb_concrete_regions({:?}, {:?})", a, b);
         match (a, b) {
+            (re_fn_bound(*), _) |
+            (_, re_fn_bound(*)) |
+            (re_type_bound(*), _) |
+            (_, re_type_bound(*)) => {
+              self.tcx.sess.bug(
+                  format!("Cannot relate bound region: GLB({}, {})",
+                          a.repr(self.tcx),
+                          b.repr(self.tcx)));
+            }
+
             (re_static, r) | (r, re_static) => {
                 // static lives longer than everything else
                 Ok(r)
@@ -627,12 +652,7 @@ fn glb_concrete_regions(&self,
             // For these types, we cannot define any additional
             // relationship:
             (re_infer(ReSkolemized(*)), _) |
-            (_, re_infer(ReSkolemized(*))) |
-            (re_bound(_), re_bound(_)) |
-            (re_bound(_), re_free(_)) |
-            (re_bound(_), re_scope(_)) |
-            (re_free(_), re_bound(_)) |
-            (re_scope(_), re_bound(_)) => {
+            (_, re_infer(ReSkolemized(*))) => {
                 if a == b {
                     Ok(a)
                 } else {
index 564fcb76dc73b57ec688500de4c10b08d256b283..84f3d9c69379bb49d08595c37e504817efc85023 100644 (file)
@@ -50,6 +50,7 @@
 use middle::ty::{FloatVar, FloatVid, IntVar, IntVid, RegionVid, TyVar, TyVid};
 use middle::ty::{type_is_bot, IntType, UintType};
 use middle::ty;
+use middle::ty_fold;
 use middle::typeck::infer::{Bounds, cyclic_ty, fixup_err, fres, InferCtxt};
 use middle::typeck::infer::{region_var_bound_by_region_var, unresolved_ty};
 use middle::typeck::infer::to_str::InferStr;
@@ -96,6 +97,20 @@ pub fn resolver(infcx: @mut InferCtxt, modes: uint) -> ResolveState {
     }
 }
 
+impl ty_fold::TypeFolder for ResolveState {
+    fn tcx(&self) -> ty::ctxt {
+        self.infcx.tcx
+    }
+
+    fn fold_ty(&mut self, t: ty::t) -> ty::t {
+        self.resolve_type(t)
+    }
+
+    fn fold_region(&mut self, r: ty::Region) -> ty::Region {
+        self.resolve_region(r)
+    }
+}
+
 impl ResolveState {
     pub fn should(&mut self, mode: uint) -> bool {
         (self.modes & mode) == mode
@@ -166,11 +181,7 @@ pub fn resolve_type(&mut self, typ: ty::t) -> ty::t {
                     typ
                 } else {
                     self.type_depth += 1;
-                    let result = ty::fold_regions_and_ty(
-                        self.infcx.tcx, typ,
-                        |r| self.resolve_region(r),
-                        |t| self.resolve_type(t),
-                        |t| self.resolve_type(t));
+                    let result = ty_fold::super_fold_ty(self, typ);
                     self.type_depth -= 1;
                     result
                 }
index e5afefe0c716471b18bb503f35a6389df9129aaa..802d635a3f0c0edcb2502acdde448345d562363f 100644 (file)
@@ -24,8 +24,6 @@
 use util::common::{indenter};
 use util::ppaux::bound_region_to_str;
 
-use extra::list::Nil;
-use extra::list;
 use syntax::ast::{Onceness, purity};
 
 pub struct Sub(CombineFields);  // "subtype", "subregion" etc
@@ -168,9 +166,8 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
 
         // Second, we instantiate each bound region in the supertype with a
         // fresh concrete region.
-        let (skol_isr, _, b_sig) = {
-            do replace_bound_regions_in_fn_sig(self.infcx.tcx, @Nil,
-                                              None, b) |br| {
+        let (skol_map, _, b_sig) = {
+            do replace_bound_regions_in_fn_sig(self.infcx.tcx, None, b) |br| {
                 let skol = self.infcx.region_vars.new_skolemized(br);
                 debug!("Bound region {} skolemized to {:?}",
                        bound_region_to_str(self.infcx.tcx, "", false, br),
@@ -189,10 +186,7 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
         // that the skolemized regions do not "leak".
         let new_vars =
             self.infcx.region_vars.vars_created_since_snapshot(snapshot);
-
-        let mut ret = Ok(sig);
-        do list::each(skol_isr) |pair| {
-            let (skol_br, skol) = *pair;
+        for (&skol_br, &skol) in skol_map.iter() {
             let tainted = self.infcx.region_vars.tainted(snapshot, skol);
             for tainted_region in tainted.iter() {
                 // Each skolemized should only be relatable to itself
@@ -208,19 +202,16 @@ fn fn_sigs(&self, a: &ty::FnSig, b: &ty::FnSig) -> cres<ty::FnSig> {
 
                 // A is not as polymorphic as B:
                 if self.a_is_expected {
-                    ret = Err(ty::terr_regions_insufficiently_polymorphic(
-                        skol_br, *tainted_region));
-                    break
+                    return Err(ty::terr_regions_insufficiently_polymorphic(
+                            skol_br, *tainted_region));
                 } else {
-                    ret = Err(ty::terr_regions_overly_polymorphic(
-                        skol_br, *tainted_region));
-                    break
+                    return Err(ty::terr_regions_overly_polymorphic(
+                            skol_br, *tainted_region));
                 }
             }
-            ret.is_ok()
-        };
+        }
 
-        ret
+        return Ok(sig);
     }
 
 }
index 75c7adfb03e405e764d2f9eae5368995e637d023..022c0ffb432541f05ac7b82e6823bc0c4e0392f7 100644 (file)
@@ -64,7 +64,6 @@
 use syntax::codemap::Span;
 use syntax::print::pprust::*;
 use syntax::{ast, ast_map, abi};
-use syntax::opt_vec;
 
 pub mod check;
 pub mod rscope;
@@ -266,7 +265,7 @@ pub fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
 pub fn no_params(t: ty::t) -> ty::ty_param_bounds_and_ty {
     ty::ty_param_bounds_and_ty {
         generics: ty::Generics {type_param_defs: @~[],
-                                region_param: None},
+                                region_param_defs: @[]},
         ty: t
     }
 }
@@ -354,7 +353,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 purity: ast::impure_fn,
                 abis: abi::AbiSet::Rust(),
                 sig: ty::FnSig {
-                    bound_lifetime_names: opt_vec::Empty,
+                    binder_id: main_id,
                     inputs: ~[],
                     output: ty::mk_nil(),
                     variadic: false
@@ -400,7 +399,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 purity: ast::impure_fn,
                 abis: abi::AbiSet::Rust(),
                 sig: ty::FnSig {
-                    bound_lifetime_names: opt_vec::Empty,
+                    binder_id: start_id,
                     inputs: ~[
                         ty::mk_int(),
                         ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
index 006e14232f368e65fdf1c1d7f2bce5ac4eedb3ab..89dc71b3af648241ba834e98b8e1947316b2e102 100644 (file)
 
 use metadata::encoder;
 use middle::ty::{ReSkolemized, ReVar};
-use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
+use middle::ty::{bound_region, br_anon, br_named};
 use middle::ty::{br_fresh, ctxt, field};
 use middle::ty::{mt, t, param_ty};
-use middle::ty::{re_bound, re_free, re_scope, re_infer, re_static, Region,
+use middle::ty::{re_free, re_scope, re_infer, re_static, Region,
                  re_empty};
 use middle::ty::{ty_bool, ty_char, ty_bot, ty_box, ty_struct, ty_enum};
 use middle::ty::{ty_err, ty_estr, ty_evec, ty_float, ty_bare_fn, ty_closure};
@@ -118,6 +118,11 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
             let (msg, opt_span) = explain_span(cx, "block", blk.span);
             (format!("{} {}", prefix, msg), opt_span)
           }
+          Some(&ast_map::node_item(it, _)) if match it.node {
+                ast::item_impl(*) => true, _ => false} => {
+            let (msg, opt_span) = explain_span(cx, "impl", it.span);
+            (format!("{} {}", prefix, msg), opt_span)
+          }
           Some(_) | None => {
             // this really should not happen
             (format!("{} node {}", prefix, fr.scope_id), None)
@@ -131,7 +136,7 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
 
       // I believe these cases should not occur (except when debugging,
       // perhaps)
-      re_infer(_) | re_bound(_) => {
+      ty::re_infer(_) | ty::re_type_bound(*) | ty::re_fn_bound(*) => {
         (format!("lifetime {:?}", region), None)
       }
     };
@@ -154,14 +159,15 @@ pub fn bound_region_to_str(cx: ctxt,
                            br: bound_region) -> ~str {
     let space_str = if space { " " } else { "" };
 
-    if cx.sess.verbose() { return format!("{}{:?}{}", prefix, br, space_str); }
+    if cx.sess.verbose() {
+        return format!("{}{}{}", prefix, br.repr(cx), space_str);
+    }
 
     match br {
-      br_named(id)         => format!("{}'{}{}", prefix, cx.sess.str_of(id), space_str),
-      br_self              => format!("{}'self{}", prefix, space_str),
+      br_named(_, ident)   => format!("{}'{}{}", prefix,
+                                      cx.sess.str_of(ident), space_str),
       br_anon(_)           => prefix.to_str(),
       br_fresh(_)          => prefix.to_str(),
-      br_cap_avoid(_, br)  => bound_region_to_str(cx, prefix, space, *br)
     }
 }
 
@@ -215,7 +221,7 @@ pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~st
     let space_str = if space { " " } else { "" };
 
     if cx.sess.verbose() {
-        return format!("{}{:?}{}", prefix, region, space_str);
+        return format!("{}{}{}", prefix, region.repr(cx), space_str);
     }
 
     // These printouts are concise.  They do not contain all the information
@@ -223,15 +229,16 @@ pub fn region_to_str(cx: ctxt, prefix: &str, space: bool, region: Region) -> ~st
     // to fit that into a short string.  Hence the recommendation to use
     // `explain_region()` or `note_and_explain_region()`.
     match region {
-        re_scope(_) => prefix.to_str(),
-        re_bound(br) => bound_region_to_str(cx, prefix, space, br),
-        re_free(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
-        re_infer(ReSkolemized(_, br)) => {
+        ty::re_scope(_) => prefix.to_str(),
+        ty::re_type_bound(_, _, ident) => cx.sess.str_of(ident).to_owned(),
+        ty::re_fn_bound(_, br) => bound_region_to_str(cx, prefix, space, br),
+        ty::re_free(ref fr) => bound_region_to_str(cx, prefix, space, fr.bound_region),
+        ty::re_infer(ReSkolemized(_, br)) => {
             bound_region_to_str(cx, prefix, space, br)
         }
-        re_infer(ReVar(_)) => prefix.to_str(),
-        re_static => format!("{}'static{}", prefix, space_str),
-        re_empty => format!("{}'<empty>{}", prefix, space_str)
+        ty::re_infer(ReVar(_)) => prefix.to_str(),
+        ty::re_static => format!("{}'static{}", prefix, space_str),
+        ty::re_empty => format!("{}'<empty>{}", prefix, space_str)
     }
 }
 
@@ -289,9 +296,10 @@ pub fn tys_to_str(cx: ctxt, ts: &[t]) -> ~str {
 }
 
 pub fn fn_sig_to_str(cx: ctxt, typ: &ty::FnSig) -> ~str {
-    format!("fn{} -> {}",
-         tys_to_str(cx, typ.inputs.map(|a| *a)),
-         ty_to_str(cx, typ.output))
+    format!("fn{}{} -> {}",
+            typ.binder_id,
+            typ.inputs.repr(cx),
+            typ.output.repr(cx))
 }
 
 pub fn trait_ref_to_str(cx: ctxt, trait_ref: &ty::TraitRef) -> ~str {
@@ -594,8 +602,17 @@ fn repr(&self, tcx: ctxt) -> ~str {
 
 impl Repr for ty::TypeParameterDef {
     fn repr(&self, tcx: ctxt) -> ~str {
-        format!("TypeParameterDef \\{{:?}, bounds: {}\\}",
-             self.def_id, self.bounds.repr(tcx))
+        format!("TypeParameterDef({:?}, {})",
+                self.def_id,
+                self.bounds.repr(tcx))
+    }
+}
+
+impl Repr for ty::RegionParameterDef {
+    fn repr(&self, tcx: ctxt) -> ~str {
+        format!("RegionParameterDef({}, {:?})",
+                tcx.sess.str_of(self.ident),
+                self.def_id)
     }
 }
 
@@ -655,6 +672,15 @@ fn repr(&self, tcx: ctxt) -> ~str {
     }
 }
 
+impl Repr for ast::item {
+    fn repr(&self, tcx: ctxt) -> ~str {
+        format!("item({})",
+                ast_map::node_id_to_str(tcx.items,
+                                        self.id,
+                                        token::get_ident_interner()))
+    }
+}
+
 impl Repr for ast::Pat {
     fn repr(&self, tcx: ctxt) -> ~str {
         format!("pat({}: {})",
@@ -665,13 +691,56 @@ fn repr(&self, tcx: ctxt) -> ~str {
 
 impl Repr for ty::bound_region {
     fn repr(&self, tcx: ctxt) -> ~str {
-        bound_region_ptr_to_str(tcx, *self)
+        match *self {
+            ty::br_anon(id) => format!("br_anon({})", id),
+            ty::br_named(id, ident) => format!("br_named({}, {})",
+                                               id.repr(tcx),
+                                               ident.repr(tcx)),
+            ty::br_fresh(id) => format!("br_fresh({})", id),
+        }
     }
 }
 
 impl Repr for ty::Region {
     fn repr(&self, tcx: ctxt) -> ~str {
-        region_to_str(tcx, "", false, *self)
+        match *self {
+            ty::re_type_bound(id, index, ident) => {
+                format!("re_type_bound({}, {}, {})",
+                        id, index, ident.repr(tcx))
+            }
+
+            ty::re_fn_bound(binder_id, ref bound_region) => {
+                format!("re_fn_bound({}, {})",
+                        binder_id, bound_region.repr(tcx))
+            }
+
+            ty::re_free(ref fr) => {
+                format!("re_free({}, {})",
+                        fr.scope_id,
+                        fr.bound_region.repr(tcx))
+            }
+
+            ty::re_scope(id) => {
+                format!("re_scope({})", id)
+            }
+
+            ty::re_static => {
+                format!("re_static")
+            }
+
+            ty::re_infer(ReVar(ref vid)) => {
+                format!("re_infer({})", vid.id)
+            }
+
+            ty::re_infer(ReSkolemized(id, ref bound_region)) => {
+                format!("re_skolemized({}, {})",
+                        id, bound_region.repr(tcx))
+            }
+
+            ty::re_empty => {
+                format!("re_empty")
+            }
+        }
     }
 }
 
@@ -707,23 +776,38 @@ fn repr(&self, tcx: ctxt) -> ~str {
 
 impl Repr for ty::Generics {
     fn repr(&self, tcx: ctxt) -> ~str {
-        format!("Generics \\{type_param_defs: {}, region_param: {:?}\\}",
-             self.type_param_defs.repr(tcx),
-             self.region_param)
+        format!("Generics(type_param_defs: {}, region_param_defs: {})",
+                self.type_param_defs.repr(tcx),
+                self.region_param_defs.repr(tcx))
+    }
+}
+
+impl Repr for ty::ItemVariances {
+    fn repr(&self, tcx: ctxt) -> ~str {
+        format!("IterVariances(self_param={}, type_params={}, region_params={})",
+                self.self_param.repr(tcx),
+                self.type_params.repr(tcx),
+                self.region_params.repr(tcx))
+    }
+}
+
+impl Repr for ty::Variance {
+    fn repr(&self, _: ctxt) -> ~str {
+        self.to_str().to_owned()
     }
 }
 
 impl Repr for ty::Method {
     fn repr(&self, tcx: ctxt) -> ~str {
-        format!("method \\{ident: {}, generics: {}, transformed_self_ty: {}, \
-              fty: {}, explicit_self: {}, vis: {}, def_id: {}\\}",
-             self.ident.repr(tcx),
-             self.generics.repr(tcx),
-             self.transformed_self_ty.repr(tcx),
-             self.fty.repr(tcx),
-             self.explicit_self.repr(tcx),
-             self.vis.repr(tcx),
-             self.def_id.repr(tcx))
+        format!("method(ident: {}, generics: {}, transformed_self_ty: {}, \
+                fty: {}, explicit_self: {}, vis: {}, def_id: {})",
+                self.ident.repr(tcx),
+                self.generics.repr(tcx),
+                self.transformed_self_ty.repr(tcx),
+                self.fty.repr(tcx),
+                self.explicit_self.repr(tcx),
+                self.vis.repr(tcx),
+                self.def_id.repr(tcx))
     }
 }
 
index dd1ad8263da860c2d1eb6d9864f6ffc2a8244855..f48ad25712d1226cd129f13637f6a1433f22406e 100644 (file)
@@ -835,7 +835,7 @@ fn clean(&self) -> Path {
 #[deriving(Clone, Encodable, Decodable)]
 pub struct PathSegment {
     name: ~str,
-    lifetime: Option<Lifetime>,
+    lifetimes: ~[Lifetime],
     types: ~[Type],
 }
 
@@ -843,7 +843,7 @@ impl Clean<PathSegment> for ast::PathSegment {
     fn clean(&self) -> PathSegment {
         PathSegment {
             name: self.identifier.clean(),
-            lifetime: self.lifetime.clean(),
+            lifetimes: self.lifetimes.clean(),
             types: self.types.clean()
         }
     }
index 9ff450d4135ff839d59015a49b3ec7e394d558e5..4c64feee384397ed5f1ef198e41aa8c13b99343d 100644 (file)
@@ -92,16 +92,17 @@ fn fmt(path: &clean::Path, f: &mut fmt::Formatter) {
             if i > 0 { f.buf.write("::".as_bytes()) }
             f.buf.write(seg.name.as_bytes());
 
-            if seg.lifetime.is_some() || seg.types.len() > 0 {
+            if seg.lifetimes.len() > 0 || seg.types.len() > 0 {
                 f.buf.write("&lt;".as_bytes());
-                match seg.lifetime {
-                    Some(ref lifetime) => write!(f.buf, "{}", *lifetime),
-                    None => {}
+                let mut comma = false;
+                for lifetime in seg.lifetimes.iter() {
+                    if comma { f.buf.write(", ".as_bytes()); }
+                    comma = true;
+                    write!(f.buf, "{}", *lifetime);
                 }
-                for (i, ty) in seg.types.iter().enumerate() {
-                    if i > 0 || seg.lifetime.is_some() {
-                        f.buf.write(", ".as_bytes());
-                    }
+                for ty in seg.types.iter() {
+                    if comma { f.buf.write(", ".as_bytes()); }
+                    comma = true;
                     write!(f.buf, "{}", *ty);
                 }
                 f.buf.write("&gt;".as_bytes());
@@ -152,16 +153,17 @@ fn path(w: &mut io::Writer, path: &clean::Path, print_all: bool,
     // The generics will get written to both the title and link
     let mut generics = ~"";
     let last = path.segments.last();
-    if last.lifetime.is_some() || last.types.len() > 0 {
+    if last.lifetimes.len() > 0 || last.types.len() > 0 {
+        let mut counter = 0;
         generics.push_str("&lt;");
-        match last.lifetime {
-            Some(ref lifetime) => generics.push_str(format!("{}", *lifetime)),
-            None => {}
+        for lifetime in last.lifetimes.iter() {
+            if counter > 0 { generics.push_str(", "); }
+            counter += 1;
+            generics.push_str(format!("{}", *lifetime));
         }
-        for (i, ty) in last.types.iter().enumerate() {
-            if i > 0 || last.lifetime.is_some() {
-                generics.push_str(", ");
-            }
+        for ty in last.types.iter() {
+            if counter > 0 { generics.push_str(", "); }
+            counter += 1;
             generics.push_str(format!("{}", *ty));
         }
         generics.push_str("&gt;");
@@ -495,7 +497,7 @@ fn fmt(v: &clean::ViewListIdent, f: &mut fmt::Formatter) {
                     global: false,
                     segments: ~[clean::PathSegment {
                         name: v.name.clone(),
-                        lifetime: None,
+                        lifetimes: ~[],
                         types: ~[],
                     }]
                 };
index 7d10061e812c32bbb30b68adfeb822dd6b4e9efc..90729966c18a64be77025e69ad8826ab5081584c 100644 (file)
@@ -12,7 +12,7 @@
 
 use clone::Clone;
 use container::Container;
-use iter::Iterator;
+use iter::{Iterator, FromIterator};
 use option::{Option, Some, None};
 use mem;
 use unstable::raw::Repr;
@@ -134,6 +134,17 @@ fn clone(&self) -> @[T] {
     }
 }
 
+impl<A> FromIterator<A> for @[A] {
+    fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> @[A] {
+        let (lower, _) = iterator.size_hint();
+        do build(Some(lower)) |push| {
+            for x in *iterator {
+                push(x);
+            }
+        }
+    }
+}
+
 #[cfg(not(test))]
 #[allow(missing_doc)]
 pub mod traits {
index c0c2e2822f1621331d699bb5284b7b0cae19ef6c..6245c61dfa1844fc5673bad1d6a11d0141731118 100644 (file)
@@ -28,7 +28,7 @@
 // table) and a SyntaxContext to track renaming and
 // macro expansion per Flatt et al., "Macros
 // That Work Together"
-#[deriving(Clone, IterBytes, ToStr)]
+#[deriving(Clone, IterBytes, ToStr, TotalEq, TotalOrd)]
 pub struct Ident { name: Name, ctxt: SyntaxContext }
 
 impl Ident {
@@ -110,6 +110,7 @@ pub enum SyntaxContext_ {
 /// A name is a part of an identifier, representing a string or gensym. It's
 /// the result of interning.
 pub type Name = uint;
+
 /// A mark represents a unique id associated with a macro expansion
 pub type Mrk = uint;
 
@@ -156,9 +157,8 @@ pub struct Path {
 pub struct PathSegment {
     /// The identifier portion of this path segment.
     identifier: Ident,
-    /// The lifetime parameter for this path segment. Currently only one
-    /// lifetime parameter is allowed.
-    lifetime: Option<Lifetime>,
+    /// The lifetime parameters for this path segment.
+    lifetimes: OptVec<Lifetime>,
     /// The type parameters for this path segment, if present.
     types: OptVec<Ty>,
 }
@@ -167,7 +167,7 @@ pub struct PathSegment {
 
 pub type NodeId = int;
 
-#[deriving(Clone, Eq, Encodable, Decodable, IterBytes, ToStr)]
+#[deriving(Clone, TotalEq, TotalOrd, Eq, Encodable, Decodable, IterBytes, ToStr)]
 pub struct DefId {
     crate: CrateNum,
     node: NodeId,
index 17613d19c7ef1148c1fb76b0f135538e6ce6c2fd..f3d7ac1804db79f7431369a738f9a919cf6c6e25 100644 (file)
@@ -488,3 +488,15 @@ pub fn node_item_query<Result>(items: map, id: NodeId,
         _ => fail!("{}", error_msg)
     }
 }
+
+pub fn item_span(items: map,
+                 id: ast::NodeId)
+                 -> Span {
+    match items.find(&id) {
+        Some(&node_item(item, _)) => item.span,
+        r => {
+            fail!(format!("item_span: expected item with id {} but found {:?}",
+                           id, r))
+        }
+    }
+}
index 3ec87dbdd26fba67871318acdb821c5071b9e8b7..ccae25dc012ac8866a643cf3850c17a5335e2543 100644 (file)
@@ -225,7 +225,7 @@ pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
         segments: ~[
             ast::PathSegment {
                 identifier: identifier,
-                lifetime: None,
+                lifetimes: opt_vec::Empty,
                 types: opt_vec::Empty,
             }
         ],
@@ -948,7 +948,7 @@ pub fn segments_name_eq(a : &[ast::PathSegment], b : &[ast::PathSegment]) -> boo
         for (idx,seg) in a.iter().enumerate() {
             if (seg.identifier.name != b[idx].identifier.name)
                 // FIXME #7743: ident -> name problems in lifetime comparison?
-                || (seg.lifetime != b[idx].lifetime)
+                || (seg.lifetimes != b[idx].lifetimes)
                 // can types contain idents?
                 || (seg.types != b[idx].types) {
                 return false;
@@ -966,7 +966,9 @@ mod test {
     use std::hashmap::HashMap;
 
     fn ident_to_segment(id : &Ident) -> PathSegment {
-        PathSegment{identifier:id.clone(), lifetime: None, types: opt_vec::Empty}
+        PathSegment {identifier:id.clone(),
+                     lifetimes: opt_vec::Empty,
+                     types: opt_vec::Empty}
     }
 
     #[test] fn idents_name_eq_test() {
index 0a5e20fc2b29a3eae8ab603848dc06f3c655aab4..5ae158045e0e72e289430f48732e84ef8d52a4a1 100644 (file)
@@ -38,7 +38,7 @@ pub trait AstBuilder {
     fn path_all(&self, sp: Span,
                 global: bool,
                 idents: ~[ast::Ident],
-                rp: Option<ast::Lifetime>,
+                lifetimes: OptVec<ast::Lifetime>,
                 types: ~[ast::Ty])
         -> ast::Path;
 
@@ -237,19 +237,19 @@ fn view_use_glob(&self, sp: Span,
 
 impl AstBuilder for @ExtCtxt {
     fn path(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path {
-        self.path_all(span, false, strs, None, ~[])
+        self.path_all(span, false, strs, opt_vec::Empty, ~[])
     }
     fn path_ident(&self, span: Span, id: ast::Ident) -> ast::Path {
         self.path(span, ~[id])
     }
     fn path_global(&self, span: Span, strs: ~[ast::Ident]) -> ast::Path {
-        self.path_all(span, true, strs, None, ~[])
+        self.path_all(span, true, strs, opt_vec::Empty, ~[])
     }
     fn path_all(&self,
                 sp: Span,
                 global: bool,
                 mut idents: ~[ast::Ident],
-                rp: Option<ast::Lifetime>,
+                lifetimes: OptVec<ast::Lifetime>,
                 types: ~[ast::Ty])
                 -> ast::Path {
         let last_identifier = idents.pop();
@@ -257,13 +257,13 @@ fn path_all(&self,
                                                       .map(|ident| {
             ast::PathSegment {
                 identifier: ident,
-                lifetime: None,
+                lifetimes: opt_vec::Empty,
                 types: opt_vec::Empty,
             }
         }).collect();
         segments.push(ast::PathSegment {
             identifier: last_identifier,
-            lifetime: rp,
+            lifetimes: lifetimes,
             types: opt_vec::from(types),
         });
         ast::Path {
@@ -327,7 +327,7 @@ fn ty_option(&self, ty: ast::Ty) -> ast::Ty {
                               self.ident_of("option"),
                               self.ident_of("Option")
                           ],
-                          None,
+                          opt_vec::Empty,
                           ~[ ty ]), None)
     }
 
index 0ca18f1208d0db715df7ebec13569a8c8cbdac93..216bc3097ce9402ef86150ac0f6c3e32a62ea538 100644 (file)
@@ -43,7 +43,7 @@ pub fn expand_syntax_ext(cx: @ExtCtxt, sp: Span, tts: &[ast::token_tree])
                  segments: ~[
                     ast::PathSegment {
                         identifier: res,
-                        lifetime: None,
+                        lifetimes: opt_vec::Empty,
                         types: opt_vec::Empty,
                     }
                 ]
index cfb6048df18f1e5006501d0e9db9704b8d448a3a..b37757341efd8fea67b42cba87e03576afd6b191 100644 (file)
@@ -375,14 +375,10 @@ fn create_derived_impl(&self, cx: @ExtCtxt, trait_span: Span,
             cx.ty_ident(trait_span, ty_param.ident)
         };
 
-        let self_lifetime = if generics.lifetimes.is_empty() {
-            None
-        } else {
-            Some(*generics.lifetimes.get(0))
-        };
+        let self_lifetimes = generics.lifetimes.clone();
 
         // Create the type of `self`.
-        let self_type = cx.ty_path(cx.path_all(trait_span, false, ~[ type_ident ], self_lifetime,
+        let self_type = cx.ty_path(cx.path_all(trait_span, false, ~[ type_ident ], self_lifetimes,
                                                opt_vec::take_vec(self_ty_params)), None);
 
         let doc_attr = cx.attribute(
index 1e2a6fa2eb51b541603f157fb17a58fed5774118..d014816c070c113c202e8f37c2160eeb1967b5da 100644 (file)
@@ -14,6 +14,7 @@
 use ext::base::ExtCtxt;
 use ext::build::{AstBuilder};
 use ext::deriving::generic::*;
+use opt_vec;
 
 pub fn expand_deriving_rand(cx: @ExtCtxt,
                             span: Span,
@@ -77,7 +78,7 @@ fn rand_substructure(cx: @ExtCtxt, span: Span, substr: &Substructure) -> @Expr {
             let rand_name = cx.path_all(span,
                                         true,
                                         rand_ident.clone(),
-                                        None,
+                                        opt_vec::Empty,
                                         ~[]);
             let rand_name = cx.expr_path(rand_name);
 
index c60259304aef23cac3baea73919089ceff543ee4..d1a5af5f7e8911102811fa26ed2c04a0569bd848 100644 (file)
@@ -19,6 +19,7 @@
 use ext::build::AstBuilder;
 use codemap::{Span,respan};
 use opt_vec;
+use opt_vec::OptVec;
 
 /// The types of pointers
 pub enum PtrTy<'self> {
@@ -71,7 +72,7 @@ pub fn to_path(&self,
                    self_generics: &Generics)
                    -> ast::Path {
         let idents = self.path.map(|s| cx.ident_of(*s) );
-        let lt = mk_lifetime(cx, span, &self.lifetime);
+        let lt = mk_lifetimes(cx, span, &self.lifetime);
         let tys = self.params.map(|t| t.to_ty(cx, span, self_ty, self_generics));
 
         cx.path_all(span, self.global, idents, lt, tys)
@@ -116,6 +117,13 @@ fn mk_lifetime(cx: @ExtCtxt, span: Span, lt: &Option<&str>) -> Option<ast::Lifet
     }
 }
 
+fn mk_lifetimes(cx: @ExtCtxt, span: Span, lt: &Option<&str>) -> OptVec<ast::Lifetime> {
+    match *lt {
+        Some(ref s) => opt_vec::with(cx.lifetime(span, cx.ident_of(*s))),
+        None => opt_vec::Empty
+    }
+}
+
 impl<'self> Ty<'self> {
     pub fn to_ty(&self,
                  cx: @ExtCtxt,
@@ -166,13 +174,9 @@ pub fn to_path(&self,
                 let self_params = do self_generics.ty_params.map |ty_param| {
                     cx.ty_ident(span, ty_param.ident)
                 };
-                let lifetime = if self_generics.lifetimes.is_empty() {
-                    None
-                } else {
-                    Some(*self_generics.lifetimes.get(0))
-                };
+                let lifetimes = self_generics.lifetimes.clone();
 
-                cx.path_all(span, false, ~[self_ty], lifetime,
+                cx.path_all(span, false, ~[self_ty], lifetimes,
                             opt_vec::take_vec(self_params))
             }
             Literal(ref p) => {
index ba946d5fb1f1d8a48fc8eccf0ff4b02e536f1035..b74349da2a9fa6b80e7e88cb75a26001d38d2115 100644 (file)
@@ -169,7 +169,7 @@ fn mk_simple_path(ident: ast::Ident, span: Span) -> ast::Path {
                     segments: ~[
                         ast::PathSegment {
                             identifier: ident,
-                            lifetime: None,
+                            lifetimes: opt_vec::Empty,
                             types: opt_vec::Empty,
                         }
                     ],
@@ -628,7 +628,7 @@ fn visit_pat(&mut self, pattern: @ast::Pat, _: ()) {
                         segments: [
                             ast::PathSegment {
                                 identifier: id,
-                                lifetime: _,
+                                lifetimes: _,
                                 types: _
                             }
                         ]
index 943279d2dc6831ae76661d001ba72158b8221a5c..00919fce5db6cf79ddf1451630c24dc0e757113f 100644 (file)
@@ -15,7 +15,7 @@
 use ext::build::AstBuilder;
 use rsparse = parse;
 use parse::token;
-
+use opt_vec;
 use std::fmt::parse;
 use std::hashmap::{HashMap, HashSet};
 use std::vec;
@@ -464,7 +464,7 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> @ast::Expr {
                 sp,
                 true,
                 rtpath("Method"),
-                Some(life),
+                opt_vec::with(life),
                 ~[]
             ), None);
             let st = ast::item_static(ty, ast::MutImmutable, method);
@@ -582,7 +582,8 @@ fn to_expr(&self, extra: @ast::Expr) -> @ast::Expr {
                     self.ecx.ident_of("rt"),
                     self.ecx.ident_of("Piece"),
                 ],
-                Some(self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("static"))),
+                opt_vec::with(
+                    self.ecx.lifetime(self.fmtsp, self.ecx.ident_of("static"))),
                 ~[]
             ), None);
         let ty = ast::ty_fixed_length_vec(
index 388de29b45680c3fe470deeb67c9a84a695c9091..ea0ab95a45105358ce4aa269870049cdab3c8c2d 100644 (file)
@@ -144,7 +144,7 @@ fn fold_method(&self, m: @method) -> @method {
             ident: self.fold_ident(m.ident),
             attrs: m.attrs.map(|a| fold_attribute_(*a, self)),
             generics: fold_generics(&m.generics, self),
-            explicit_self: m.explicit_self,
+            explicit_self: self.fold_explicit_self(&m.explicit_self),
             purity: m.purity,
             decl: fold_fn_decl(&m.decl, self),
             body: self.fold_block(&m.body),
@@ -245,12 +245,14 @@ fn fold_ty(&self, t: &Ty) -> Ty {
             ty_uniq(ref mt) => ty_uniq(fold_mt(mt, self)),
             ty_vec(ref mt) => ty_vec(fold_mt(mt, self)),
             ty_ptr(ref mt) => ty_ptr(fold_mt(mt, self)),
-            ty_rptr(region, ref mt) => ty_rptr(region, fold_mt(mt, self)),
+            ty_rptr(ref region, ref mt) => {
+                ty_rptr(fold_opt_lifetime(region, self), fold_mt(mt, self))
+            }
             ty_closure(ref f) => {
                 ty_closure(@TyClosure {
                     sigil: f.sigil,
                     purity: f.purity,
-                    region: f.region,
+                    region: fold_opt_lifetime(&f.region, self),
                     onceness: f.onceness,
                     bounds: fold_opt_bounds(&f.bounds, self),
                     decl: fold_fn_decl(&f.decl, self),
@@ -349,7 +351,7 @@ fn fold_path(&self, p: &Path) -> Path {
             global: p.global,
             segments: p.segments.map(|segment| ast::PathSegment {
                 identifier: self.fold_ident(segment.identifier),
-                lifetime: segment.lifetime,
+                lifetimes: segment.lifetimes.map(|l| fold_lifetime(l, self)),
                 types: segment.types.map(|typ| self.fold_ty(typ)),
             })
         }
@@ -389,6 +391,24 @@ fn new_id(&self, i: NodeId) -> NodeId {
     fn new_span(&self, sp: Span) -> Span {
         sp
     }
+
+    fn fold_explicit_self(&self, es: &explicit_self) -> explicit_self {
+        Spanned {
+            span: self.new_span(es.span),
+            node: self.fold_explicit_self_(&es.node)
+        }
+    }
+
+    fn fold_explicit_self_(&self, es: &explicit_self_) -> explicit_self_ {
+        match *es {
+            sty_static | sty_value(_) | sty_uniq(_) | sty_box(_) => {
+                *es
+            }
+            sty_region(ref lifetime, m) => {
+                sty_region(fold_opt_lifetime(lifetime, self), m)
+            }
+        }
+    }
 }
 
 /* some little folds that probably aren't useful to have in ast_fold itself*/
@@ -505,6 +525,11 @@ pub fn fold_lifetimes<T:ast_fold>(lts: &OptVec<Lifetime>, fld: &T)
     lts.map(|l| fold_lifetime(l, fld))
 }
 
+pub fn fold_opt_lifetime<T:ast_fold>(o_lt: &Option<Lifetime>, fld: &T)
+                                     -> Option<Lifetime> {
+    o_lt.as_ref().map(|lt| fold_lifetime(lt, fld))
+}
+
 pub fn fold_generics<T:ast_fold>(generics: &Generics, fld: &T) -> Generics {
     Generics {ty_params: fold_ty_params(&generics.ty_params, fld),
               lifetimes: fold_lifetimes(&generics.lifetimes, fld)}
@@ -675,7 +700,7 @@ pub fn noop_fold_type_method<T:ast_fold>(m: &TypeMethod, fld: &T)
         purity: m.purity,
         decl: fold_fn_decl(&m.decl, fld),
         generics: fold_generics(&m.generics, fld),
-        explicit_self: m.explicit_self,
+        explicit_self: fld.fold_explicit_self(&m.explicit_self),
         id: fld.new_id(m.id),
         span: fld.new_span(m.span),
     }
index 2000d0b97461f8b8f150a38cb6d02b8b566ff8de..4d39d4df72f5363123e9c302e6d3b4bcbfb5c2d7 100644 (file)
@@ -165,3 +165,13 @@ fn size_hint(&self) -> (uint, Option<uint>) {
         }
     }
 }
+
+impl<A> FromIterator<A> for OptVec<A> {
+    fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> OptVec<A> {
+        let mut r = Empty;
+        for x in *iterator {
+            r.push(x);
+        }
+        r
+    }
+}
index 6c81784b5dee48e09154ff74dc6049809261b853..672865aadcc2672123a45a47375f9b079b945bab 100644 (file)
@@ -368,7 +368,7 @@ fn sp (a: uint, b: uint) -> Span {
                         segments: ~[
                             ast::PathSegment {
                                 identifier: str_to_ident("a"),
-                                lifetime: None,
+                                lifetimes: opt_vec::Empty,
                                 types: opt_vec::Empty,
                             }
                         ],
@@ -387,12 +387,12 @@ fn sp (a: uint, b: uint) -> Span {
                             segments: ~[
                                 ast::PathSegment {
                                     identifier: str_to_ident("a"),
-                                    lifetime: None,
+                                    lifetimes: opt_vec::Empty,
                                     types: opt_vec::Empty,
                                 },
                                 ast::PathSegment {
                                     identifier: str_to_ident("b"),
-                                    lifetime: None,
+                                    lifetimes: opt_vec::Empty,
                                     types: opt_vec::Empty,
                                 }
                             ]
@@ -592,7 +592,7 @@ fn sp (a: uint, b: uint) -> Span {
                             segments: ~[
                                 ast::PathSegment {
                                     identifier: str_to_ident("d"),
-                                    lifetime: None,
+                                    lifetimes: opt_vec::Empty,
                                     types: opt_vec::Empty,
                                 }
                             ],
@@ -614,7 +614,7 @@ fn sp (a: uint, b: uint) -> Span {
                                segments: ~[
                                 ast::PathSegment {
                                     identifier: str_to_ident("b"),
-                                    lifetime: None,
+                                    lifetimes: opt_vec::Empty,
                                     types: opt_vec::Empty,
                                 }
                                ],
@@ -641,7 +641,7 @@ fn parser_done(p: Parser){
                                     segments: ~[
                                         ast::PathSegment {
                                             identifier: str_to_ident("b"),
-                                            lifetime: None,
+                                            lifetimes: opt_vec::Empty,
                                             types: opt_vec::Empty,
                                         }
                                     ],
@@ -669,7 +669,7 @@ fn parser_done(p: Parser){
                                             ast::PathSegment {
                                                 identifier:
                                                     str_to_ident("int"),
-                                                lifetime: None,
+                                                lifetimes: opt_vec::Empty,
                                                 types: opt_vec::Empty,
                                             }
                                         ],
@@ -687,7 +687,7 @@ fn parser_done(p: Parser){
                                                     ast::PathSegment {
                                                         identifier:
                                                             str_to_ident("b"),
-                                                        lifetime: None,
+                                                        lifetimes: opt_vec::Empty,
                                                         types: opt_vec::Empty,
                                                     }
                                                 ],
@@ -724,8 +724,8 @@ fn parser_done(p: Parser){
                                                                 identifier:
                                                                 str_to_ident(
                                                                     "b"),
-                                                                lifetime:
-                                                                    None,
+                                                                lifetimes:
+                                                                opt_vec::Empty,
                                                                 types:
                                                                 opt_vec::Empty
                                                             }
index 7c98d8d1c85b344db905e616f2ef218032048cad..cfb4da87720becaf97ca6bb29c68df389faf7491 100644 (file)
@@ -1490,7 +1490,7 @@ pub fn parse_path(&self, mode: PathParsingMode) -> PathAndBounds {
                 segments.push(PathSegmentAndBoundSet {
                     segment: ast::PathSegment {
                         identifier: identifier,
-                        lifetime: None,
+                        lifetimes: opt_vec::Empty,
                         types: opt_vec::Empty,
                     },
                     bound_set: bound_set
@@ -1499,46 +1499,21 @@ pub fn parse_path(&self, mode: PathParsingMode) -> PathAndBounds {
             }
 
             // Parse the `<` before the lifetime and types, if applicable.
-            let (any_lifetime_or_types, optional_lifetime, types) =
-                    if mode != NoTypesAllowed && self.eat(&token::LT) {
-                // Parse an optional lifetime.
-                let optional_lifetime = match *self.token {
-                    token::LIFETIME(*) => Some(self.parse_lifetime()),
-                    _ => None,
-                };
-
-                // Parse type parameters.
-                let mut types = opt_vec::Empty;
-                let mut need_comma = optional_lifetime.is_some();
-                loop {
-                    // We're done if we see a `>`.
-                    match *self.token {
-                        token::GT | token::BINOP(token::SHR) => {
-                            self.expect_gt();
-                            break
-                        }
-                        _ => {} // Go on.
-                    }
-
-                    if need_comma {
-                        self.expect(&token::COMMA)
-                    } else {
-                        need_comma = true
-                    }
-
-                    types.push(self.parse_ty(false))
+            let (any_lifetime_or_types, lifetimes, types) = {
+                if mode != NoTypesAllowed && self.eat(&token::LT) {
+                    let (lifetimes, types) =
+                        self.parse_generic_values_after_lt();
+                    (true, lifetimes, opt_vec::from(types))
+                } else {
+                    (false, opt_vec::Empty, opt_vec::Empty)
                 }
-
-                (true, optional_lifetime, types)
-            } else {
-                (false, None, opt_vec::Empty)
             };
 
             // Assemble and push the result.
             segments.push(PathSegmentAndBoundSet {
                 segment: ast::PathSegment {
                     identifier: identifier,
-                    lifetime: optional_lifetime,
+                    lifetimes: lifetimes,
                     types: types,
                 },
                 bound_set: bound_set
@@ -1609,11 +1584,11 @@ pub fn parse_opt_lifetime(&self) -> Option<ast::Lifetime> {
     pub fn parse_lifetime(&self) -> ast::Lifetime {
         match *self.token {
             token::LIFETIME(i) => {
-                let span = self.span;
+                let span = *self.span;
                 self.bump();
                 return ast::Lifetime {
                     id: ast::DUMMY_NODE_ID,
-                    span: *span,
+                    span: span,
                     ident: i
                 };
             }
@@ -4856,7 +4831,7 @@ fn parse_view_path(&self) -> @view_path {
                 segments: path.move_iter().map(|identifier| {
                     ast::PathSegment {
                         identifier: identifier,
-                        lifetime: None,
+                        lifetimes: opt_vec::Empty,
                         types: opt_vec::Empty,
                     }
                 }).collect()
@@ -4892,7 +4867,7 @@ fn parse_view_path(&self) -> @view_path {
                         segments: path.move_iter().map(|identifier| {
                             ast::PathSegment {
                                 identifier: identifier,
-                                lifetime: None,
+                                lifetimes: opt_vec::Empty,
                                 types: opt_vec::Empty,
                             }
                         }).collect()
@@ -4910,7 +4885,7 @@ fn parse_view_path(&self) -> @view_path {
                         segments: path.move_iter().map(|identifier| {
                             ast::PathSegment {
                                 identifier: identifier,
-                                lifetime: None,
+                                lifetimes: opt_vec::Empty,
                                 types: opt_vec::Empty,
                             }
                         }).collect()
@@ -4932,7 +4907,7 @@ fn parse_view_path(&self) -> @view_path {
             segments: path.move_iter().map(|identifier| {
                 ast::PathSegment {
                     identifier: identifier,
-                    lifetime: None,
+                    lifetimes: opt_vec::Empty,
                     types: opt_vec::Empty,
                 }
             }).collect()
index 08c2ae88e4fabbf14966ff947bd6423bea63b150..fd02ac68f4e1a039665baae7ff3e38dc0d6dfb46 100644 (file)
@@ -1566,13 +1566,13 @@ fn print_path_(s: @ps,
             }
         }
 
-        if segment.lifetime.is_some() || !segment.types.is_empty() {
+        if !segment.lifetimes.is_empty() || !segment.types.is_empty() {
             if colons_before_params {
                 word(s.s, "::")
             }
             word(s.s, "<");
 
-            for lifetime in segment.lifetime.iter() {
+            for lifetime in segment.lifetimes.iter() {
                 print_lifetime(s, lifetime);
                 if !segment.types.is_empty() {
                     word_space(s, ",")
@@ -1905,7 +1905,8 @@ pub fn print_meta_item(s: @ps, item: &ast::MetaItem) {
 pub fn print_view_path(s: @ps, vp: &ast::view_path) {
     match vp.node {
       ast::view_path_simple(ident, ref path, _) => {
-        if path.segments.last().identifier != ident {
+            // FIXME can't compare identifiers directly here
+        if path.segments.last().identifier.name != ident.name {
             print_ident(s, ident);
             space(s.s);
             word_space(s, "=");