@@ -716,51 +716,40 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
716
716
/// emit a generic note suggesting using a `where` clause to constraint instead.
717
717
pub ( crate ) fn check_for_required_assoc_tys (
718
718
& self ,
719
- associated_types : FxIndexMap < Span , FxIndexSet < DefId > > ,
719
+ principal_span : Span ,
720
+ missing_assoc_types : FxIndexSet < DefId > ,
720
721
potential_assoc_types : Vec < usize > ,
721
722
trait_bounds : & [ hir:: PolyTraitRef < ' _ > ] ,
722
723
) -> Result < ( ) , ErrorGuaranteed > {
723
- if associated_types . values ( ) . all ( |v| v . is_empty ( ) ) {
724
+ if missing_assoc_types . is_empty ( ) {
724
725
return Ok ( ( ) ) ;
725
726
}
726
727
727
728
let tcx = self . tcx ( ) ;
728
- // FIXME: Marked `mut` so that we can replace the spans further below with a more
729
- // appropriate one, but this should be handled earlier in the span assignment.
730
- let associated_types: FxIndexMap < Span , Vec < _ > > = associated_types
731
- . into_iter ( )
732
- . map ( |( span, def_ids) | {
733
- ( span, def_ids. into_iter ( ) . map ( |did| tcx. associated_item ( did) ) . collect ( ) )
734
- } )
735
- . collect ( ) ;
729
+ let missing_assoc_types: Vec < _ > =
730
+ missing_assoc_types. into_iter ( ) . map ( |def_id| tcx. associated_item ( def_id) ) . collect ( ) ;
736
731
let mut names: FxIndexMap < String , Vec < Symbol > > = Default :: default ( ) ;
737
732
let mut names_len = 0 ;
738
733
739
734
// Account for things like `dyn Foo + 'a`, like in tests `issue-22434.rs` and
740
735
// `issue-22560.rs`.
741
- let mut trait_bound_spans: Vec < Span > = vec ! [ ] ;
742
736
let mut dyn_compatibility_violations = Ok ( ( ) ) ;
743
- for ( span, items) in & associated_types {
744
- if !items. is_empty ( ) {
745
- trait_bound_spans. push ( * span) ;
746
- }
747
- for assoc_item in items {
748
- let trait_def_id = assoc_item. container_id ( tcx) ;
749
- names. entry ( tcx. def_path_str ( trait_def_id) ) . or_default ( ) . push ( assoc_item. name ) ;
750
- names_len += 1 ;
751
-
752
- let violations =
753
- dyn_compatibility_violations_for_assoc_item ( tcx, trait_def_id, * assoc_item) ;
754
- if !violations. is_empty ( ) {
755
- dyn_compatibility_violations = Err ( report_dyn_incompatibility (
756
- tcx,
757
- * span,
758
- None ,
759
- trait_def_id,
760
- & violations,
761
- )
762
- . emit ( ) ) ;
763
- }
737
+ for assoc_item in & missing_assoc_types {
738
+ let trait_def_id = assoc_item. container_id ( tcx) ;
739
+ names. entry ( tcx. def_path_str ( trait_def_id) ) . or_default ( ) . push ( assoc_item. name ) ;
740
+ names_len += 1 ;
741
+
742
+ let violations =
743
+ dyn_compatibility_violations_for_assoc_item ( tcx, trait_def_id, * assoc_item) ;
744
+ if !violations. is_empty ( ) {
745
+ dyn_compatibility_violations = Err ( report_dyn_incompatibility (
746
+ tcx,
747
+ principal_span,
748
+ None ,
749
+ trait_def_id,
750
+ & violations,
751
+ )
752
+ . emit ( ) ) ;
764
753
}
765
754
}
766
755
@@ -821,10 +810,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
821
810
names. sort ( ) ;
822
811
let names = names. join ( ", " ) ;
823
812
824
- trait_bound_spans. sort ( ) ;
825
813
let mut err = struct_span_code_err ! (
826
814
self . dcx( ) ,
827
- trait_bound_spans ,
815
+ principal_span ,
828
816
E0191 ,
829
817
"the value of the associated type{} {} must be specified" ,
830
818
pluralize!( names_len) ,
@@ -834,81 +822,81 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
834
822
let mut types_count = 0 ;
835
823
let mut where_constraints = vec ! [ ] ;
836
824
let mut already_has_generics_args_suggestion = false ;
837
- for ( span, assoc_items) in & associated_types {
838
- let mut names: UnordMap < _ , usize > = Default :: default ( ) ;
839
- for item in assoc_items {
840
- types_count += 1 ;
841
- * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
842
- }
843
- let mut dupes = false ;
844
- let mut shadows = false ;
845
- for item in assoc_items {
846
- let prefix = if names[ & item. name ] > 1 {
847
- let trait_def_id = item. container_id ( tcx) ;
848
- dupes = true ;
849
- format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
850
- } else if bound_names. get ( & item. name ) . is_some_and ( |x| x != & item) {
851
- let trait_def_id = item. container_id ( tcx) ;
852
- shadows = true ;
853
- format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
854
- } else {
855
- String :: new ( )
856
- } ;
857
825
858
- let mut is_shadowed = false ;
859
-
860
- if let Some ( assoc_item) = bound_names. get ( & item. name )
861
- && assoc_item != & item
862
- {
863
- is_shadowed = true ;
826
+ let mut names: UnordMap < _ , usize > = Default :: default ( ) ;
827
+ for item in & missing_assoc_types {
828
+ types_count += 1 ;
829
+ * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
830
+ }
831
+ let mut dupes = false ;
832
+ let mut shadows = false ;
833
+ for item in & missing_assoc_types {
834
+ let prefix = if names[ & item. name ] > 1 {
835
+ let trait_def_id = item. container_id ( tcx) ;
836
+ dupes = true ;
837
+ format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
838
+ } else if bound_names. get ( & item. name ) . is_some_and ( |x| * x != item) {
839
+ let trait_def_id = item. container_id ( tcx) ;
840
+ shadows = true ;
841
+ format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
842
+ } else {
843
+ String :: new ( )
844
+ } ;
864
845
865
- let rename_message =
866
- if assoc_item. def_id . is_local ( ) { ", consider renaming it" } else { "" } ;
867
- err. span_label (
868
- tcx. def_span ( assoc_item. def_id ) ,
869
- format ! ( "`{}{}` shadowed here{}" , prefix, item. name, rename_message) ,
870
- ) ;
871
- }
846
+ let mut is_shadowed = false ;
872
847
873
- let rename_message = if is_shadowed { ", consider renaming it" } else { "" } ;
848
+ if let Some ( assoc_item) = bound_names. get ( & item. name )
849
+ && * assoc_item != item
850
+ {
851
+ is_shadowed = true ;
874
852
875
- if let Some ( sp ) = tcx . hir ( ) . span_if_local ( item . def_id ) {
876
- err . span_label (
877
- sp ,
878
- format ! ( "`{}{}` defined here{}" , prefix , item . name , rename_message ) ,
879
- ) ;
880
- }
853
+ let rename_message =
854
+ if assoc_item . def_id . is_local ( ) { ", consider renaming it" } else { "" } ;
855
+ err . span_label (
856
+ tcx . def_span ( assoc_item . def_id ) ,
857
+ format ! ( "`{}{}` shadowed here{}" , prefix , item . name , rename_message ) ,
858
+ ) ;
881
859
}
882
- if potential_assoc_types. len ( ) == assoc_items. len ( ) {
883
- // When the amount of missing associated types equals the number of
884
- // extra type arguments present. A suggesting to replace the generic args with
885
- // associated types is already emitted.
886
- already_has_generics_args_suggestion = true ;
887
- } else if let ( Ok ( snippet) , false , false ) =
888
- ( tcx. sess . source_map ( ) . span_to_snippet ( * span) , dupes, shadows)
889
- {
890
- let types: Vec < _ > =
891
- assoc_items. iter ( ) . map ( |item| format ! ( "{} = Type" , item. name) ) . collect ( ) ;
892
- let code = if snippet. ends_with ( '>' ) {
893
- // The user wrote `Trait<'a>` or similar and we don't have a type we can
894
- // suggest, but at least we can clue them to the correct syntax
895
- // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
896
- // suggestion.
897
- format ! ( "{}, {}>" , & snippet[ ..snippet. len( ) - 1 ] , types. join( ", " ) )
898
- } else if in_expr_or_pat {
899
- // The user wrote `Iterator`, so we don't have a type we can suggest, but at
900
- // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
901
- format ! ( "{}::<{}>" , snippet, types. join( ", " ) )
902
- } else {
903
- // The user wrote `Iterator`, so we don't have a type we can suggest, but at
904
- // least we can clue them to the correct syntax `Iterator<Item = Type>`.
905
- format ! ( "{}<{}>" , snippet, types. join( ", " ) )
906
- } ;
907
- suggestions. push ( ( * span, code) ) ;
908
- } else if dupes {
909
- where_constraints. push ( * span) ;
860
+
861
+ let rename_message = if is_shadowed { ", consider renaming it" } else { "" } ;
862
+
863
+ if let Some ( sp) = tcx. hir ( ) . span_if_local ( item. def_id ) {
864
+ err. span_label (
865
+ sp,
866
+ format ! ( "`{}{}` defined here{}" , prefix, item. name, rename_message) ,
867
+ ) ;
910
868
}
911
869
}
870
+ if potential_assoc_types. len ( ) == missing_assoc_types. len ( ) {
871
+ // When the amount of missing associated types equals the number of
872
+ // extra type arguments present. A suggesting to replace the generic args with
873
+ // associated types is already emitted.
874
+ already_has_generics_args_suggestion = true ;
875
+ } else if let ( Ok ( snippet) , false , false ) =
876
+ ( tcx. sess . source_map ( ) . span_to_snippet ( principal_span) , dupes, shadows)
877
+ {
878
+ let types: Vec < _ > =
879
+ missing_assoc_types. iter ( ) . map ( |item| format ! ( "{} = Type" , item. name) ) . collect ( ) ;
880
+ let code = if snippet. ends_with ( '>' ) {
881
+ // The user wrote `Trait<'a>` or similar and we don't have a type we can
882
+ // suggest, but at least we can clue them to the correct syntax
883
+ // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
884
+ // suggestion.
885
+ format ! ( "{}, {}>" , & snippet[ ..snippet. len( ) - 1 ] , types. join( ", " ) )
886
+ } else if in_expr_or_pat {
887
+ // The user wrote `Iterator`, so we don't have a type we can suggest, but at
888
+ // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
889
+ format ! ( "{}::<{}>" , snippet, types. join( ", " ) )
890
+ } else {
891
+ // The user wrote `Iterator`, so we don't have a type we can suggest, but at
892
+ // least we can clue them to the correct syntax `Iterator<Item = Type>`.
893
+ format ! ( "{}<{}>" , snippet, types. join( ", " ) )
894
+ } ;
895
+ suggestions. push ( ( principal_span, code) ) ;
896
+ } else if dupes {
897
+ where_constraints. push ( principal_span) ;
898
+ }
899
+
912
900
let where_msg = "consider introducing a new type parameter, adding `where` constraints \
913
901
using the fully-qualified path to the associated types";
914
902
if !where_constraints. is_empty ( ) && suggestions. is_empty ( ) {
@@ -919,32 +907,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
919
907
}
920
908
if suggestions. len ( ) != 1 || already_has_generics_args_suggestion {
921
909
// We don't need this label if there's an inline suggestion, show otherwise.
922
- for ( span, assoc_items) in & associated_types {
923
- let mut names: FxIndexMap < _ , usize > = FxIndexMap :: default ( ) ;
924
- for item in assoc_items {
925
- types_count += 1 ;
926
- * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
927
- }
928
- let mut label = vec ! [ ] ;
929
- for item in assoc_items {
930
- let postfix = if names[ & item. name ] > 1 {
931
- let trait_def_id = item. container_id ( tcx) ;
932
- format ! ( " (from trait `{}`)" , tcx. def_path_str( trait_def_id) )
933
- } else {
934
- String :: new ( )
935
- } ;
936
- label. push ( format ! ( "`{}`{}" , item. name, postfix) ) ;
937
- }
938
- if !label. is_empty ( ) {
939
- err. span_label (
940
- * span,
941
- format ! (
942
- "associated type{} {} must be specified" ,
943
- pluralize!( label. len( ) ) ,
944
- label. join( ", " ) ,
945
- ) ,
946
- ) ;
947
- }
910
+ let mut names: FxIndexMap < _ , usize > = FxIndexMap :: default ( ) ;
911
+ for item in & missing_assoc_types {
912
+ types_count += 1 ;
913
+ * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
914
+ }
915
+ let mut label = vec ! [ ] ;
916
+ for item in & missing_assoc_types {
917
+ let postfix = if names[ & item. name ] > 1 {
918
+ let trait_def_id = item. container_id ( tcx) ;
919
+ format ! ( " (from trait `{}`)" , tcx. def_path_str( trait_def_id) )
920
+ } else {
921
+ String :: new ( )
922
+ } ;
923
+ label. push ( format ! ( "`{}`{}" , item. name, postfix) ) ;
924
+ }
925
+ if !label. is_empty ( ) {
926
+ err. span_label (
927
+ principal_span,
928
+ format ! (
929
+ "associated type{} {} must be specified" ,
930
+ pluralize!( label. len( ) ) ,
931
+ label. join( ", " ) ,
932
+ ) ,
933
+ ) ;
948
934
}
949
935
}
950
936
suggestions. sort_by_key ( |& ( span, _) | span) ;
0 commit comments