From cb7ebd10a25b7a81468cbbf6b07bfb3386ad8507 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 15 Nov 2012 16:36:16 -0800 Subject: [PATCH] Check for duplicate supertraits and forbid them As per #3953 --- src/librustc/middle/typeck/collect.rs | 16 +++++++++++++--- src/test/compile-fail/issue-3953.rs | 23 +++++++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/issue-3953.rs diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs index 4faf34b3078ce..064fd6b8bf311 100644 --- a/src/librustc/middle/typeck/collect.rs +++ b/src/librustc/middle/typeck/collect.rs @@ -254,16 +254,26 @@ fn ensure_trait_methods(ccx: @crate_ctxt, id: ast::node_id, trait_ty: ty::t) { fn ensure_supertraits(ccx: @crate_ctxt, id: ast::node_id, + sp: codemap::span, rp: Option, trait_refs: &[@ast::trait_ref]) { - if ccx.tcx.supertraits.contains_key(local_def(id)) { return; } + let tcx = ccx.tcx; + if tcx.supertraits.contains_key(local_def(id)) { return; } let instantiated = dvec::DVec(); for trait_refs.each |trait_ref| { let (did, tpt) = instantiate_trait_ref(ccx, *trait_ref, rp); + if instantiated.any(|other_trait: &InstantiatedTraitRef| + { (*other_trait).def_id == did }) { + // This means a trait inherited from the same supertrait more + // than once. + tcx.sess.span_err(sp, ~"Duplicate supertrait in trait \ + declaration"); + return; + } instantiated.push(InstantiatedTraitRef { def_id: did, tpt: tpt }); } - ccx.tcx.supertraits.insert(local_def(id), + tcx.supertraits.insert(local_def(id), @dvec::unwrap(move instantiated)); } @@ -538,7 +548,7 @@ fn convert(ccx: @crate_ctxt, it: @ast::item) { it.id, ty_to_str(tcx, tpt.ty)); write_ty_to_tcx(tcx, it.id, tpt.ty); ensure_trait_methods(ccx, it.id, tpt.ty); - ensure_supertraits(ccx, it.id, rp, supertraits); + ensure_supertraits(ccx, it.id, it.span, rp, supertraits); let (_, provided_methods) = split_trait_methods(trait_methods); let {bounds, _} = mk_substs(ccx, tps, rp); diff --git a/src/test/compile-fail/issue-3953.rs b/src/test/compile-fail/issue-3953.rs new file mode 100644 index 0000000000000..45fa00bd672bf --- /dev/null +++ b/src/test/compile-fail/issue-3953.rs @@ -0,0 +1,23 @@ +use cmp::Eq; + +trait Hahaha: Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, //~ ERROR Duplicate supertrait in trait declaration + Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, + Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, + Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, + Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, + Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq, Eq {} + +enum Lol = int; + +pub impl Lol: Hahaha { + pure fn eq(other: &Lol) -> bool { *self != **other } + pure fn ne(other: &Lol) -> bool { *self == **other } +} + +fn main() { + if Lol(2) == Lol(4) { + io::println("2 == 4"); + } else { + io::println("2 != 4"); + } +} \ No newline at end of file