rustc: Make static methods not leak out of traits. r=brson

This commit is contained in:
Patrick Walton 2012-11-12 12:15:08 -08:00
parent a0fda80a52
commit 2b93ab5a21
2 changed files with 87 additions and 15 deletions

View File

@ -1299,6 +1299,38 @@ impl Resolver {
let (name_bindings, new_parent) = let (name_bindings, new_parent) =
self.add_child(ident, parent, ForbidDuplicateTypes, sp); self.add_child(ident, parent, ForbidDuplicateTypes, sp);
// If the trait has static methods, then add all the static
// methods within to a new module.
//
// We only need to create the module if the trait has static
// methods, so check that first.
let mut has_static_methods = false;
for methods.each |method| {
let ty_m = trait_method_to_ty_method(*method);
match ty_m.self_ty.node {
sty_static => {
has_static_methods = true;
break;
}
_ => {}
}
}
// Create the module if necessary.
let module_parent_opt;
if has_static_methods {
let parent_link = self.get_parent_link(parent, ident);
name_bindings.define_module(privacy,
parent_link,
Some(local_def(item.id)),
false,
sp);
module_parent_opt = Some(ModuleReducedGraphParent(
name_bindings.get_module()));
} else {
module_parent_opt = None;
}
// Add the names of all the methods to the trait info. // Add the names of all the methods to the trait info.
let method_names = @HashMap(); let method_names = @HashMap();
for methods.each |method| { for methods.each |method| {
@ -1306,21 +1338,36 @@ impl Resolver {
let ident = ty_m.ident; let ident = ty_m.ident;
// Add it to the trait info if not static, // Add it to the trait info if not static,
// add it as a name in the enclosing module otherwise. // add it as a name in the trait module otherwise.
match ty_m.self_ty.node { match ty_m.self_ty.node {
sty_static => { sty_static => {
// which parent to use?? let def = def_static_method(
let (method_name_bindings, _) = local_def(ty_m.id),
self.add_child(ident, new_parent,
ForbidDuplicateValues, ty_m.span);
let def = def_static_method(local_def(ty_m.id),
Some(local_def(item.id)), Some(local_def(item.id)),
ty_m.purity); ty_m.purity);
(*method_name_bindings).define_value
(Public, def, ty_m.span); // For now, add to both the trait module and the
// enclosing module, for backwards compatibility.
let (method_name_bindings, _) =
self.add_child(ident,
new_parent,
ForbidDuplicateValues,
ty_m.span);
method_name_bindings.define_value(Public,
def,
ty_m.span);
let (method_name_bindings, _) =
self.add_child(ident,
module_parent_opt.get(),
ForbidDuplicateValues,
ty_m.span);
method_name_bindings.define_value(Public,
def,
ty_m.span);
} }
_ => { _ => {
(*method_names).insert(ident, ()); method_names.insert(ident, ());
} }
} }
} }

View File

@ -0,0 +1,25 @@
mod a {
pub trait Foo {
static pub fn foo() -> self;
}
impl int : Foo {
static pub fn foo() -> int {
3
}
}
impl uint : Foo {
static pub fn foo() -> uint {
5u
}
}
}
fn main() {
let x: int = a::Foo::foo();
let y: uint = a::Foo::foo();
assert x == 3;
assert y == 5;
}