Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 560bb0a

Browse files
author
Nick Hamann
committed
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 rust-lang#23969.
1 parent 906ad72 commit 560bb0a

File tree

5 files changed

+111
-15
lines changed

5 files changed

+111
-15
lines changed

src/librustc_typeck/collect.rs

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -748,17 +748,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
748748
rcvr_ty_generics.repr(ccx.tcx),
749749
rcvr_ty_predicates.repr(ccx.tcx));
750750

751-
let tcx = ccx.tcx;
752-
let mut seen_methods = FnvHashSet();
753-
for (sig, id, ident, vis, span) in methods {
754-
if !seen_methods.insert(ident.name) {
755-
let fn_desc = match sig.explicit_self.node {
756-
ast::SelfStatic => "associated function",
757-
_ => "method",
758-
};
759-
span_err!(tcx.sess, span, E0201, "duplicate {}", fn_desc);
760-
}
761-
751+
for (sig, id, ident, vis, _span) in methods {
762752
convert_method(ccx,
763753
container,
764754
sig,
@@ -860,7 +850,30 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
860850
};
861851

862852
// Convert all the associated consts.
853+
// Also, check if there are any duplicate associated items
854+
let mut seen_type_items = FnvHashSet();
855+
let mut seen_value_items = FnvHashSet();
856+
863857
for impl_item in impl_items {
858+
let seen_items = match impl_item.node {
859+
ast::TypeImplItem(_) => &mut seen_type_items,
860+
_ => &mut seen_value_items,
861+
};
862+
if !seen_items.insert(impl_item.ident.name) {
863+
let desc = match impl_item.node {
864+
ast::ConstImplItem(_, _) => "associated constant",
865+
ast::TypeImplItem(_) => "associated type",
866+
ast::MethodImplItem(ref sig, _) =>
867+
match sig.explicit_self.node {
868+
ast::SelfStatic => "associated function",
869+
_ => "method",
870+
},
871+
_ => "associated item",
872+
};
873+
874+
span_err!(tcx.sess, impl_item.span, E0201, "duplicate {}", desc);
875+
}
876+
864877
if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
865878
let ty = ccx.icx(&ty_predicates)
866879
.to_ty(&ExplicitRscope, &*ty);

src/librustc_typeck/diagnostics.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,8 @@ unsafe impl Bar for Foo { }
10361036
"##,
10371037

10381038
E0201: r##"
1039-
It is an error to define an associated function more than once.
1039+
It is an error to define two associated items (like methods, associated types,
1040+
associated functions, etc.) with the same identifier.
10401041
10411042
For example:
10421043
@@ -1045,20 +1046,24 @@ struct Foo(u8);
10451046
10461047
impl Foo {
10471048
fn bar(&self) -> bool { self.0 > 5 }
1048-
1049-
// error: duplicate associated function
1050-
fn bar() {}
1049+
fn bar() {} // error: duplicate associated function
10511050
}
10521051
10531052
trait Baz {
1053+
type Quux;
10541054
fn baz(&self) -> bool;
10551055
}
10561056
10571057
impl Baz for Foo {
1058+
type Quux = u32;
1059+
10581060
fn baz(&self) -> bool { true }
10591061
10601062
// error: duplicate method
10611063
fn baz(&self) -> bool { self.0 > 5 }
1064+
1065+
// error: duplicate associated type
1066+
type Quux = u32;
10621067
}
10631068
```
10641069
"##,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(associated_consts)]
12+
13+
struct Foo;
14+
15+
impl Foo {
16+
const bar: bool = true;
17+
fn bar() {} //~ ERROR duplicate associated function
18+
}
19+
20+
fn main() {}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
//
11+
// Before the introduction of the "duplicate associated type" error, the
12+
// program below used to result in the "ambiguous associated type" error E0223,
13+
// which is unexpected.
14+
15+
trait Foo {
16+
type Bar;
17+
}
18+
19+
struct Baz;
20+
21+
impl Foo for Baz {
22+
type Bar = i16;
23+
type Bar = u16; //~ ERROR duplicate associated type
24+
}
25+
26+
fn main() {
27+
let x: Baz::Bar = 5;
28+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test for issue #23969
12+
13+
#![feature(associated_consts)]
14+
15+
trait Foo {
16+
type Ty;
17+
const BAR: u32;
18+
}
19+
20+
impl Foo for () {
21+
type Ty = ();
22+
type Ty = usize; //~ ERROR duplicate associated type
23+
const BAR: u32 = 7;
24+
const BAR: u32 = 8; //~ ERROR duplicate associated constant
25+
}
26+
27+
fn main() {
28+
let _: <() as Foo>::Ty = ();
29+
let _: u32 = <() as Foo>::BAR;
30+
}

0 commit comments

Comments
 (0)