Skip to content

Commit 24e85ac

Browse files
committed
auto merge of #6880 : thomaslee/rust/issue-6745, r=catamorphism
This fixes #6745, which itself relates to #4202. Slightly ham-fisted -- feel particularly funny about using the typeck phase to gather the base -> impl mapping, and the separate code paths for traits vs. "real" bases feels like it could be avoided -- but it seems to work. As always, open to suggestions if there's a better way to accomplish what I'm trying to do. @catamorphism r?
2 parents c35b7b5 + 4246694 commit 24e85ac

File tree

5 files changed

+123
-35
lines changed

5 files changed

+123
-35
lines changed

src/librustc/metadata/encoder.rs

+70-30
Original file line numberDiff line numberDiff line change
@@ -374,50 +374,90 @@ fn encode_path(ecx: @EncodeContext,
374374
fn encode_reexported_static_method(ecx: @EncodeContext,
375375
ebml_w: &mut writer::Encoder,
376376
exp: &middle::resolve::Export2,
377-
m: @ty::Method) {
378-
debug!("(encode static trait method) reexport '%s::%s'",
379-
*exp.name, *ecx.tcx.sess.str_of(m.ident));
377+
method_def_id: def_id,
378+
method_ident: ident) {
379+
debug!("(encode reexported static method) %s::%s",
380+
*exp.name, *ecx.tcx.sess.str_of(method_ident));
380381
ebml_w.start_tag(tag_items_data_item_reexport);
381382
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
382-
ebml_w.wr_str(def_to_str(m.def_id));
383+
ebml_w.wr_str(def_to_str(method_def_id));
383384
ebml_w.end_tag();
384385
ebml_w.start_tag(tag_items_data_item_reexport_name);
385-
ebml_w.wr_str(*exp.name + "::" + *ecx.tcx.sess.str_of(m.ident));
386+
ebml_w.wr_str(*exp.name + "::" + *ecx.tcx.sess.str_of(method_ident));
386387
ebml_w.end_tag();
387388
ebml_w.end_tag();
388389
}
389390

391+
fn encode_reexported_static_base_methods(ecx: @EncodeContext,
392+
ebml_w: &mut writer::Encoder,
393+
exp: &middle::resolve::Export2)
394+
-> bool {
395+
match ecx.tcx.base_impls.find(&exp.def_id) {
396+
Some(implementations) => {
397+
for implementations.each |&base_impl| {
398+
for base_impl.methods.each |&m| {
399+
if m.explicit_self == ast::sty_static {
400+
encode_reexported_static_method(ecx, ebml_w, exp,
401+
m.did, m.ident);
402+
}
403+
}
404+
}
405+
406+
true
407+
}
408+
None => { false }
409+
}
410+
}
411+
412+
fn encode_reexported_static_trait_methods(ecx: @EncodeContext,
413+
ebml_w: &mut writer::Encoder,
414+
exp: &middle::resolve::Export2)
415+
-> bool {
416+
match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
417+
Some(methods) => {
418+
for methods.each |&m| {
419+
if m.explicit_self == ast::sty_static {
420+
encode_reexported_static_method(ecx, ebml_w, exp,
421+
m.def_id, m.ident);
422+
}
423+
}
424+
425+
true
426+
}
427+
None => { false }
428+
}
429+
}
430+
390431
fn encode_reexported_static_methods(ecx: @EncodeContext,
391432
ebml_w: &mut writer::Encoder,
392433
mod_path: &[ast_map::path_elt],
393434
exp: &middle::resolve::Export2) {
394-
match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
395-
Some(methods) => {
396-
match ecx.tcx.items.find(&exp.def_id.node) {
397-
Some(&ast_map::node_item(item, path)) => {
398-
let original_name = ecx.tcx.sess.str_of(item.ident);
399-
400-
//
401-
// We don't need to reexport static methods on traits
402-
// declared in the same module as our `pub use ...` since
403-
// that's done when we encode the trait item.
404-
//
405-
// The only exception is when the reexport *changes* the
406-
// name e.g. `pub use Foo = self::Bar` -- we have
407-
// encoded metadata for static methods relative to Bar,
408-
// but not yet for Foo.
409-
//
410-
if mod_path != *path || *exp.name != *original_name {
411-
for methods.each |&m| {
412-
if m.explicit_self == ast::sty_static {
413-
encode_reexported_static_method(ecx,
414-
ebml_w,
415-
exp, m);
416-
}
417-
}
435+
match ecx.tcx.items.find(&exp.def_id.node) {
436+
Some(&ast_map::node_item(item, path)) => {
437+
let original_name = ecx.tcx.sess.str_of(item.ident);
438+
439+
//
440+
// We don't need to reexport static methods on items
441+
// declared in the same module as our `pub use ...` since
442+
// that's done when we encode the item itself.
443+
//
444+
// The only exception is when the reexport *changes* the
445+
// name e.g. `pub use Foo = self::Bar` -- we have
446+
// encoded metadata for static methods relative to Bar,
447+
// but not yet for Foo.
448+
//
449+
if mod_path != *path || *exp.name != *original_name {
450+
if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
451+
if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
452+
debug!(fmt!("(encode reexported static methods) %s \
453+
[trait]",
454+
*original_name));
418455
}
419456
}
420-
_ => {}
457+
else {
458+
debug!(fmt!("(encode reexported static methods) %s [base]",
459+
*original_name));
460+
}
421461
}
422462
}
423463
_ => {}

src/librustc/middle/ty.rs

+19
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,9 @@ struct ctxt_ {
307307
// Maps a trait onto a mapping from self-ty to impl
308308
trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>,
309309

310+
// Maps a base type to its impl
311+
base_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
312+
310313
// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
311314
// present in this set can be warned about.
312315
used_unsafe: @mut HashSet<ast::node_id>,
@@ -972,6 +975,7 @@ pub fn mk_ctxt(s: session::Session,
972975
destructor_for_type: @mut HashMap::new(),
973976
destructors: @mut HashSet::new(),
974977
trait_impls: @mut HashMap::new(),
978+
base_impls: @mut HashMap::new(),
975979
used_unsafe: @mut HashSet::new(),
976980
used_mut_nodes: @mut HashSet::new(),
977981
}
@@ -3700,6 +3704,21 @@ pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method {
37003704
ty::method(cx, method_def_id)
37013705
}
37023706

3707+
3708+
pub fn add_base_impl(cx: ctxt, base_def_id: def_id, implementation: @Impl) {
3709+
let implementations;
3710+
match cx.base_impls.find(&base_def_id) {
3711+
None => {
3712+
implementations = @mut ~[];
3713+
cx.base_impls.insert(base_def_id, implementations);
3714+
}
3715+
Some(&existing) => {
3716+
implementations = existing;
3717+
}
3718+
}
3719+
implementations.push(implementation);
3720+
}
3721+
37033722
pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] {
37043723
match cx.trait_methods_cache.find(&trait_did) {
37053724
Some(&methods) => methods,

src/librustc/middle/typeck/coherence.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt,
146146
}
147147
_ => {
148148
fail!("get_base_type() returned a type that wasn't an \
149-
enum, class, or trait");
149+
enum, struct, or trait");
150150
}
151151
}
152152
}
@@ -313,6 +313,7 @@ impl CoherenceChecker {
313313
implementation = existing_implementation;
314314
}
315315
}
316+
316317
self.add_inherent_method(base_type_def_id,
317318
implementation);
318319
}
@@ -434,6 +435,8 @@ impl CoherenceChecker {
434435
}
435436

436437
implementation_list.push(implementation);
438+
439+
ty::add_base_impl(self.crate_context.tcx, base_def_id, implementation);
437440
}
438441

439442
pub fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) {

src/test/auxiliary/mod_trait_with_static_methods_lib.rs renamed to src/test/auxiliary/reexported_static_methods.rs

+22
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
pub use sub_foo::Foo;
1212
pub use Baz = self::Bar;
13+
pub use sub_foo::Boz;
14+
pub use sub_foo::Bort;
1315

1416
pub trait Bar {
1517
pub fn bar() -> Self;
@@ -28,4 +30,24 @@ pub mod sub_foo {
2830
pub fn foo() -> int { 42 }
2931
}
3032

33+
pub struct Boz {
34+
unused_str: ~str
35+
}
36+
37+
pub impl Boz {
38+
pub fn boz(i: int) -> bool {
39+
i > 0
40+
}
41+
}
42+
43+
pub enum Bort {
44+
Bort1,
45+
Bort2
46+
}
47+
48+
pub impl Bort {
49+
pub fn bort() -> ~str {
50+
~"bort()"
51+
}
52+
}
3153
}

src/test/run-pass/trait_with_static_methods_cross_crate.rs renamed to src/test/run-pass/reexported-static-methods-cross-crate.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,17 @@
99
// except according to those terms.
1010

1111
// xfail-fast
12-
// aux-build:mod_trait_with_static_methods_lib.rs
13-
extern mod mod_trait_with_static_methods_lib;
12+
// aux-build:reexported_static_methods.rs
13+
extern mod reexported_static_methods;
1414

15-
use mod_trait_with_static_methods_lib::Foo;
16-
use mod_trait_with_static_methods_lib::Baz;
15+
use reexported_static_methods::Foo;
16+
use reexported_static_methods::Baz;
17+
use reexported_static_methods::Boz;
18+
use reexported_static_methods::Bort;
1719

1820
pub fn main() {
1921
assert_eq!(42, Foo::foo());
2022
assert_eq!(84, Baz::bar());
23+
assert!(Boz::boz(1));
24+
assert_eq!(~"bort()", Bort::bort());
2125
}

0 commit comments

Comments
 (0)