about summary refs log tree commit diff
path: root/src/rustc/metadata
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2012-07-31 16:32:37 -0700
committerPatrick Walton <pcwalton@mimiga.net>2012-07-31 16:35:11 -0700
commit2cfe8fb357f8ad7e99dc03b09e0ec5fa1c2c9029 (patch)
tree56af8b2f6feb43d3393caf47bcebaa8399712257 /src/rustc/metadata
parent567f881fdf4053d4890929eb4cd46c67c4a011ee (diff)
downloadrust-2cfe8fb357f8ad7e99dc03b09e0ec5fa1c2c9029.tar.gz
rust-2cfe8fb357f8ad7e99dc03b09e0ec5fa1c2c9029.zip
rustc: Check self types in method lookup; allow required trait methods to have self types; write self types into metadata
Diffstat (limited to 'src/rustc/metadata')
-rw-r--r--src/rustc/metadata/common.rs2
-rw-r--r--src/rustc/metadata/decoder.rs57
-rw-r--r--src/rustc/metadata/encoder.rs57
3 files changed, 113 insertions, 3 deletions
diff --git a/src/rustc/metadata/common.rs b/src/rustc/metadata/common.rs
index e7ef25a04d5..946f3c764fa 100644
--- a/src/rustc/metadata/common.rs
+++ b/src/rustc/metadata/common.rs
@@ -97,6 +97,8 @@ const tag_mod_impl_trait: uint = 0x47u;
 const tag_item_impl_method: uint = 0x48u;
 const tag_item_dtor: uint = 0x49u;
 const tag_paths_foreign_path: uint = 0x4a;
+const tag_item_trait_method_self_ty: uint = 0x4b;
+const tag_item_trait_method_self_ty_region: uint = 0x4c;
 
 // used to encode crate_ctxt side tables
 enum astencode_tag { // Reserves 0x50 -- 0x6f
diff --git a/src/rustc/metadata/decoder.rs b/src/rustc/metadata/decoder.rs
index ba5ff3a6a9d..37da481a82d 100644
--- a/src/rustc/metadata/decoder.rs
+++ b/src/rustc/metadata/decoder.rs
@@ -565,19 +565,70 @@ fn get_enum_variants(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
 }
 
 // NB: These types are duplicated in resolve.rs
-type method_info = {did: ast::def_id, n_tps: uint, ident: ast::ident};
+type method_info = {
+    did: ast::def_id,
+    n_tps: uint,
+    ident: ast::ident,
+    self_type: ast::self_ty_
+};
+
 type _impl = {did: ast::def_id, ident: ast::ident, methods: ~[@method_info]};
 
+fn get_self_ty(item: ebml::doc) -> ast::self_ty_ {
+    fn get_mutability(ch: u8) -> ast::mutability {
+        alt ch as char {
+            'i' => { ast::m_imm }
+            'm' => { ast::m_mutbl }
+            'c' => { ast::m_const }
+            _ => {
+                fail fmt!{"unknown mutability character: `%c`", ch as char}
+            }
+        }
+    }
+
+    let self_type_doc = ebml::get_doc(item, tag_item_trait_method_self_ty);
+    let string = ebml::doc_as_str(self_type_doc);
+
+    let self_ty_kind = string[0];
+    alt self_ty_kind as char {
+        'r' => { ret ast::sty_by_ref; }
+        'v' => { ret ast::sty_value; }
+        '@' => { ret ast::sty_box(get_mutability(string[1])); }
+        '~' => { ret ast::sty_uniq(get_mutability(string[1])); }
+        '&' => {
+            let mutability = get_mutability(string[1]);
+
+            let region;
+            let region_doc =
+                ebml::get_doc(self_type_doc,
+                              tag_item_trait_method_self_ty_region);
+            let region_string = str::from_bytes(ebml::doc_data(region_doc));
+            if str::eq(region_string, ~"") {
+                region = ast::re_anon;
+            } else {
+                region = ast::re_named(@region_string);
+            }
+
+            ret ast::sty_region(@{ id: 0, node: region }, mutability);
+        }
+        _ => {
+            fail fmt!{"unknown self type code: `%c`", self_ty_kind as char};
+        }
+    }
+}
+
 fn item_impl_methods(cdata: cmd, item: ebml::doc, base_tps: uint)
     -> ~[@method_info] {
     let mut rslt = ~[];
     for ebml::tagged_docs(item, tag_item_impl_method) |doc| {
         let m_did = ebml::with_doc_data(doc, |d| parse_def_id(d));
         let mth_item = lookup_item(m_did.node, cdata.data);
+        let self_ty = get_self_ty(mth_item);
         vec::push(rslt, @{did: translate_def_id(cdata, m_did),
                     /* FIXME (maybe #2323) tjc: take a look at this. */
                    n_tps: item_ty_param_count(mth_item) - base_tps,
-                   ident: item_name(mth_item)});
+                   ident: item_name(mth_item),
+                   self_type: self_ty});
     }
     rslt
 }
