Reexport static methods on structs & enums.
This commit is contained in:
parent
2bf053c0a3
commit
f6fa5b91e2
5 changed files with 122 additions and 34 deletions
|
@ -374,50 +374,90 @@ fn encode_path(ecx: @EncodeContext,
|
||||||
fn encode_reexported_static_method(ecx: @EncodeContext,
|
fn encode_reexported_static_method(ecx: @EncodeContext,
|
||||||
ebml_w: &mut writer::Encoder,
|
ebml_w: &mut writer::Encoder,
|
||||||
exp: &middle::resolve::Export2,
|
exp: &middle::resolve::Export2,
|
||||||
m: @ty::Method) {
|
method_def_id: def_id,
|
||||||
debug!("(encode static trait method) reexport '%s::%s'",
|
method_ident: ident) {
|
||||||
*exp.name, *ecx.tcx.sess.str_of(m.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);
|
||||||
ebml_w.start_tag(tag_items_data_item_reexport_def_id);
|
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.end_tag();
|
||||||
ebml_w.start_tag(tag_items_data_item_reexport_name);
|
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();
|
||||||
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,
|
fn encode_reexported_static_methods(ecx: @EncodeContext,
|
||||||
ebml_w: &mut writer::Encoder,
|
ebml_w: &mut writer::Encoder,
|
||||||
mod_path: &[ast_map::path_elt],
|
mod_path: &[ast_map::path_elt],
|
||||||
exp: &middle::resolve::Export2) {
|
exp: &middle::resolve::Export2) {
|
||||||
match ecx.tcx.trait_methods_cache.find(&exp.def_id) {
|
match ecx.tcx.items.find(&exp.def_id.node) {
|
||||||
Some(methods) => {
|
Some(&ast_map::node_item(item, path)) => {
|
||||||
match ecx.tcx.items.find(&exp.def_id.node) {
|
let original_name = ecx.tcx.sess.str_of(item.ident);
|
||||||
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
|
// We don't need to reexport static methods on items
|
||||||
// declared in the same module as our `pub use ...` since
|
// declared in the same module as our `pub use ...` since
|
||||||
// that's done when we encode the trait item.
|
// that's done when we encode the trait item.
|
||||||
//
|
//
|
||||||
// The only exception is when the reexport *changes* the
|
// The only exception is when the reexport *changes* the
|
||||||
// name e.g. `pub use Foo = self::Bar` -- we have
|
// name e.g. `pub use Foo = self::Bar` -- we have
|
||||||
// encoded metadata for static methods relative to Bar,
|
// encoded metadata for static methods relative to Bar,
|
||||||
// but not yet for Foo.
|
// but not yet for Foo.
|
||||||
//
|
//
|
||||||
if mod_path != *path || *exp.name != *original_name {
|
if mod_path != *path || *exp.name != *original_name {
|
||||||
for methods.each |&m| {
|
if !encode_reexported_static_base_methods(ecx, ebml_w, exp) {
|
||||||
if m.explicit_self == ast::sty_static {
|
if encode_reexported_static_trait_methods(ecx, ebml_w, exp) {
|
||||||
encode_reexported_static_method(ecx,
|
debug!(fmt!("(encode reexported static methods) %s \
|
||||||
ebml_w,
|
[trait]",
|
||||||
exp, m);
|
*original_name));
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
else {
|
||||||
|
debug!(fmt!("(encode reexported static methods) %s [base]",
|
||||||
|
*original_name));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -306,6 +306,9 @@ struct ctxt_ {
|
||||||
// Maps a trait onto a mapping from self-ty to impl
|
// Maps a trait onto a mapping from self-ty to impl
|
||||||
trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @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
|
// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
|
||||||
// present in this set can be warned about.
|
// present in this set can be warned about.
|
||||||
used_unsafe: @mut HashSet<ast::node_id>,
|
used_unsafe: @mut HashSet<ast::node_id>,
|
||||||
|
@ -971,6 +974,7 @@ pub fn mk_ctxt(s: session::Session,
|
||||||
destructor_for_type: @mut HashMap::new(),
|
destructor_for_type: @mut HashMap::new(),
|
||||||
destructors: @mut HashSet::new(),
|
destructors: @mut HashSet::new(),
|
||||||
trait_impls: @mut HashMap::new(),
|
trait_impls: @mut HashMap::new(),
|
||||||
|
base_impls: @mut HashMap::new(),
|
||||||
used_unsafe: @mut HashSet::new(),
|
used_unsafe: @mut HashSet::new(),
|
||||||
used_mut_nodes: @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)
|
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] {
|
pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] {
|
||||||
match cx.trait_methods_cache.find(&trait_did) {
|
match cx.trait_methods_cache.find(&trait_did) {
|
||||||
Some(&methods) => methods,
|
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 \
|
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;
|
implementation = existing_implementation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_inherent_method(base_type_def_id,
|
self.add_inherent_method(base_type_def_id,
|
||||||
implementation);
|
implementation);
|
||||||
}
|
}
|
||||||
|
@ -432,6 +433,8 @@ pub impl CoherenceChecker {
|
||||||
}
|
}
|
||||||
|
|
||||||
implementation_list.push(implementation);
|
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) {
|
fn add_trait_method(&self, trait_id: def_id, implementation: @Impl) {
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
|
|
||||||
pub use sub_foo::Foo;
|
pub use sub_foo::Foo;
|
||||||
pub use Baz = self::Bar;
|
pub use Baz = self::Bar;
|
||||||
|
pub use sub_foo::Boz;
|
||||||
|
pub use sub_foo::Bort;
|
||||||
|
|
||||||
pub trait Bar {
|
pub trait Bar {
|
||||||
pub fn bar() -> Self;
|
pub fn bar() -> Self;
|
||||||
|
@ -28,4 +30,24 @@ pub mod sub_foo {
|
||||||
pub fn foo() -> int { 42 }
|
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.
|
// except according to those terms.
|
||||||
|
|
||||||
// xfail-fast
|
// xfail-fast
|
||||||
// aux-build:mod_trait_with_static_methods_lib.rs
|
// aux-build:reexported_static_methods.rs
|
||||||
extern mod mod_trait_with_static_methods_lib;
|
extern mod reexported_static_methods;
|
||||||
|
|
||||||
use mod_trait_with_static_methods_lib::Foo;
|
use reexported_static_methods::Foo;
|
||||||
use mod_trait_with_static_methods_lib::Baz;
|
use reexported_static_methods::Baz;
|
||||||
|
use reexported_static_methods::Boz;
|
||||||
|
use reexported_static_methods::Bort;
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
assert_eq!(42, Foo::foo());
|
assert_eq!(42, Foo::foo());
|
||||||
assert_eq!(84, Baz::bar());
|
assert_eq!(84, Baz::bar());
|
||||||
|
assert!(Boz::boz(1));
|
||||||
|
assert_eq!(~"bort()", Bort::bort());
|
||||||
}
|
}
|
Loading…
Add table
Add a link
Reference in a new issue