Skip to content

Commit 2b93ab5

Browse files
committed
rustc: Make static methods not leak out of traits. r=brson
1 parent a0fda80 commit 2b93ab5

File tree

2 files changed

+87
-15
lines changed

2 files changed

+87
-15
lines changed

src/librustc/middle/resolve.rs

Lines changed: 62 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1299,29 +1299,76 @@ impl Resolver {
12991299
let (name_bindings, new_parent) =
13001300
self.add_child(ident, parent, ForbidDuplicateTypes, sp);
13011301

1302+
// If the trait has static methods, then add all the static
1303+
// methods within to a new module.
1304+
//
1305+
// We only need to create the module if the trait has static
1306+
// methods, so check that first.
1307+
let mut has_static_methods = false;
1308+
for methods.each |method| {
1309+
let ty_m = trait_method_to_ty_method(*method);
1310+
match ty_m.self_ty.node {
1311+
sty_static => {
1312+
has_static_methods = true;
1313+
break;
1314+
}
1315+
_ => {}
1316+
}
1317+
}
1318+
1319+
// Create the module if necessary.
1320+
let module_parent_opt;
1321+
if has_static_methods {
1322+
let parent_link = self.get_parent_link(parent, ident);
1323+
name_bindings.define_module(privacy,
1324+
parent_link,
1325+
Some(local_def(item.id)),
1326+
false,
1327+
sp);
1328+
module_parent_opt = Some(ModuleReducedGraphParent(
1329+
name_bindings.get_module()));
1330+
} else {
1331+
module_parent_opt = None;
1332+
}
1333+
13021334
// Add the names of all the methods to the trait info.
13031335
let method_names = @HashMap();
13041336
for methods.each |method| {
13051337
let ty_m = trait_method_to_ty_method(*method);
13061338

13071339
let ident = ty_m.ident;
13081340
// Add it to the trait info if not static,
1309-
// add it as a name in the enclosing module otherwise.
1341+
// add it as a name in the trait module otherwise.
13101342
match ty_m.self_ty.node {
1311-
sty_static => {
1312-
// which parent to use??
1313-
let (method_name_bindings, _) =
1314-
self.add_child(ident, new_parent,
1315-
ForbidDuplicateValues, ty_m.span);
1316-
let def = def_static_method(local_def(ty_m.id),
1317-
Some(local_def(item.id)),
1318-
ty_m.purity);
1319-
(*method_name_bindings).define_value
1320-
(Public, def, ty_m.span);
1321-
}
1322-
_ => {
1323-
(*method_names).insert(ident, ());
1324-
}
1343+
sty_static => {
1344+
let def = def_static_method(
1345+
local_def(ty_m.id),
1346+
Some(local_def(item.id)),
1347+
ty_m.purity);
1348+
1349+
// For now, add to both the trait module and the
1350+
// enclosing module, for backwards compatibility.
1351+
let (method_name_bindings, _) =
1352+
self.add_child(ident,
1353+
new_parent,
1354+
ForbidDuplicateValues,
1355+
ty_m.span);
1356+
method_name_bindings.define_value(Public,
1357+
def,
1358+
ty_m.span);
1359+
1360+
let (method_name_bindings, _) =
1361+
self.add_child(ident,
1362+
module_parent_opt.get(),
1363+
ForbidDuplicateValues,
1364+
ty_m.span);
1365+
method_name_bindings.define_value(Public,
1366+
def,
1367+
ty_m.span);
1368+
}
1369+
_ => {
1370+
method_names.insert(ident, ());
1371+
}
13251372
}
13261373
}
13271374

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
mod a {
2+
pub trait Foo {
3+
static pub fn foo() -> self;
4+
}
5+
6+
impl int : Foo {
7+
static pub fn foo() -> int {
8+
3
9+
}
10+
}
11+
12+
impl uint : Foo {
13+
static pub fn foo() -> uint {
14+
5u
15+
}
16+
}
17+
}
18+
19+
fn main() {
20+
let x: int = a::Foo::foo();
21+
let y: uint = a::Foo::foo();
22+
assert x == 3;
23+
assert y == 5;
24+
}
25+

0 commit comments

Comments
 (0)