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?
This commit is contained in:
commit
24e85ac82d
@ -374,50 +374,90 @@ fn encode_path_elt(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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
//
|
||||
// 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 item itself.
|
||||
//
|
||||
// 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
@ -307,6 +307,9 @@ struct ctxt_ {
|
||||
// Maps a trait onto a mapping from self-ty to impl
|
||||
trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>,
|
||||
|
||||
// Maps a base type to its impl
|
||||
base_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
|
||||
|
||||
// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
|
||||
// present in this set can be warned about.
|
||||
used_unsafe: @mut HashSet<ast::node_id>,
|
||||
@ -972,6 +975,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(),
|
||||
}
|
||||
@ -3700,6 +3704,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,
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -313,6 +313,7 @@ pub fn check_implementation(&self,
|
||||
implementation = existing_implementation;
|
||||
}
|
||||
}
|
||||
|
||||
self.add_inherent_method(base_type_def_id,
|
||||
implementation);
|
||||
}
|
||||
@ -434,6 +435,8 @@ pub fn add_inherent_method(&self,
|
||||
}
|
||||
|
||||
implementation_list.push(implementation);
|
||||
|
||||
ty::add_base_impl(self.crate_context.tcx, base_def_id, implementation);
|
||||
}
|
||||
|
||||
pub fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) {
|
||||
|
@ -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 @@ impl Foo for int {
|
||||
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()"
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user