Skip to content

Commit

Permalink
resolve: report duplicate module definitions
Browse files Browse the repository at this point in the history
add_child() is responsible for reporting errors about type, value, and
module duplicate definitions.  Although it checks for all three, it uses
namespace_to_str() to convert a Namespace value into a string before
printing an error like:

  error: duplicate definition of type `foo`
                                 ^^^^
  note: first definition of type foo here:
                            ^^^^

Unfortunately, this string can only be one of "type" or
"value" (corresponding to TypeNS and ValueNS respectively), and it
reports duplicate modules as duplicate types.

To alleviate the problem, define a special NamespaceError enum to define
more specialized errors, and use it instead of attempting to reuse the
Namespace enum.

Reported-by: Corey Richardson <corey@octayn.net>
Signed-off-by: Ramkumar Ramachandra <artagnon@gmail.com>
  • Loading branch information
artagnon committed Jun 25, 2013
1 parent 3b126e4 commit 9f80591
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
38 changes: 26 additions & 12 deletions src/librustc/middle/resolve.rs
Expand Up @@ -101,6 +101,14 @@ pub enum Namespace {
ValueNS
}

#[deriving(Eq)]
pub enum NamespaceError {
NoError,
ModuleError,
TypeError,
ValueError
}

/// A NamespaceResult represents the result of resolving an import in
/// a particular namespace. The result is either definitely-resolved,
/// definitely- unresolved, or unknown.
Expand Down Expand Up @@ -759,10 +767,12 @@ pub fn PrimitiveTypeTable() -> PrimitiveTypeTable {
}


pub fn namespace_to_str(ns: Namespace) -> ~str {
pub fn namespace_error_to_str(ns: NamespaceError) -> &'static str {
match ns {
TypeNS => ~"type",
ValueNS => ~"value",
NoError => "",
ModuleError => "module",
TypeError => "type",
ValueError => "value",
}
}

Expand Down Expand Up @@ -993,21 +1003,25 @@ impl Resolver {
// * If no duplicate checking was requested at all, do
// nothing.

let mut is_duplicate = false;
let mut duplicate_type = NoError;
let ns = match duplicate_checking_mode {
ForbidDuplicateModules => {
is_duplicate = child.get_module_if_available().is_some();
if (child.get_module_if_available().is_some()) {
duplicate_type = ModuleError;
}
Some(TypeNS)
}
ForbidDuplicateTypes => {
match child.def_for_namespace(TypeNS) {
Some(def_mod(_)) | None => {}
Some(_) => is_duplicate = true
Some(_) => duplicate_type = TypeError
}
Some(TypeNS)
}
ForbidDuplicateValues => {
is_duplicate = child.defined_in_namespace(ValueNS);
if child.defined_in_namespace(ValueNS) {
duplicate_type = ValueError;
}
Some(ValueNS)
}
ForbidDuplicateTypesAndValues => {
Expand All @@ -1016,31 +1030,31 @@ impl Resolver {
Some(def_mod(_)) | None => {}
Some(_) => {
n = Some(TypeNS);
is_duplicate = true;
duplicate_type = TypeError;
}
};
if child.defined_in_namespace(ValueNS) {
is_duplicate = true;
duplicate_type = ValueError;
n = Some(ValueNS);
}
n
}
OverwriteDuplicates => None
};
if is_duplicate {
if (duplicate_type != NoError) {
// Return an error here by looking up the namespace that
// had the duplicate.
let ns = ns.unwrap();
self.session.span_err(sp,
fmt!("duplicate definition of %s `%s`",
namespace_to_str(ns),
namespace_error_to_str(duplicate_type),
self.session.str_of(name)));
{
let r = child.span_for_namespace(ns);
for r.iter().advance |sp| {
self.session.span_note(*sp,
fmt!("first definition of %s %s here:",
namespace_to_str(ns),
namespace_error_to_str(duplicate_type),
self.session.str_of(name)));
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-3099-b.rs
Expand Up @@ -10,6 +10,6 @@

pub mod a {}

pub mod a {} //~ ERROR duplicate definition of type `a`
pub mod a {} //~ ERROR duplicate definition of module `a`

fn main() {}

0 comments on commit 9f80591

Please sign in to comment.