@@ -628,7 +679,9 @@ fn get_trait_methods(cdata: cmd, id: ast::node_id, tcx: ty::ctxt)
             tcx.diag.handler().bug(
                 ~"get_trait_methods: id has non-function type");
         } };
+        let self_ty = get_self_ty(mth);
         vec::push(result, {ident: name, tps: bounds, fty: fty,
+                    self_ty: self_ty,
                     purity: alt check item_family(mth) {
                       'u' { ast::unsafe_fn }
                       'f' { ast::impure_fn }
diff --git a/src/rustc/metadata/encoder.rs b/src/rustc/metadata/encoder.rs
index ee4a8bdd63f..49096e1fdf8 100644
--- a/src/rustc/metadata/encoder.rs
+++ b/src/rustc/metadata/encoder.rs
@@ -438,6 +438,58 @@ fn encode_visibility(ebml_w: ebml::writer, visibility: visibility) {
     });
 }
 
+fn encode_region(ebml_w: ebml::writer, region: region) {
+    alt region.node {
+        re_anon => {
+            ebml_w.wr_tagged_str(tag_item_trait_method_self_ty, ~"");
+        }
+        re_named(ident) => {
+            ebml_w.wr_tagged_str(tag_item_trait_method_self_ty, *ident);
+        }
+    }
+}
+
+fn encode_self_type(ebml_w: ebml::writer, self_type: ast::self_ty_) {
+    ebml_w.start_tag(tag_item_trait_method_self_ty);
+
+    // Encode the base self type.
+    let ch;
+    alt self_type {
+        sty_by_ref =>       { ch = 'r' as u8; }
+        sty_value =>        { ch = 'v' as u8; }
+        sty_region(_, _) => { ch = '&' as u8; }
+        sty_box(_) =>       { ch = '@' as u8; }
+        sty_uniq(_) =>      { ch = '~' as u8; }
+    }
+    ebml_w.writer.write(&[ ch ]);
+
+    // Encode mutability.
+    alt self_type {
+        sty_by_ref | sty_value => { /* No-op. */ }
+        sty_region(_, m_imm) | sty_box(m_imm) | sty_uniq(m_imm) => {
+            ebml_w.writer.write(&[ 'i' as u8 ]);
+        }
+        sty_region(_, m_mutbl) | sty_box(m_mutbl) | sty_uniq(m_mutbl) => {
+            ebml_w.writer.write(&[ 'm' as u8 ]);
+        }
+        sty_region(_, m_const) | sty_box(m_const) | sty_uniq(m_const) => {
+            ebml_w.writer.write(&[ 'c' as u8 ]);
+        }
+    }
+
+    // Encode the region.
+    alt self_type {
+        sty_region(region, _) => {
+            encode_region(ebml_w, *region);
+        }
+        sty_by_ref | sty_value | sty_box(*) | sty_uniq(*) => {
+            // Nothing to do.
+        }
+    }
+
+    ebml_w.end_tag();
+}
+
 /* Returns an index of items in this class */
 fn encode_info_for_class(ecx: @encode_ctxt, ebml_w: ebml::writer,
                          id: node_id, path: ast_map::path,
@@ -523,6 +575,7 @@ fn encode_info_for_method(ecx: @encode_ctxt, ebml_w: ebml::writer,
     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
     encode_name(ebml_w, m.ident);
     encode_path(ebml_w, impl_path, ast_map::path_name(m.ident));
+    encode_self_type(ebml_w, m.self_ty.node);
     if all_tps.len() > 0u || should_inline {
         ecx.encode_inlined_item(
            ecx, ebml_w, impl_path,
@@ -712,9 +765,10 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                 encode_type_param_bounds(ebml_w, ecx, m.tps);
                 encode_type(ecx, ebml_w, node_id_to_type(tcx, m.id));
                 encode_def_id(ebml_w, local_def(m.id));
+                encode_self_type(ebml_w, m.self_ty.node);
                 ebml_w.end_tag();
                 /* Write the info that's needed when viewing this class
-                   as an impl (just the method def_id) */
+                   as an impl (just the method def_id and self type) */
                 ebml_w.start_tag(tag_item_impl_method);
                 ebml_w.writer.write(str::bytes(def_to_str(local_def(m.id))));
                 ebml_w.end_tag();
@@ -778,6 +832,7 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: ebml::writer, item: @item,
                 encode_type_param_bounds(ebml_w, ecx, ty_m.tps);
                 encode_type(ecx, ebml_w, ty::mk_fn(tcx, mty.fty));
                 encode_family(ebml_w, purity_fn_family(mty.purity));
+                encode_self_type(ebml_w, mty.self_ty);
                 ebml_w.end_tag();
               }
               provided(m) {