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