about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorRamkumar Ramachandra <artagnon@gmail.com>2013-06-23 22:18:43 +0530
committerRamkumar Ramachandra <artagnon@gmail.com>2013-06-25 23:58:48 +0530
commit9f80591d84790a9571707a85cf4bc5d8f6df114d (patch)
treea03261cb60137dcf127e54148616b7137a9e6ca6 /src
parent3b126e4d6dda1eac3881b8ca19772071997a7992 (diff)
resolve: report duplicate module definitions
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>
Diffstat (limited to 'src')
-rw-r--r--src/librustc/middle/resolve.rs38
-rw-r--r--src/test/compile-fail/issue-3099-b.rs2
2 files changed, 27 insertions, 13 deletions
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index 8a08b3419e2..5fb7cc9b9bd 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -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.
@@ -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",
     }
 }
 
@@ -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 => {
@@ -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)));
                         }
                     }
diff --git a/src/test/compile-fail/issue-3099-b.rs b/src/test/compile-fail/issue-3099-b.rs
index 3d22a59d6bd..5502b18f094 100644
--- a/src/test/compile-fail/issue-3099-b.rs
+++ b/src/test/compile-fail/issue-3099-b.rs
@@ -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() {}