Skip to content

Commit e7d98d5

Browse files
committed
Check duplicated paramter bounds, refs rust-lang#2687
1 parent d9346d8 commit e7d98d5

File tree

4 files changed

+53
-8
lines changed

4 files changed

+53
-8
lines changed

src/librustc/middle/lint.rs

+8
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ pub enum Lint {
102102
DeadCode,
103103
VisiblePrivateTypes,
104104
UnnecessaryTypecast,
105+
DuplicatedTypeBound,
105106

106107
MissingDoc,
107108
UnreachableCode,
@@ -304,6 +305,13 @@ static lint_table: &'static [(&'static str, LintSpec)] = &[
304305
default: allow,
305306
}),
306307

308+
("duplicated_type_bound",
309+
LintSpec {
310+
lint: DuplicatedTypeBound,
311+
desc: "detects duplicated type bound",
312+
default: warn
313+
}),
314+
307315
("unused_mut",
308316
LintSpec {
309317
lint: UnusedMut,

src/librustc/middle/typeck/collect.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ are represented as `ty_param()` instances.
3333

3434
use metadata::csearch;
3535
use middle::resolve_lifetime;
36+
use middle::lint::DuplicatedTypeBound;
3637
use middle::ty::{ImplContainer, MethodContainer, TraitContainer, substs};
3738
use middle::ty::{ty_param_bounds_and_ty};
3839
use middle::ty;
@@ -45,6 +46,8 @@ use middle::typeck::{CrateCtxt, lookup_def_tcx, no_params, write_ty_to_tcx};
4546
use util::ppaux;
4647
use util::ppaux::Repr;
4748

49+
use collections::HashSet;
50+
4851
use std::rc::Rc;
4952
use std::vec_ng::Vec;
5053
use std::vec_ng;
@@ -1029,20 +1032,21 @@ pub fn ty_generics(ccx: &CrateCtxt,
10291032
builtin_bounds: ty::EmptyBuiltinBounds(),
10301033
trait_bounds: Vec::new()
10311034
};
1035+
1036+
let mut added_bounds = HashSet::new();
10321037
for ast_bound in ast_bounds.iter() {
10331038
match *ast_bound {
10341039
TraitTyParamBound(ref b) => {
10351040
let ty = ty::mk_param(ccx.tcx, param_ty.idx, param_ty.def_id);
10361041
let trait_ref = instantiate_trait_ref(ccx, b, ty);
1037-
if added_bounds.contains_key(&trait_ref.def_id) {
1038-
ccx.tcx.sess.span_warn(
1042+
if !added_bounds.insert(trait_ref.def_id) {
1043+
ccx.tcx.sess.add_lint(
1044+
DuplicatedTypeBound,
1045+
0,
10391046
b.path.span,
10401047
format!("duplicated bound `{}`, ignoring it",
10411048
trait_ref.repr(ccx.tcx)));
10421049
continue;
1043-
1044-
} else {
1045-
added_bounds.insert(trait_ref.def_id, ());
10461050
}
10471051

10481052
if !ty::try_add_builtin_trait(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2014 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+
// Tests contravariant type parameters in implementations of traits, see #2687
12+
13+
#[deny(duplicated_type_bound)];
14+
15+
trait A {}
16+
17+
trait Foo {
18+
fn test_duplicated_builtin_bounds_fn<T: Eq+Ord+Eq>(&self);
19+
//~^ ERROR duplicated bound `std::cmp::Eq`, ignoring it
20+
21+
fn test_duplicated_user_bounds_fn<T: A+A>(&self);
22+
//~^ ERROR duplicated bound `A`, ignoring it
23+
}
24+
25+
impl Foo for int {
26+
fn test_duplicated_builtin_bounds_fn<T: Eq+Ord+Eq+Eq>(&self) {}
27+
//~^ ERROR duplicated bound `std::cmp::Eq`, ignoring it
28+
//~^^ ERROR duplicated bound `std::cmp::Eq`, ignoring it
29+
30+
fn test_duplicated_user_bounds_fn<T: A+A+A+A>(&self) {}
31+
//~^ ERROR duplicated bound `A`, ignoring it
32+
//~^^ ERROR duplicated bound `A`, ignoring it
33+
//~^^^ ERROR duplicated bound `A`, ignoring it
34+
}
35+
36+
fn main() {}

src/test/run-pass/typeck-contravariant-trait-bounds-impl.rs

-3
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ impl B for u32 {
3939
trait Foo {
4040
fn test_fn<T: B>(&self, x: T) -> int;
4141
fn test_duplicated_bounds1_fn<T: B+B>(&self) -> int;
42-
//~^ warn: duplicated bound `B`, ignoring it
4342
fn test_duplicated_bounds2_fn<T: B>(&self) -> int;
4443
}
4544

@@ -49,12 +48,10 @@ impl Foo for int {
4948
}
5049

5150
fn test_duplicated_bounds1_fn<T: B+B>(&self) -> int {
52-
//~^ warn: duplicated bound `B`, ignoring it
5351
99
5452
}
5553

5654
fn test_duplicated_bounds2_fn<T: B+B>(&self) -> int {
57-
//~^ warn: duplicated bound `B`, ignoring it
5855
199
5956
}
6057
}

0 commit comments

Comments
 (0)