diff options
| author | F001 <changchun.fan@qq.com> | 2018-05-19 00:17:13 +0800 |
|---|---|---|
| committer | F001 <changchun.fan@qq.com> | 2018-05-20 10:16:33 +0800 |
| commit | 4bb39966a670864de0078cafc1e5b623ca1b2ec3 (patch) | |
| tree | cba862b02742a47ae094a4d4f68bf3ebe9c53d06 | |
| parent | 3ea24915894d49cb93eab52e65f1e4f0baa1bc32 (diff) | |
| download | rust-4bb39966a670864de0078cafc1e5b623ca1b2ec3.tar.gz rust-4bb39966a670864de0078cafc1e5b623ca1b2ec3.zip | |
re-implement
| -rw-r--r-- | src/librustc/lint/builtin.rs | 7 | ||||
| -rw-r--r-- | src/librustc_typeck/astconv.rs | 21 | ||||
| -rw-r--r-- | src/test/ui/lint/issue-50589-multiple-associated-types.rs | 23 | ||||
| -rw-r--r-- | src/test/ui/lint/issue-50589-multiple-associated-types.stderr | 14 |
4 files changed, 61 insertions, 4 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index ac2fa8515bc..1cb00abbb7e 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -279,6 +279,12 @@ declare_lint! { "detects labels that are never used" } +declare_lint! { + pub DUPLICATE_ASSOCIATED_TYPE_BINDING, + Warn, + "warns about duplicate associated type bindings in generics" +} + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. #[derive(Copy, Clone)] @@ -330,6 +336,7 @@ impl LintPass for HardwiredLints { BARE_TRAIT_OBJECT, ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE, UNSTABLE_NAME_COLLISION, + DUPLICATE_ASSOCIATED_TYPE_BINDING, ) } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index c1868467503..091ed0a4b36 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -27,7 +27,7 @@ use rustc_target::spec::abi; use std::slice; use require_c_abi_if_variadic; use util::common::ErrorReported; -use util::nodemap::FxHashSet; +use util::nodemap::{FxHashSet, FxHashMap}; use errors::FatalError; use std::iter; @@ -398,13 +398,24 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { trait_ref.path.segments.last().unwrap()); let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs)); + let mut dup_bindings = FxHashMap::default(); poly_projections.extend(assoc_bindings.iter().filter_map(|binding| { // specify type to assert that error was already reported in Err case: let predicate: Result<_, ErrorReported> = - self.ast_type_binding_to_poly_projection_predicate(trait_ref.ref_id, poly_trait_ref, - binding, speculative); + self.ast_type_binding_to_poly_projection_predicate( + trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings); predicate.ok() // ok to ignore Err() because ErrorReported (see above) })); + for (_id, spans) in dup_bindings { + if spans.len() > 1 { + self.tcx().struct_span_lint_node( + ::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDING, + trait_ref.ref_id, + spans, + "duplicate associated type binding" + ).emit(); + } + } debug!("ast_path_to_poly_trait_ref({:?}, projections={:?}) -> {:?}", trait_ref, poly_projections, poly_trait_ref); @@ -487,7 +498,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { ref_id: ast::NodeId, trait_ref: ty::PolyTraitRef<'tcx>, binding: &ConvertedBinding<'tcx>, - speculative: bool) + speculative: bool, + dup_bindings: &mut FxHashMap<DefId, Vec<Span>>) -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported> { let tcx = self.tcx(); @@ -565,6 +577,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o { tcx.sess.span_err(binding.span, &msg); } tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span); + dup_bindings.entry(assoc_ty.def_id).or_insert(Vec::new()).push(binding.span); Ok(candidate.map_bound(|trait_ref| { ty::ProjectionPredicate { diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.rs b/src/test/ui/lint/issue-50589-multiple-associated-types.rs new file mode 100644 index 00000000000..2c789a139cd --- /dev/null +++ b/src/test/ui/lint/issue-50589-multiple-associated-types.rs @@ -0,0 +1,23 @@ +// Copyright 2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-pass + +use std::iter::Iterator; + +type Unit = (); + +fn test() -> Box<Iterator<Item = (), Item = Unit>> { + Box::new(None.into_iter()) +} + +fn main() { + test(); +} diff --git a/src/test/ui/lint/issue-50589-multiple-associated-types.stderr b/src/test/ui/lint/issue-50589-multiple-associated-types.stderr new file mode 100644 index 00000000000..05e02879f1f --- /dev/null +++ b/src/test/ui/lint/issue-50589-multiple-associated-types.stderr @@ -0,0 +1,14 @@ +warning: duplicate associated type binding + --> $DIR/issue-50589-multiple-associated-types.rs:17:28 + | +LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> { + | ^^^^^^^^^ ^^^^^^^^^^^ + | + = note: #[warn(duplicate_associated_type_binding)] on by default + +warning: duplicate associated type binding + --> $DIR/issue-50589-multiple-associated-types.rs:17:28 + | +LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> { + | ^^^^^^^^^ ^^^^^^^^^^^ + |
