Skip to content

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 #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

+24-11
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

+9-4
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
"##,
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() {}
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+
}
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)