about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNick Hamann <nick@wabbo.org>2015-06-03 00:47:41 -0500
committerNick Hamann <nick@wabbo.org>2015-07-15 13:32:29 -0500
commit560bb0af6d0dda06b856a80cc5095b7d552b8406 (patch)
tree94462b67ad88771977ff2399eba8307cf3ae1844 /src
parent906ad724620e1ff93082b364a38761940a7abdcf (diff)
downloadrust-560bb0af6d0dda06b856a80cc5095b7d552b8406.tar.gz
rust-560bb0af6d0dda06b856a80cc5095b7d552b8406.zip
Better detection of duplicate associated items.
Expands E0201 to be used for any duplicate associated items, not just duplicate
methods/functions. It also correctly detects when two different kinds of items
(like a constant and a method) have the same name.

Fixes #23969.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_typeck/collect.rs35
-rw-r--r--src/librustc_typeck/diagnostics.rs13
-rw-r--r--src/test/compile-fail/associated-item-duplicate-names-2.rs20
-rw-r--r--src/test/compile-fail/associated-item-duplicate-names-3.rs28
-rw-r--r--src/test/compile-fail/associated-item-duplicate-names.rs30
5 files changed, 111 insertions, 15 deletions
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index aabd33d9c1d..82449296eae 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -748,17 +748,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
            rcvr_ty_generics.repr(ccx.tcx),
            rcvr_ty_predicates.repr(ccx.tcx));
 
-    let tcx = ccx.tcx;
-    let mut seen_methods = FnvHashSet();
-    for (sig, id, ident, vis, span) in methods {
-        if !seen_methods.insert(ident.name) {
-            let fn_desc = match sig.explicit_self.node {
-                ast::SelfStatic => "associated function",
-                _               => "method",
-            };
-            span_err!(tcx.sess, span, E0201, "duplicate {}", fn_desc);
-        }
-
+    for (sig, id, ident, vis, _span) in methods {
         convert_method(ccx,
                        container,
                        sig,
@@ -860,7 +850,30 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             };
 
             // Convert all the associated consts.
+            // Also, check if there are any duplicate associated items
+            let mut seen_type_items = FnvHashSet();
+            let mut seen_value_items = FnvHashSet();
+
             for impl_item in impl_items {
+                let seen_items = match impl_item.node {
+                    ast::TypeImplItem(_) => &mut seen_type_items,
+                    _                    => &mut seen_value_items,
+                };
+                if !seen_items.insert(impl_item.ident.name) {
+                    let desc = match impl_item.node {
+                        ast::ConstImplItem(_, _) => "associated constant",
+                        ast::TypeImplItem(_) => "associated type",
+                        ast::MethodImplItem(ref sig, _) =>
+                            match sig.explicit_self.node {
+                                ast::SelfStatic => "associated function",
+                                _ => "method",
+                            },
+                        _ => "associated item",
+                    };
+
+                    span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
+                }
+
                 if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
                     let ty = ccx.icx(&ty_predicates)
                                 .to_ty(&ExplicitRscope, &*ty);
diff --git a/src/librustc_typeck/diagnostics.rs b/src/librustc_typeck/diagnostics.rs
index d89174295a8..c9ff6e36e66 100644
--- a/src/librustc_typeck/diagnostics.rs
+++ b/src/librustc_typeck/diagnostics.rs
@@ -1036,7 +1036,8 @@ unsafe impl Bar for Foo { }
 "##,
 
 E0201: r##"
-It is an error to define an associated function more than once.
+It is an error to define two associated items (like methods, associated types,
+associated functions, etc.) with the same identifier.
 
 For example:
 
@@ -1045,20 +1046,24 @@ struct Foo(u8);
 
 impl Foo {
     fn bar(&self) -> bool { self.0 > 5 }
-
-    // error: duplicate associated function
-    fn bar() {}
+    fn bar() {} // error: duplicate associated function
 }
 
 trait Baz {
+    type Quux;
     fn baz(&self) -> bool;
 }
 
 impl Baz for Foo {
+    type Quux = u32;
+
     fn baz(&self) -> bool { true }
 
     // error: duplicate method
     fn baz(&self) -> bool { self.0 > 5 }
+
+    // error: duplicate associated type
+    type Quux = u32;
 }
 ```
 "##,
diff --git a/src/test/compile-fail/associated-item-duplicate-names-2.rs b/src/test/compile-fail/associated-item-duplicate-names-2.rs
new file mode 100644
index 00000000000..6a7eaecae7f
--- /dev/null
+++ b/src/test/compile-fail/associated-item-duplicate-names-2.rs
@@ -0,0 +1,20 @@
+// 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.
+
+#![feature(associated_consts)]
+
+struct Foo;
+
+impl Foo {
+    const bar: bool = true;
+    fn bar() {} //~ ERROR duplicate associated function
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/associated-item-duplicate-names-3.rs b/src/test/compile-fail/associated-item-duplicate-names-3.rs
new file mode 100644
index 00000000000..7c4c5ca6b4e
--- /dev/null
+++ b/src/test/compile-fail/associated-item-duplicate-names-3.rs
@@ -0,0 +1,28 @@
+// 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.
+//
+// Before the introduction of the "duplicate associated type" error, the
+// program below used to result in the "ambiguous associated type" error E0223,
+// which is unexpected.
+
+trait Foo {
+    type Bar;
+}
+
+struct Baz;
+
+impl Foo for Baz {
+    type Bar = i16;
+    type Bar = u16; //~ ERROR duplicate associated type
+}
+
+fn main() {
+    let x: Baz::Bar = 5;
+}
diff --git a/src/test/compile-fail/associated-item-duplicate-names.rs b/src/test/compile-fail/associated-item-duplicate-names.rs
new file mode 100644
index 00000000000..4c484b49024
--- /dev/null
+++ b/src/test/compile-fail/associated-item-duplicate-names.rs
@@ -0,0 +1,30 @@
+// 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.
+
+// Test for issue #23969
+
+#![feature(associated_consts)]
+
+trait Foo {
+    type Ty;
+    const BAR: u32;
+}
+
+impl Foo for () {
+    type Ty = ();
+    type Ty = usize; //~ ERROR duplicate associated type
+    const BAR: u32 = 7;
+    const BAR: u32 = 8; //~ ERROR duplicate associated constant
+}
+
+fn main() {
+    let _: <() as Foo>::Ty = ();
+    let _: u32 = <() as Foo>::BAR;
+}