about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Sullivan <sully@msully.net>2013-07-11 17:07:57 -0700
committerMichael Sullivan <sully@msully.net>2013-07-18 13:56:15 -0700
commit002bfd796648547839d0f3740308995b4a926f50 (patch)
tree7246f701fe535ba330867ae9cb25f512c6c04f45
parent8e714fa8d8d02bf6a892a65a7b91c0e352a285fd (diff)
downloadrust-002bfd796648547839d0f3740308995b4a926f50.tar.gz
rust-002bfd796648547839d0f3740308995b4a926f50.zip
Export information about used default methods instead of regenerating it. Closes #7862.
-rw-r--r--src/librustc/metadata/decoder.rs9
-rw-r--r--src/librustc/metadata/encoder.rs28
-rw-r--r--src/librustc/middle/typeck/coherence.rs23
-rw-r--r--src/test/auxiliary/trait_default_method_xc_aux_2.rs17
-rw-r--r--src/test/run-pass/trait-default-method-xc-2.rs25
5 files changed, 82 insertions, 20 deletions
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 6604ef5df34..a77c6c6ab52 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -185,6 +185,12 @@ fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
     return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
 }
 
+fn get_provided_source(d: ebml::Doc, cdata: cmd) -> Option<ast::def_id> {
+    do reader::maybe_get_doc(d, tag_item_method_provided_source).map |doc| {
+        translate_def_id(cdata, reader::with_doc_data(*doc, parse_def_id))
+    }
+}
+
 fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool {
     for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
         if !f(reexport_doc) {
@@ -844,6 +850,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
     let fty = doc_method_fty(method_doc, tcx, cdata);
     let vis = item_visibility(method_doc);
     let explicit_self = get_explicit_self(method_doc);
+    let provided_source = get_provided_source(method_doc, cdata);
 
     ty::Method::new(
         name,
@@ -857,7 +864,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
         vis,
         def_id,
         container_id,
-        None
+        provided_source
     )
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 8fda0fff27d..2ef00a2167f 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -650,6 +650,16 @@ fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
     ebml_w.end_tag();
 }
 
+fn encode_provided_source(ebml_w: &mut writer::Encoder,
+                          source_opt: Option<def_id>) {
+    for source_opt.iter().advance |source| {
+        ebml_w.start_tag(tag_item_method_provided_source);
+        let s = def_to_str(*source);
+        ebml_w.writer.write(s.as_bytes());
+        ebml_w.end_tag();
+    }
+}
+
 /* Returns an index of items in this class */
 fn encode_info_for_struct(ecx: &EncodeContext,
                           ebml_w: &mut writer::Encoder,
@@ -726,6 +736,7 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
         }
         _ => encode_family(ebml_w, purity_fn_family(purity))
     }
