Skip to content

Commit 9a4e5df

Browse files
committed
Auto merge of #50682 - F001:issue-50589, r=petrochenkov
Add lint for multiple associated types Fix #50589. cc @abonander
2 parents 5ec4ab9 + 88f810f commit 9a4e5df

File tree

5 files changed

+81
-4
lines changed

5 files changed

+81
-4
lines changed

src/librustc/lint/builtin.rs

+7
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,12 @@ declare_lint! {
279279
"detects labels that are never used"
280280
}
281281

282+
declare_lint! {
283+
pub DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
284+
Warn,
285+
"warns about duplicate associated type bindings in generics"
286+
}
287+
282288
/// Does nothing as a lint pass, but registers some `Lint`s
283289
/// which are used by other parts of the compiler.
284290
#[derive(Copy, Clone)]
@@ -330,6 +336,7 @@ impl LintPass for HardwiredLints {
330336
BARE_TRAIT_OBJECT,
331337
ABSOLUTE_PATH_NOT_STARTING_WITH_CRATE,
332338
UNSTABLE_NAME_COLLISION,
339+
DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
333340
)
334341
}
335342
}

src/librustc_lint/lib.rs

+5
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,11 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
283283
reference: "issue TBD",
284284
edition: Some(Edition::Edition2018),
285285
},
286+
FutureIncompatibleInfo {
287+
id: LintId::of(DUPLICATE_ASSOCIATED_TYPE_BINDINGS),
288+
reference: "issue #50589 <https://github.com/rust-lang/rust/issues/50589>",
289+
edition: None,
290+
},
286291
]);
287292

288293
// Register renamed and removed lints

src/librustc_typeck/astconv.rs

+23-4
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use rustc_target::spec::abi;
2727
use std::slice;
2828
use require_c_abi_if_variadic;
2929
use util::common::ErrorReported;
30-
use util::nodemap::FxHashSet;
30+
use util::nodemap::{FxHashSet, FxHashMap};
3131
use errors::FatalError;
3232

3333
use std::iter;
@@ -398,11 +398,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
398398
trait_ref.path.segments.last().unwrap());
399399
let poly_trait_ref = ty::Binder::bind(ty::TraitRef::new(trait_def_id, substs));
400400

401+
let mut dup_bindings = FxHashMap::default();
401402
poly_projections.extend(assoc_bindings.iter().filter_map(|binding| {
402403
// specify type to assert that error was already reported in Err case:
403404
let predicate: Result<_, ErrorReported> =
404-
self.ast_type_binding_to_poly_projection_predicate(trait_ref.ref_id, poly_trait_ref,
405-
binding, speculative);
405+
self.ast_type_binding_to_poly_projection_predicate(
406+
trait_ref.ref_id, poly_trait_ref, binding, speculative, &mut dup_bindings);
406407
predicate.ok() // ok to ignore Err() because ErrorReported (see above)
407408
}));
408409

@@ -487,7 +488,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
487488
ref_id: ast::NodeId,
488489
trait_ref: ty::PolyTraitRef<'tcx>,
489490
binding: &ConvertedBinding<'tcx>,
490-
speculative: bool)
491+
speculative: bool,
492+
dup_bindings: &mut FxHashMap<DefId, Span>)
491493
-> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
492494
{
493495
let tcx = self.tcx();
@@ -566,6 +568,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
566568
}
567569
tcx.check_stability(assoc_ty.def_id, Some(ref_id), binding.span);
568570

571+
if !speculative {
572+
dup_bindings.entry(assoc_ty.def_id)
573+
.and_modify(|prev_span| {
574+
let mut err = self.tcx().struct_span_lint_node(
575+
::rustc::lint::builtin::DUPLICATE_ASSOCIATED_TYPE_BINDINGS,
576+
ref_id,
577+
binding.span,
578+
&format!("associated type binding `{}` specified more than once",
579+
binding.item_name)
580+
);
581+
err.span_label(binding.span, "used more than once");
582+
err.span_label(*prev_span, format!("first use of `{}`", binding.item_name));
583+
err.emit();
584+
})
585+
.or_insert(binding.span);
586+
}
587+
569588
Ok(candidate.map_bound(|trait_ref| {
570589
ty::ProjectionPredicate {
571590
projection_ty: ty::ProjectionTy::from_ref_and_name(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Copyright 2018 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+
// compile-pass
12+
13+
use std::iter::Iterator;
14+
15+
type Unit = ();
16+
17+
fn test() -> Box<Iterator<Item = (), Item = Unit>> {
18+
Box::new(None.into_iter())
19+
}
20+
21+
fn main() {
22+
test();
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
warning: associated type binding `Item` specified more than once
2+
--> $DIR/issue-50589-multiple-associated-types.rs:17:39
3+
|
4+
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
5+
| --------- ^^^^^^^^^^^ used more than once
6+
| |
7+
| first use of `Item`
8+
|
9+
= note: #[warn(duplicate_associated_type_bindings)] on by default
10+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
11+
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
12+
13+
warning: associated type binding `Item` specified more than once
14+
--> $DIR/issue-50589-multiple-associated-types.rs:17:39
15+
|
16+
LL | fn test() -> Box<Iterator<Item = (), Item = Unit>> {
17+
| --------- ^^^^^^^^^^^ used more than once
18+
| |
19+
| first use of `Item`
20+
|
21+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
22+
= note: for more information, see issue #50589 <https://github.com/rust-lang/rust/issues/50589>
23+

0 commit comments

Comments
 (0)