rustc_resolve: Do not allow mods to shadow types

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 #6936
This commit is contained in:
Alex Crichton 2015-01-16 14:25:45 -08:00
parent 46366faf61
commit 2549cbec9d
3 changed files with 73 additions and 16 deletions

View File

@ -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()
}
@ -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 =
@ -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
};

View File

@ -459,6 +459,7 @@ enum ModuleKind {
TraitModuleKind,
ImplModuleKind,
EnumModuleKind,
TypeModuleKind,
AnonymousModuleKind,
}
@ -2240,6 +2241,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => {
search_module = parent_module_node.upgrade().unwrap();
}
@ -2337,6 +2339,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
TraitModuleKind |
ImplModuleKind |
EnumModuleKind |
TypeModuleKind |
AnonymousModuleKind => module_ = new_module,
}
}
@ -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_,

View File

@ -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() {}