diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index a488d39d18756..eb9d0d0f937e0 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -374,50 +374,90 @@ fn encode_path(ecx: @EncodeContext, fn encode_reexported_static_method(ecx: @EncodeContext, ebml_w: &mut writer::Encoder, exp: &middle::resolve::Export2, - m: @ty::Method) { - debug!("(encode static trait method) reexport '%s::%s'", - *exp.name, *ecx.tcx.sess.str_of(m.ident)); + method_def_id: def_id, + method_ident: ident) { + debug!("(encode reexported static method) %s::%s", + *exp.name, *ecx.tcx.sess.str_of(method_ident)); ebml_w.start_tag(tag_items_data_item_reexport); ebml_w.start_tag(tag_items_data_item_reexport_def_id); - ebml_w.wr_str(def_to_str(m.def_id)); + ebml_w.wr_str(def_to_str(method_def_id)); ebml_w.end_tag(); ebml_w.start_tag(tag_items_data_item_reexport_name); - ebml_w.wr_str(*exp.name + "::" + *ecx.tcx.sess.str_of(m.ident)); + ebml_w.wr_str(*exp.name + "::" + *ecx.tcx.sess.str_of(method_ident)); ebml_w.end_tag(); ebml_w.end_tag(); } +fn encode_reexported_static_base_methods(ecx: @EncodeContext, + ebml_w: &mut writer::Encoder, + exp: &middle::resolve::Export2) + -> bool { + match ecx.tcx.base_impls.find(&exp.def_id) { + Some(implementations) => { + for implementations.each |&base_impl| { + for base_impl.methods.each |&m| { + if m.explicit_self == ast::sty_static { + encode_reexported_static_method(ecx, ebml_w, exp, + m.did, m.ident); + } + } + } + + true + } + None => { false } + } +} + +fn encode_reexported_static_trait_methods(ecx: @EncodeContext, + ebml_w: &mut writer::Encoder, + exp: &middle::resolve::Export2) + -> bool { + match ecx.tcx.trait_methods_cache.find(&exp.def_id) { + Some(methods) => { + for methods.each |&m| { + if m.explicit_self == ast::sty_static { + encode_reexported_static_method(ecx, ebml_w, exp, + m.def_id, m.ident); + } + } + + true + } + None => { false } + } +} + fn encode_reexported_static_methods(ecx: @EncodeContext, ebml_w: &mut writer::Encoder, mod_path: &[ast_map::path_elt], exp: &middle::resolve::Export2) { - match ecx.tcx.trait_methods_cache.find(&exp.def_id) { - Some(methods) => { - match ecx.tcx.items.find(&exp.def_id.node) { - Some(&ast_map::node_item(item, path)) => { - let original_name = ecx.tcx.sess.str_of(item.ident); - - // - // We don't need to reexport static methods on traits - // declared in the same module as our `pub use ...` since - // that's done when we encode the trait item. - // - // The only exception is when the reexport *changes* the - // name e.g. `pub use Foo = self::Bar` -- we have - // encoded metadata for static methods relative to Bar, - // but not yet for Foo. - // - if mod_path != *path || *exp.name != *original_name { - for methods.each |&m| { - if m.explicit_self == ast::sty_static { - encode_reexported_static_method(ecx, - ebml_w, - exp, m); - } - } + match ecx.tcx.items.find(&exp.def_id.node) { + Some(&ast_map::node_item(item, path)) => { + let original_name = ecx.tcx.sess.str_of(item.ident); + + // + // We don't need to reexport static methods on items + // declared in the same module as our `pub use ...` since + // that's done when we encode the trait item. + // + // The only exception is when the reexport *changes* the + // name e.g. `pub use Foo = self::Bar` -- we have + // encoded metadata for static methods relative to Bar, + // but not yet for Foo. + // + if mod_path != *path || *exp.name != *original_name { + if !encode_reexported_static_base_methods(ecx, ebml_w, exp) { + if encode_reexported_static_trait_methods(ecx, ebml_w, exp) { + debug!(fmt!("(encode reexported static methods) %s \ + [trait]", + *original_name)); } } - _ => {} + else { + debug!(fmt!("(encode reexported static methods) %s [base]", + *original_name)); + } } } _ => {} diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 0d180223fefc8..e46a19d88c679 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -306,6 +306,9 @@ struct ctxt_ { // Maps a trait onto a mapping from self-ty to impl trait_impls: @mut HashMap>, + // Maps a base type to its impl + base_impls: @mut HashMap, + // Set of used unsafe nodes (functions or blocks). Unsafe nodes not // present in this set can be warned about. used_unsafe: @mut HashSet, @@ -971,6 +974,7 @@ pub fn mk_ctxt(s: session::Session, destructor_for_type: @mut HashMap::new(), destructors: @mut HashSet::new(), trait_impls: @mut HashMap::new(), + base_impls: @mut HashMap::new(), used_unsafe: @mut HashSet::new(), used_mut_nodes: @mut HashSet::new(), } @@ -3699,6 +3703,21 @@ pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method { ty::method(cx, method_def_id) } + +pub fn add_base_impl(cx: ctxt, base_def_id: def_id, implementation: @Impl) { + let implementations; + match cx.base_impls.find(&base_def_id) { + None => { + implementations = @mut ~[]; + cx.base_impls.insert(base_def_id, implementations); + } + Some(&existing) => { + implementations = existing; + } + } + implementations.push(implementation); +} + pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] { match cx.trait_methods_cache.find(&trait_did) { Some(&methods) => methods, diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs index 3cb028b811e22..01260a097d754 100644 --- a/src/librustc/middle/typeck/coherence.rs +++ b/src/librustc/middle/typeck/coherence.rs @@ -146,7 +146,7 @@ pub fn get_base_type_def_id(inference_context: @mut InferCtxt, } _ => { fail!("get_base_type() returned a type that wasn't an \ - enum, class, or trait"); + enum, struct, or trait"); } } } @@ -312,6 +312,7 @@ pub impl CoherenceChecker { implementation = existing_implementation; } } + self.add_inherent_method(base_type_def_id, implementation); } @@ -432,6 +433,8 @@ pub impl CoherenceChecker { } implementation_list.push(implementation); + + ty::add_base_impl(self.crate_context.tcx, base_def_id, implementation); } fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) { diff --git a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs b/src/test/auxiliary/reexported_static_methods.rs similarity index 69% rename from src/test/auxiliary/mod_trait_with_static_methods_lib.rs rename to src/test/auxiliary/reexported_static_methods.rs index 3591ff7931855..88e746585c923 100644 --- a/src/test/auxiliary/mod_trait_with_static_methods_lib.rs +++ b/src/test/auxiliary/reexported_static_methods.rs @@ -10,6 +10,8 @@ pub use sub_foo::Foo; pub use Baz = self::Bar; +pub use sub_foo::Boz; +pub use sub_foo::Bort; pub trait Bar { pub fn bar() -> Self; @@ -28,4 +30,24 @@ pub mod sub_foo { pub fn foo() -> int { 42 } } + pub struct Boz { + unused_str: ~str + } + + pub impl Boz { + pub fn boz(i: int) -> bool { + i > 0 + } + } + + pub enum Bort { + Bort1, + Bort2 + } + + pub impl Bort { + pub fn bort() -> ~str { + ~"bort()" + } + } } diff --git a/src/test/run-pass/trait_with_static_methods_cross_crate.rs b/src/test/run-pass/reexported-static-methods-cross-crate.rs similarity index 65% rename from src/test/run-pass/trait_with_static_methods_cross_crate.rs rename to src/test/run-pass/reexported-static-methods-cross-crate.rs index 4402881c43ddd..e8e58d78e9515 100644 --- a/src/test/run-pass/trait_with_static_methods_cross_crate.rs +++ b/src/test/run-pass/reexported-static-methods-cross-crate.rs @@ -9,13 +9,17 @@ // except according to those terms. // xfail-fast -// aux-build:mod_trait_with_static_methods_lib.rs -extern mod mod_trait_with_static_methods_lib; +// aux-build:reexported_static_methods.rs +extern mod reexported_static_methods; -use mod_trait_with_static_methods_lib::Foo; -use mod_trait_with_static_methods_lib::Baz; +use reexported_static_methods::Foo; +use reexported_static_methods::Baz; +use reexported_static_methods::Boz; +use reexported_static_methods::Bort; pub fn main() { assert_eq!(42, Foo::foo()); assert_eq!(84, Baz::bar()); + assert!(Boz::boz(1)); + assert_eq!(~"bort()", Bort::bort()); }