Skip to content

Commit

Permalink
rustc_resolve: Do not allow mods to shadow types
Browse files Browse the repository at this point in the history
This commit modifies resolve to prevent conflicts with typedef names in the same
method that conflits are prevented with enum names. This is a breaking change
due to the differing semantics in resolve, and any errors generated on behalf of
this change require that a conflicting typedef, module, or structure to be
renamed so they do not conflict.

[breaking-change]
Closes rust-lang#6936
  • Loading branch information
alexcrichton committed Jan 19, 2015
1 parent 46366fa commit 2549cbe
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 16 deletions.
41 changes: 25 additions & 16 deletions src/librustc_resolve/build_reduced_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -321,9 +321,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
// These items live in the type namespace.
ItemTy(..) => {
let name_bindings =
self.add_child(name, parent, ForbidDuplicateTypesAndModules, sp);
self.add_child(name, parent, ForbidDuplicateTypesAndModules,
sp);

name_bindings.define_type(DefTy(local_def(item.id), false), sp, modifiers);
name_bindings.define_type(DefTy(local_def(item.id), false), sp,
modifiers);

let parent_link = self.get_parent_link(parent, name);
name_bindings.set_module_kind(parent_link,
Some(local_def(item.id)),
TypeModuleKind,
false,
is_public,
sp);
parent.clone()
}

Expand Down Expand Up @@ -423,21 +433,19 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
return parent.clone();
}
};

// Create the module and add all methods.
let parent_opt = parent.children.borrow().get(&mod_name).cloned();
let new_parent = match parent_opt {
let child_opt = parent.children.borrow().get(&mod_name)
.and_then(|m| m.get_module_if_available());
let new_parent = match child_opt {
// It already exists
Some(ref child) if child.get_module_if_available()
.is_some() &&
(child.get_module().kind.get() == ImplModuleKind ||
child.get_module().kind.get() == TraitModuleKind) => {
child.get_module()
}
Some(ref child) if child.get_module_if_available()
.is_some() &&
child.get_module().kind.get() ==
EnumModuleKind => child.get_module(),
Some(ref child) if (child.kind.get() == ImplModuleKind ||
child.kind.get() == TraitModuleKind) => {
child.clone()
}
Some(ref child) if child.kind.get() == EnumModuleKind ||
child.kind.get() == TypeModuleKind => {
child.clone()
}
// Create the module
_ => {
let name_bindings =
Expand Down Expand Up @@ -859,7 +867,8 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {

let kind = match def {
DefTy(_, true) => EnumModuleKind,
DefStruct(..) | DefTy(..) => ImplModuleKind,
DefTy(_, false) => TypeModuleKind,
DefStruct(..) => ImplModuleKind,
_ => NormalModuleKind
};

Expand Down
4 changes: 4 additions & 0 deletions src/librustc_resolve/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ enum ModuleKind {
TraitModuleKind,
ImplModuleKind,
EnumModuleKind,
TypeModuleKind,
AnonymousModuleKind,
}

Expand Down Expand Up @@ -2240,6 +2241,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => {
search_module = parent_module_node.upgrade().unwrap();
}
Expand Down Expand Up @@ -2337,6 +2339,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => module_ = new_module,
}
}
Expand All @@ -2353,6 +2356,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => {
match self.get_nearest_normal_module_parent(module_.clone()) {
None => module_,
Expand Down
44 changes: 44 additions & 0 deletions src/test/compile-fail/issue-6936.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

struct T;

mod t1 {
type Foo = ::T;
mod Foo {} //~ ERROR: duplicate definition of type or module `Foo`
}

mod t2 {
type Foo = ::T;
struct Foo; //~ ERROR: duplicate definition of type or module `Foo`
}

mod t3 {
type Foo = ::T;
enum Foo {} //~ ERROR: duplicate definition of type or module `Foo`
}

mod t4 {
type Foo = ::T;
fn Foo() {} // ok
}

mod t5 {
type Bar<T> = T;
mod Bar {} //~ ERROR: duplicate definition of type or module `Bar`
}

mod t6 {
type Foo = ::T;
impl Foo {} // ok
}


fn main() {}

0 comments on commit 2549cbe

Please sign in to comment.