@@ -9,7 +9,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorG
9
9
use rustc_hir as hir;
10
10
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
11
11
use rustc_infer:: traits:: FulfillmentError ;
12
- use rustc_middle:: ty:: { self , suggest_constraining_type_param, Ty , TyCtxt } ;
12
+ use rustc_middle:: ty:: { self , suggest_constraining_type_param, AssocItem , AssocKind , Ty , TyCtxt } ;
13
13
use rustc_session:: parse:: feature_err;
14
14
use rustc_span:: edit_distance:: find_best_match_for_name;
15
15
use rustc_span:: symbol:: { sym, Ident } ;
@@ -509,6 +509,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
509
509
if associated_types. values ( ) . all ( |v| v. is_empty ( ) ) {
510
510
return ;
511
511
}
512
+
512
513
let tcx = self . tcx ( ) ;
513
514
// FIXME: Marked `mut` so that we can replace the spans further below with a more
514
515
// appropriate one, but this should be handled earlier in the span assignment.
@@ -581,6 +582,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
581
582
}
582
583
}
583
584
585
+ // We get all the associated items that _are_ set,
586
+ // so that we can check if any of their names match one of the ones we are missing.
587
+ // This would mean that they are shadowing the associated type we are missing,
588
+ // and we can then use their span to indicate this to the user.
589
+ let bound_names = trait_bounds
590
+ . iter ( )
591
+ . filter_map ( |poly_trait_ref| {
592
+ let path = poly_trait_ref. trait_ref . path . segments . last ( ) ?;
593
+ let args = path. args ?;
594
+
595
+ Some ( args. bindings . iter ( ) . filter_map ( |binding| {
596
+ let ident = binding. ident ;
597
+ let trait_def = path. res . def_id ( ) ;
598
+ let assoc_item = tcx. associated_items ( trait_def) . find_by_name_and_kind (
599
+ tcx,
600
+ ident,
601
+ AssocKind :: Type ,
602
+ trait_def,
603
+ ) ;
604
+
605
+ Some ( ( ident. name , assoc_item?) )
606
+ } ) )
607
+ } )
608
+ . flatten ( )
609
+ . collect :: < FxHashMap < Symbol , & AssocItem > > ( ) ;
610
+
584
611
let mut names = names
585
612
. into_iter ( )
586
613
. map ( |( trait_, mut assocs) | {
@@ -621,25 +648,51 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
621
648
* names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
622
649
}
623
650
let mut dupes = false ;
651
+ let mut shadows = false ;
624
652
for item in assoc_items {
625
653
let prefix = if names[ & item. name ] > 1 {
626
654
let trait_def_id = item. container_id ( tcx) ;
627
655
dupes = true ;
628
656
format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
657
+ } else if bound_names. get ( & item. name ) . is_some_and ( |x| x != & item) {
658
+ let trait_def_id = item. container_id ( tcx) ;
659
+ shadows = true ;
660
+ format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
629
661
} else {
630
662
String :: new ( )
631
663
} ;
664
+
665
+ let mut is_shadowed = false ;
666
+
667
+ if let Some ( assoc_item) = bound_names. get ( & item. name )
668
+ && assoc_item != & item
669
+ {
670
+ is_shadowed = true ;
671
+
672
+ let is_local = tcx. hir ( ) . get_if_local ( assoc_item. def_id ) . is_some ( ) ;
673
+ let rename_message = if is_local { ", consider renaming it" } else { "" } ;
674
+ err. span_label (
675
+ tcx. def_span ( assoc_item. def_id ) ,
676
+ format ! ( "`{}{}` shadowed here{}" , prefix, item. name, rename_message) ,
677
+ ) ;
678
+ }
679
+
680
+ let rename_message = if is_shadowed { ", consider renaming it" } else { "" } ;
681
+
632
682
if let Some ( sp) = tcx. hir ( ) . span_if_local ( item. def_id ) {
633
- err. span_label ( sp, format ! ( "`{}{}` defined here" , prefix, item. name) ) ;
683
+ err. span_label (
684
+ sp,
685
+ format ! ( "`{}{}` defined here{}" , prefix, item. name, rename_message) ,
686
+ ) ;
634
687
}
635
688
}
636
689
if potential_assoc_types. len ( ) == assoc_items. len ( ) {
637
690
// When the amount of missing associated types equals the number of
638
691
// extra type arguments present. A suggesting to replace the generic args with
639
692
// associated types is already emitted.
640
693
already_has_generics_args_suggestion = true ;
641
- } else if let ( Ok ( snippet) , false ) =
642
- ( tcx. sess . source_map ( ) . span_to_snippet ( * span) , dupes)
694
+ } else if let ( Ok ( snippet) , false , false ) =
695
+ ( tcx. sess . source_map ( ) . span_to_snippet ( * span) , dupes, shadows )
643
696
{
644
697
let types: Vec < _ > =
645
698
assoc_items. iter ( ) . map ( |item| format ! ( "{} = Type" , item. name) ) . collect ( ) ;
@@ -721,6 +774,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
721
774
err. span_help ( where_constraints, where_msg) ;
722
775
}
723
776
}
777
+
724
778
err. emit ( ) ;
725
779
}
726
780
}
0 commit comments