@@ -9,7 +9,7 @@ use rustc_errors::{pluralize, struct_span_err, Applicability, Diagnostic, ErrorG
99use rustc_hir as hir;
1010use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1111use 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 } ;
1313use rustc_session:: parse:: feature_err;
1414use rustc_span:: edit_distance:: find_best_match_for_name;
1515use rustc_span:: symbol:: { sym, Ident } ;
@@ -513,6 +513,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
513513 if associated_types. values ( ) . all ( |v| v. is_empty ( ) ) {
514514 return ;
515515 }
516+
516517 let tcx = self . tcx ( ) ;
517518 // FIXME: Marked `mut` so that we can replace the spans further below with a more
518519 // appropriate one, but this should be handled earlier in the span assignment.
@@ -585,6 +586,32 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
585586 }
586587 }
587588
589+ // We get all the associated items that _are_ set,
590+ // so that we can check if any of their names match one of the ones we are missing.
591+ // This would mean that they are shadowing the associated type we are missing,
592+ // and we can then use their span to indicate this to the user.
593+ let bound_names = trait_bounds
594+ . iter ( )
595+ . filter_map ( |poly_trait_ref| {
596+ poly_trait_ref. trait_ref . path . segments . last ( ) . and_then ( |path| path. args )
597+ } )
598+ . flat_map ( |args| {
599+ args. bindings . iter ( ) . map ( |binding| {
600+ let ident = binding. ident ;
601+ let trait_def = poly_trait_ref. trait_ref . path . res . opt_def_id ( ) ;
602+ let assoc_item = trait_def. and_then ( |did| {
603+ tcx. associated_items ( did) . find_by_name_and_kinds (
604+ tcx,
605+ ident,
606+ & [ AssocKind :: Fn , AssocKind :: Type , AssocKind :: Const ] ,
607+ did,
608+ ) ;
609+ } ) ;
610+ ( ident. name , assoc_item)
611+ } )
612+ } )
613+ . collect :: < FxHashMap < Symbol , Option < & AssocItem > > > ( ) ;
614+
588615 let mut names = names
589616 . into_iter ( )
590617 . map ( |( trait_, mut assocs) | {
@@ -614,6 +641,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
614641 pluralize!( names_len) ,
615642 names,
616643 ) ;
644+ let mut rename_suggestions = vec ! [ ] ;
617645 let mut suggestions = vec ! [ ] ;
618646 let mut types_count = 0 ;
619647 let mut where_constraints = vec ! [ ] ;
@@ -625,23 +653,47 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
625653 * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
626654 }
627655 let mut dupes = false ;
656+ let mut shadows = false ;
628657 for item in assoc_items {
629658 let prefix = if names[ & item. name ] > 1 {
630659 let trait_def_id = item. container_id ( tcx) ;
631660 dupes = true ;
632661 format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
662+ } else if bound_names. contains_key ( & item. name ) {
663+ let trait_def_id = item. container_id ( tcx) ;
664+ shadows = true ;
665+ format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
633666 } else {
634667 String :: new ( )
635668 } ;
636669 if let Some ( sp) = tcx. hir ( ) . span_if_local ( item. def_id ) {
637670 err. span_label ( sp, format ! ( "`{}{}` defined here" , prefix, item. name) ) ;
638671 }
672+
673+ if let Some ( Some ( assoc_item) ) = bound_names. get ( & item. name ) {
674+ err. span_label (
675+ tcx. def_span ( assoc_item. def_id ) ,
676+ format ! ( "`{}{}` shadowed here" , prefix, item. name) ,
677+ ) ;
678+ }
639679 }
640680 if potential_assoc_types. len ( ) == assoc_items. len ( ) {
641681 // When the amount of missing associated types equals the number of
642682 // extra type arguments present. A suggesting to replace the generic args with
643683 // associated types is already emitted.
644684 already_has_generics_args_suggestion = true ;
685+ } else if shadows {
686+ for item in assoc_items {
687+ if let Some ( Some ( assoc_item) ) = bound_names. get ( & item. name ) {
688+ if let Some ( sp) = tcx. hir ( ) . span_if_local ( item. def_id ) {
689+ rename_suggestions. push ( sp) ;
690+ }
691+
692+ if let Some ( sp) = tcx. hir ( ) . span_if_local ( assoc_item. def_id ) {
693+ rename_suggestions. push ( sp) ;
694+ }
695+ }
696+ }
645697 } else if let ( Ok ( snippet) , false ) =
646698 ( tcx. sess . source_map ( ) . span_to_snippet ( * span) , dupes)
647699 {
@@ -725,6 +777,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
725777 err. span_help ( where_constraints, where_msg) ;
726778 }
727779 }
780+
781+ for span in rename_suggestions {
782+ err. span_help ( span, "consider renaming this associated type" ) ;
783+ }
728784 err. emit ( ) ;
729785 }
730786}
0 commit comments