"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)]
BARE_TRAIT_OBJECT,
ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
UNSTABLE_NAME_COLLISION,
+ DUPLICATE_ASSOCIATED_TYPE_BINDING,
)
}
}
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;
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);
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();
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 {
--- /dev/null
+// 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();
+}
--- /dev/null
+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>> {
+ | ^^^^^^^^^ ^^^^^^^^^^^
+