Skip to content

Commit

Permalink
Export information about used default methods instead of regenerating…
Browse files Browse the repository at this point in the history
… it. Closes #7862.
  • Loading branch information
msullivan committed Jul 18, 2013
1 parent 8e714fa commit 002bfd7
Show file tree
Hide file tree
Showing 5 changed files with 82 additions and 20 deletions.
9 changes: 8 additions & 1 deletion src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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,
Expand All @@ -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
)
}

Expand Down
28 changes: 23 additions & 5 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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());
Expand All @@ -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) => {
Expand Down
23 changes: 9 additions & 14 deletions src/librustc/middle/typeck/coherence.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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
Expand Down
17 changes: 17 additions & 0 deletions src/test/auxiliary/trait_default_method_xc_aux_2.rs
Original file line number Diff line number Diff line change
@@ -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
}
25 changes: 25 additions & 0 deletions src/test/run-pass/trait-default-method-xc-2.rs
Original file line number Diff line number Diff line change
@@ -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);
}

5 comments on commit 002bfd7

@bors
Copy link
Contributor

@bors bors commented on 002bfd7 Jul 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

saw approval from pcwalton
at msullivan@002bfd7

@bors
Copy link
Contributor

@bors bors commented on 002bfd7 Jul 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

merging msullivan/rust/default-methods = 002bfd7 into auto

@bors
Copy link
Contributor

@bors bors commented on 002bfd7 Jul 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

msullivan/rust/default-methods = 002bfd7 merged ok, testing candidate = 3a1db2d

@bors
Copy link
Contributor

@bors bors commented on 002bfd7 Jul 20, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fast-forwarding master to auto = 3a1db2d

Please sign in to comment.