]> git.lizzy.rs Git - rust.git/commitdiff
Better detection of duplicate associated items.
authorNick Hamann <nick@wabbo.org>
Wed, 3 Jun 2015 05:47:41 +0000 (00:47 -0500)
committerNick Hamann <nick@wabbo.org>
Wed, 15 Jul 2015 18:32:29 +0000 (13:32 -0500)
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.

src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/test/compile-fail/associated-item-duplicate-names-2.rs [new file with mode: 0644]
src/test/compile-fail/associated-item-duplicate-names-3.rs [new file with mode: 0644]
src/test/compile-fail/associated-item-duplicate-names.rs [new file with mode: 0644]

index aabd33d9c1d3a76d84dfd7ef59c00708798abef2..82449296eae1ec924ab7e7acf3e386767eca3ca5 100644 (file)
@@ -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);
index d89174295a8927db8c9f8db4f416a59863b9145d..c9ff6e36e66ed6af0601f51f1773fce8e3f87dda 100644 (file)
@@ -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 @@ unsafe impl Bar for Foo { }
 
 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 (file)
index 0000000..6a7eaec
--- /dev/null
@@ -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 (file)
index 0000000..7c4c5ca
--- /dev/null
@@ -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 (file)
index 0000000..4c484b4
--- /dev/null
@@ -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;
+}