+    encode_provided_source(ebml_w, method_ty.provided_source);
 }
 
 fn encode_info_for_method(ecx: &EncodeContext,
@@ -987,7 +998,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
             _ => {}
         }
         for imp.methods.iter().advance |method| {
-            if method.provided_source.is_some() { loop; }
             ebml_w.start_tag(tag_item_impl_method);
             let s = def_to_str(method.def_id);
             ebml_w.writer.write(s.as_bytes());
@@ -1005,16 +1015,24 @@ fn encode_info_for_item(ecx: &EncodeContext,
         let mut impl_path = vec::append(~[], path);
         impl_path.push(ast_map::path_name(item.ident));
 
-        for ast_methods.iter().advance |ast_method| {
-            let m = ty::method(ecx.tcx, local_def(ast_method.id));
+        // Iterate down the methods, emitting them. We rely on the
+        // assumption that all of the actually implemented methods
+        // appear first in the impl structure, in the same order they do
+        // in the ast. This is a little sketchy.
+        let num_implemented_methods = ast_methods.len();
+        for imp.methods.iter().enumerate().advance |(i, m)| {
+            let ast_method = if i < num_implemented_methods {
+                Some(ast_methods[i])
+            } else { None };
+
             index.push(entry {val: m.def_id.node, pos: ebml_w.writer.tell()});
             encode_info_for_method(ecx,
                                    ebml_w,
-                                   m,
+                                   *m,
                                    impl_path,
                                    false,
                                    item.id,
-                                   Some(*ast_method));
+                                   ast_method)
         }
       }
       item_trait(_, ref super_traits, ref ms) => {
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 51b206428e3..c8225365864 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -664,7 +664,7 @@ impl CoherenceChecker {
                              impls_seen: &mut HashSet<def_id>,
                              impl_def_id: def_id) {
         let tcx = self.crate_context.tcx;
-        let implementation = csearch::get_impl(tcx, impl_def_id);
+        let implementation = @csearch::get_impl(tcx, impl_def_id);
 
         debug!("coherence: adding impl from external crate: %s",
                ty::item_path_str(tcx, implementation.did));
@@ -697,21 +697,16 @@ impl CoherenceChecker {
         }
 
         // Record all the trait methods.
-        let mut implementation = @implementation;
         for associated_traits.iter().advance |trait_ref| {
-            // XXX(sully): We could probably avoid this copy if there are no
-            // default methods.
-            let mut methods = implementation.methods.clone();
-            self.instantiate_default_methods(implementation.did,
-                                             *trait_ref,
-                                             &mut methods);
-
-            implementation = @Impl {
-                methods: methods,
-                ..*implementation
-            };
+              self.add_trait_impl(trait_ref.def_id, implementation);
+        }
 
-            self.add_trait_impl(trait_ref.def_id, implementation);
+        // For any methods that use a default implementation, add them to
+        // the map. This is a bit unfortunate.
+        for implementation.methods.iter().advance |method| {
+            for method.provided_source.iter().advance |source| {
+                tcx.provided_method_sources.insert(method.def_id, *source);
+            }
         }
 
         // Add the implementation to the mapping from implementation to base
diff --git a/src/test/auxiliary/trait_default_method_xc_aux_2.rs b/src/test/auxiliary/trait_default_method_xc_aux_2.rs
new file mode 100644
index 00000000000..2d4f539f82b
--- /dev/null
+++ b/src/test/auxiliary/trait_default_method_xc_aux_2.rs
@@ -0,0 +1,17 @@
+// aux-build:trait_default_method_xc_aux.rs
+
+extern mod aux(name = "trait_default_method_xc_aux");
+use aux::A;
+
+pub struct a_struct { x: int }
+
+impl A for a_struct {
+    fn f(&self) -> int { 10 }
+}
+
+// This function will need to get inlined, and badness may result.
+pub fn welp<A>(x: A) -> A {
+    let a = a_struct { x: 0 };
+    a.g();
+    x
+}
diff --git a/src/test/run-pass/trait-default-method-xc-2.rs b/src/test/run-pass/trait-default-method-xc-2.rs
new file mode 100644
index 00000000000..1dad5d23b88
--- /dev/null
+++ b/src/test/run-pass/trait-default-method-xc-2.rs
@@ -0,0 +1,25 @@
+// xfail-fast
+// aux-build:trait_default_method_xc_aux.rs
+// aux-build:trait_default_method_xc_aux_2.rs
+
+
+extern mod aux(name = "trait_default_method_xc_aux");
+extern mod aux2(name = "trait_default_method_xc_aux_2");
+use aux::A;
+use aux2::{a_struct, welp};
+
+
+fn main () {
+
+    let a = a_struct { x: 0 };
+    let b = a_struct { x: 1 };
+
+    assert_eq!(0i.g(), 10);
+    assert_eq!(a.g(), 10);
+    assert_eq!(a.h(), 11);
+    assert_eq!(b.g(), 10);
+    assert_eq!(b.h(), 11);
+    assert_eq!(A::lurr(&a, &b), 21);
+
+    welp(&0);
+}