Skip to content

Commit 2f83baf

Browse files
committed
Check for duplicate supertraits and forbid them
As per #3953
1 parent 82017b8 commit 2f83baf

File tree

2 files changed

+36
-3
lines changed

2 files changed

+36
-3
lines changed

src/librustc/middle/typeck/collect.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -254,16 +254,26 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) {
254254

255255
fn ensure_supertraits(ccx: @crate_ctxt,
256256
id: ast::node_id,
257+
sp: codemap::span,
257258
rp: Option<ty::region_variance>,
258259
trait_refs: &[@ast::trait_ref]) {
259-
if ccx.tcx.supertraits.contains_key(local_def(id)) { return; }
260+
let tcx = ccx.tcx;
261+
if tcx.supertraits.contains_key(local_def(id)) { return; }
260262

261263
let instantiated = dvec::DVec();
262264
for trait_refs.each |trait_ref| {
263265
let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp);
266+
if instantiated.any(|other_trait: &InstantiatedTraitRef|
267+
{ (*other_trait).def_id == did }) {
268+
// This means a trait inherited from the same supertrait more
269+
// than once.
270+
tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \
271+
declaration");
272+
return;
273+
}
264274
instantiated.push(InstantiatedTraitRef { def_id: did, tpt: tpt });
265275
}
266-
ccx.tcx.supertraits.insert(local_def(id),
276+
tcx.supertraits.insert(local_def(id),
267277
@dvec::unwrap(move instantiated));
268278
}
269279

@@ -551,7 +561,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) {
551561
it.id, ty_to_str(tcx, tpt.ty));
552562
write_ty_to_tcx(tcx, it.id, tpt.ty);
553563
ensure_trait_methods(ccx, it.id, tpt.ty);
554-
ensure_supertraits(ccx, it.id, rp, supertraits);
564+
ensure_supertraits(ccx, it.id, it.span, rp, supertraits);
555565
556566
let (_, provided_methods) = split_trait_methods(trait_methods);
557567
let {bounds, _} = mk_substs(ccx, tps, rp);

src/test/compile-fail/issue-3953.rs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use cmp::Eq;
2+
3+
trait Hahaha: Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, //~ ERROR Duplicate supertrait in trait declaration
4+
Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq,
5+
Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq,
6+
Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq,
7+
Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq,
8+
Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq {}
9+
10+
enum Lol = int;
11+
12+
pub impl Lol: Hahaha {
13+
pure fn eq(other: &Lol) -> bool { *self != **other }
14+
pure fn ne(other: &Lol) -> bool { *self == **other }
15+
}
16+
17+
fn main() {
18+
if Lol(2) == Lol(4) {
19+
io::println("2 == 4");
20+
} else {
21+
io::println("2 != 4");
22+
}
23+
}

0 commit comments

Comments
 (0)