Export information about used default methods instead of regenerating it. Closes #7862.

This commit is contained in:
Michael Sullivan 2013-07-11 17:07:57 -07:00
parent 8e714fa8d8
commit 002bfd7966
5 changed files with 82 additions and 20 deletions

View file

@ -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
)
}

View file

@ -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) => {

View file

@ -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);
self.add_trait_impl(trait_ref.def_id, implementation);
}
implementation = @Impl {
methods: methods,
..*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

View file

@ -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
}

View file

@ -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);
}