Skip to content

Commit 002bfd7

Browse files
committed
Export information about used default methods instead of regenerating it. Closes #7862.
1 parent 8e714fa commit 002bfd7

File tree

5 files changed

+82
-20
lines changed

5 files changed

+82
-20
lines changed

src/librustc/metadata/decoder.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,12 @@ fn item_def_id(d: ebml::Doc, cdata: cmd) -> ast::def_id {
185185
return translate_def_id(cdata, reader::with_doc_data(tagdoc, parse_def_id));
186186
}
187187

188+
fn get_provided_source(d: ebml::Doc, cdata: cmd) -> Option<ast::def_id> {
189+
do reader::maybe_get_doc(d, tag_item_method_provided_source).map |doc| {
190+
translate_def_id(cdata, reader::with_doc_data(*doc, parse_def_id))
191+
}
192+
}
193+
188194
fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool {
189195
for reader::tagged_docs(d, tag_items_data_item_reexport) |reexport_doc| {
190196
if !f(reexport_doc) {
@@ -844,6 +850,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
844850
let fty = doc_method_fty(method_doc, tcx, cdata);
845851
let vis = item_visibility(method_doc);
846852
let explicit_self = get_explicit_self(method_doc);
853+
let provided_source = get_provided_source(method_doc, cdata);
847854

848855
ty::Method::new(
849856
name,
@@ -857,7 +864,7 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
857864
vis,
858865
def_id,
859866
container_id,
860-
None
867+
provided_source
861868
)
862869
}
863870

src/librustc/metadata/encoder.rs

+23-5
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,16 @@ fn encode_method_sort(ebml_w: &mut writer::Encoder, sort: char) {
650650
ebml_w.end_tag();
651651
}
652652

653+
fn encode_provided_source(ebml_w: &mut writer::Encoder,
654+
source_opt: Option<def_id>) {
655+
for source_opt.iter().advance |source| {
656+
ebml_w.start_tag(tag_item_method_provided_source);
657+
let s = def_to_str(*source);
658+
ebml_w.writer.write(s.as_bytes());
659+
ebml_w.end_tag();
660+
}
661+
}
662+
653663
/* Returns an index of items in this class */
654664
fn encode_info_for_struct(ecx: &EncodeContext,
655665
ebml_w: &mut writer::Encoder,
@@ -726,6 +736,7 @@ fn encode_method_ty_fields(ecx: &EncodeContext,
726736
}
727737
_ => encode_family(ebml_w, purity_fn_family(purity))
728738
}
739+
encode_provided_source(ebml_w, method_ty.provided_source);
729740
}
730741

731742
fn encode_info_for_method(ecx: &EncodeContext,
@@ -987,7 +998,6 @@ fn encode_info_for_item(ecx: &EncodeContext,
987998
_ => {}
988999
}
9891000
for imp.methods.iter().advance |method| {
990-
if method.provided_source.is_some() { loop; }
9911001
ebml_w.start_tag(tag_item_impl_method);
9921002
let s = def_to_str(method.def_id);
9931003
ebml_w.writer.write(s.as_bytes());
@@ -1005,16 +1015,24 @@ fn encode_info_for_item(ecx: &EncodeContext,
10051015
let mut impl_path = vec::append(~[], path);
10061016
impl_path.push(ast_map::path_name(item.ident));
10071017

1008-
for ast_methods.iter().advance |ast_method| {
1009-
let m = ty::method(ecx.tcx, local_def(ast_method.id));
1018+
// Iterate down the methods, emitting them. We rely on the
1019+
// assumption that all of the actually implemented methods
1020+
// appear first in the impl structure, in the same order they do
1021+
// in the ast. This is a little sketchy.
1022+
let num_implemented_methods = ast_methods.len();
1023+
for imp.methods.iter().enumerate().advance |(i, m)| {
1024+
let ast_method = if i < num_implemented_methods {
1025+
Some(ast_methods[i])
1026+
} else { None };
1027+
10101028
index.push(entry {val: m.def_id.node, pos: ebml_w.writer.tell()});
10111029
encode_info_for_method(ecx,
10121030
ebml_w,
1013-
m,
1031+
*m,
10141032
impl_path,
10151033
false,
10161034
item.id,
1017-
Some(*ast_method));
1035+
ast_method)
10181036
}
10191037
}
10201038
item_trait(_, ref super_traits, ref ms) => {

src/librustc/middle/typeck/coherence.rs

+9-14
Original file line numberDiff line numberDiff line change
@@ -664,7 +664,7 @@ impl CoherenceChecker {
664664
impls_seen: &mut HashSet<def_id>,
665665
impl_def_id: def_id) {
666666
let tcx = self.crate_context.tcx;
667-
let implementation = csearch::get_impl(tcx, impl_def_id);
667+
let implementation = @csearch::get_impl(tcx, impl_def_id);
668668

669669
debug!("coherence: adding impl from external crate: %s",
670670
ty::item_path_str(tcx, implementation.did));
@@ -697,21 +697,16 @@ impl CoherenceChecker {
697697
}
698698

699699
// Record all the trait methods.
700-
let mut implementation = @implementation;
701700
for associated_traits.iter().advance |trait_ref| {
702-
// XXX(sully): We could probably avoid this copy if there are no
703-
// default methods.
704-
let mut methods = implementation.methods.clone();
705-
self.instantiate_default_methods(implementation.did,
706-
*trait_ref,
707-
&mut methods);
708-
709-
implementation = @Impl {
710-
methods: methods,
711-
..*implementation
712-
};
701+
self.add_trait_impl(trait_ref.def_id, implementation);
702+
}
713703

714-
self.add_trait_impl(trait_ref.def_id, implementation);
704+
// For any methods that use a default implementation, add them to
705+
// the map. This is a bit unfortunate.
706+
for implementation.methods.iter().advance |method| {
707+
for method.provided_source.iter().advance |source| {
708+
tcx.provided_method_sources.insert(method.def_id, *source);
709+
}
715710
}
716711

717712
// Add the implementation to the mapping from implementation to base
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// aux-build:trait_default_method_xc_aux.rs
2+
3+
extern mod aux(name = "trait_default_method_xc_aux");
4+
use aux::A;
5+
6+
pub struct a_struct { x: int }
7+
8+
impl A for a_struct {
9+
fn f(&self) -> int { 10 }
10+
}
11+
12+
// This function will need to get inlined, and badness may result.
13+
pub fn welp<A>(x: A) -> A {
14+
let a = a_struct { x: 0 };
15+
a.g();
16+
x
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// xfail-fast
2+
// aux-build:trait_default_method_xc_aux.rs
3+
// aux-build:trait_default_method_xc_aux_2.rs
4+
5+
6+
extern mod aux(name = "trait_default_method_xc_aux");
7+
extern mod aux2(name = "trait_default_method_xc_aux_2");
8+
use aux::A;
9+
use aux2::{a_struct, welp};
10+
11+
12+
fn main () {
13+
14+
let a = a_struct { x: 0 };
15+
let b = a_struct { x: 1 };
16+
17+
assert_eq!(0i.g(), 10);
18+
assert_eq!(a.g(), 10);
19+
assert_eq!(a.h(), 11);
20+
assert_eq!(b.g(), 10);
21+
assert_eq!(b.h(), 11);
22+
assert_eq!(A::lurr(&a, &b), 21);
23+
24+
welp(&0);
25+
}

0 commit comments

Comments
 (0)