@@ -27,7 +27,7 @@ use rustc_target::spec::abi;
27
27
use std:: slice;
28
28
use require_c_abi_if_variadic;
29
29
use util:: common:: ErrorReported ;
30
- use util:: nodemap:: FxHashSet ;
30
+ use util:: nodemap:: { FxHashSet , FxHashMap } ;
31
31
use errors:: FatalError ;
32
32
33
33
use std:: iter;
@@ -398,11 +398,12 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
398
398
trait_ref. path . segments . last ( ) . unwrap ( ) ) ;
399
399
let poly_trait_ref = ty:: Binder :: bind ( ty:: TraitRef :: new ( trait_def_id, substs) ) ;
400
400
401
+ let mut dup_bindings = FxHashMap :: default ( ) ;
401
402
poly_projections. extend ( assoc_bindings. iter ( ) . filter_map ( |binding| {
402
403
// specify type to assert that error was already reported in Err case:
403
404
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 ) ;
406
407
predicate. ok ( ) // ok to ignore Err() because ErrorReported (see above)
407
408
} ) ) ;
408
409
@@ -487,7 +488,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
487
488
ref_id : ast:: NodeId ,
488
489
trait_ref : ty:: PolyTraitRef < ' tcx > ,
489
490
binding : & ConvertedBinding < ' tcx > ,
490
- speculative : bool )
491
+ speculative : bool ,
492
+ dup_bindings : & mut FxHashMap < DefId , Span > )
491
493
-> Result < ty:: PolyProjectionPredicate < ' tcx > , ErrorReported >
492
494
{
493
495
let tcx = self . tcx ( ) ;
@@ -566,6 +568,23 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
566
568
}
567
569
tcx. check_stability ( assoc_ty. def_id , Some ( ref_id) , binding. span ) ;
568
570
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
+
569
588
Ok ( candidate. map_bound ( |trait_ref| {
570
589
ty:: ProjectionPredicate {
571
590
projection_ty : ty:: ProjectionTy :: from_ref_and_name (
0 commit comments