@@ -716,45 +716,35 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
716
716
/// emit a generic note suggesting using a `where` clause to constraint instead.
717
717
pub ( crate ) fn complain_about_missing_assoc_tys (
718
718
& self ,
719
- associated_types : FxIndexMap < Span , FxIndexSet < DefId > > ,
719
+ mut principal_span : Span ,
720
+ missing_assoc_types : FxIndexSet < DefId > ,
720
721
potential_assoc_types : Vec < usize > ,
721
722
trait_bounds : & [ hir:: PolyTraitRef < ' _ > ] ,
722
723
) {
723
- if associated_types . values ( ) . all ( |v| v . is_empty ( ) ) {
724
+ if missing_assoc_types . is_empty ( ) {
724
725
return ;
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 mut 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 = false ;
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
- report_dyn_incompatibility ( tcx, * span, None , trait_def_id, & violations) . emit ( ) ;
756
- dyn_compatibility_violations = true ;
757
- }
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
+ report_dyn_incompatibility ( tcx, principal_span, None , trait_def_id, & violations)
746
+ . emit ( ) ;
747
+ dyn_compatibility_violations = true ;
758
748
}
759
749
}
760
750
if dyn_compatibility_violations {
@@ -794,11 +784,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
794
784
// | ^^^^^^^^^^^^^ help: specify the associated type:
795
785
// | `BitXor::bitor<Output = Type>`
796
786
[ segment] if segment. args . is_none ( ) => {
797
- trait_bound_spans = vec ! [ segment. ident. span] ;
798
- associated_types = associated_types
799
- . into_values ( )
800
- . map ( |items| ( segment. ident . span , items) )
801
- . collect ( ) ;
787
+ principal_span = segment. ident . span ;
802
788
}
803
789
_ => { }
804
790
}
@@ -847,10 +833,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
847
833
names. sort ( ) ;
848
834
let names = names. join ( ", " ) ;
849
835
850
- trait_bound_spans. sort ( ) ;
851
836
let mut err = struct_span_code_err ! (
852
837
self . dcx( ) ,
853
- trait_bound_spans ,
838
+ principal_span ,
854
839
E0191 ,
855
840
"the value of the associated type{} {} must be specified" ,
856
841
pluralize!( names_len) ,
@@ -860,81 +845,81 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
860
845
let mut types_count = 0 ;
861
846
let mut where_constraints = vec ! [ ] ;
862
847
let mut already_has_generics_args_suggestion = false ;
863
- for ( span, assoc_items) in & associated_types {
864
- let mut names: UnordMap < _ , usize > = Default :: default ( ) ;
865
- for item in assoc_items {
866
- types_count += 1 ;
867
- * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
868
- }
869
- let mut dupes = false ;
870
- let mut shadows = false ;
871
- for item in assoc_items {
872
- let prefix = if names[ & item. name ] > 1 {
873
- let trait_def_id = item. container_id ( tcx) ;
874
- dupes = true ;
875
- format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
876
- } else if bound_names. get ( & item. name ) . is_some_and ( |x| x != & item) {
877
- let trait_def_id = item. container_id ( tcx) ;
878
- shadows = true ;
879
- format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
880
- } else {
881
- String :: new ( )
882
- } ;
883
-
884
- let mut is_shadowed = false ;
885
848
886
- if let Some ( assoc_item) = bound_names. get ( & item. name )
887
- && assoc_item != & item
888
- {
889
- is_shadowed = true ;
849
+ let mut names: UnordMap < _ , usize > = Default :: default ( ) ;
850
+ for item in & missing_assoc_types {
851
+ types_count += 1 ;
852
+ * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
853
+ }
854
+ let mut dupes = false ;
855
+ let mut shadows = false ;
856
+ for item in & missing_assoc_types {
857
+ let prefix = if names[ & item. name ] > 1 {
858
+ let trait_def_id = item. container_id ( tcx) ;
859
+ dupes = true ;
860
+ format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
861
+ } else if bound_names. get ( & item. name ) . is_some_and ( |x| * x != item) {
862
+ let trait_def_id = item. container_id ( tcx) ;
863
+ shadows = true ;
864
+ format ! ( "{}::" , tcx. def_path_str( trait_def_id) )
865
+ } else {
866
+ String :: new ( )
867
+ } ;
890
868
891
- let rename_message =
892
- if assoc_item. def_id . is_local ( ) { ", consider renaming it" } else { "" } ;
893
- err. span_label (
894
- tcx. def_span ( assoc_item. def_id ) ,
895
- format ! ( "`{}{}` shadowed here{}" , prefix, item. name, rename_message) ,
896
- ) ;
897
- }
869
+ let mut is_shadowed = false ;
898
870
899
- let rename_message = if is_shadowed { ", consider renaming it" } else { "" } ;
871
+ if let Some ( assoc_item) = bound_names. get ( & item. name )
872
+ && * assoc_item != item
873
+ {
874
+ is_shadowed = true ;
900
875
901
- if let Some ( sp ) = tcx . hir ( ) . span_if_local ( item . def_id ) {
902
- err . span_label (
903
- sp ,
904
- format ! ( "`{}{}` defined here{}" , prefix , item . name , rename_message ) ,
905
- ) ;
906
- }
876
+ let rename_message =
877
+ if assoc_item . def_id . is_local ( ) { ", consider renaming it" } else { "" } ;
878
+ err . span_label (
879
+ tcx . def_span ( assoc_item . def_id ) ,
880
+ format ! ( "`{}{}` shadowed here{}" , prefix , item . name , rename_message ) ,
881
+ ) ;
907
882
}
908
- if potential_assoc_types. len ( ) == assoc_items. len ( ) {
909
- // When the amount of missing associated types equals the number of
910
- // extra type arguments present. A suggesting to replace the generic args with
911
- // associated types is already emitted.
912
- already_has_generics_args_suggestion = true ;
913
- } else if let ( Ok ( snippet) , false , false ) =
914
- ( tcx. sess . source_map ( ) . span_to_snippet ( * span) , dupes, shadows)
915
- {
916
- let types: Vec < _ > =
917
- assoc_items. iter ( ) . map ( |item| format ! ( "{} = Type" , item. name) ) . collect ( ) ;
918
- let code = if snippet. ends_with ( '>' ) {
919
- // The user wrote `Trait<'a>` or similar and we don't have a type we can
920
- // suggest, but at least we can clue them to the correct syntax
921
- // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
922
- // suggestion.
923
- format ! ( "{}, {}>" , & snippet[ ..snippet. len( ) - 1 ] , types. join( ", " ) )
924
- } else if in_expr_or_pat {
925
- // The user wrote `Iterator`, so we don't have a type we can suggest, but at
926
- // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
927
- format ! ( "{}::<{}>" , snippet, types. join( ", " ) )
928
- } else {
929
- // The user wrote `Iterator`, so we don't have a type we can suggest, but at
930
- // least we can clue them to the correct syntax `Iterator<Item = Type>`.
931
- format ! ( "{}<{}>" , snippet, types. join( ", " ) )
932
- } ;
933
- suggestions. push ( ( * span, code) ) ;
934
- } else if dupes {
935
- where_constraints. push ( * span) ;
883
+
884
+ let rename_message = if is_shadowed { ", consider renaming it" } else { "" } ;
885
+
886
+ if let Some ( sp) = tcx. hir ( ) . span_if_local ( item. def_id ) {
887
+ err. span_label (
888
+ sp,
889
+ format ! ( "`{}{}` defined here{}" , prefix, item. name, rename_message) ,
890
+ ) ;
936
891
}
937
892
}
893
+ if potential_assoc_types. len ( ) == missing_assoc_types. len ( ) {
894
+ // When the amount of missing associated types equals the number of
895
+ // extra type arguments present. A suggesting to replace the generic args with
896
+ // associated types is already emitted.
897
+ already_has_generics_args_suggestion = true ;
898
+ } else if let ( Ok ( snippet) , false , false ) =
899
+ ( tcx. sess . source_map ( ) . span_to_snippet ( principal_span) , dupes, shadows)
900
+ {
901
+ let types: Vec < _ > =
902
+ missing_assoc_types. iter ( ) . map ( |item| format ! ( "{} = Type" , item. name) ) . collect ( ) ;
903
+ let code = if snippet. ends_with ( '>' ) {
904
+ // The user wrote `Trait<'a>` or similar and we don't have a type we can
905
+ // suggest, but at least we can clue them to the correct syntax
906
+ // `Trait<'a, Item = Type>` while accounting for the `<'a>` in the
907
+ // suggestion.
908
+ format ! ( "{}, {}>" , & snippet[ ..snippet. len( ) - 1 ] , types. join( ", " ) )
909
+ } else if in_expr_or_pat {
910
+ // The user wrote `Iterator`, so we don't have a type we can suggest, but at
911
+ // least we can clue them to the correct syntax `Iterator::<Item = Type>`.
912
+ format ! ( "{}::<{}>" , snippet, types. join( ", " ) )
913
+ } else {
914
+ // The user wrote `Iterator`, so we don't have a type we can suggest, but at
915
+ // least we can clue them to the correct syntax `Iterator<Item = Type>`.
916
+ format ! ( "{}<{}>" , snippet, types. join( ", " ) )
917
+ } ;
918
+ suggestions. push ( ( principal_span, code) ) ;
919
+ } else if dupes {
920
+ where_constraints. push ( principal_span) ;
921
+ }
922
+
938
923
let where_msg = "consider introducing a new type parameter, adding `where` constraints \
939
924
using the fully-qualified path to the associated types";
940
925
if !where_constraints. is_empty ( ) && suggestions. is_empty ( ) {
@@ -945,32 +930,30 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
945
930
}
946
931
if suggestions. len ( ) != 1 || already_has_generics_args_suggestion {
947
932
// We don't need this label if there's an inline suggestion, show otherwise.
948
- for ( span, assoc_items) in & associated_types {
949
- let mut names: FxIndexMap < _ , usize > = FxIndexMap :: default ( ) ;
950
- for item in assoc_items {
951
- types_count += 1 ;
952
- * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
953
- }
954
- let mut label = vec ! [ ] ;
955
- for item in assoc_items {
956
- let postfix = if names[ & item. name ] > 1 {
957
- let trait_def_id = item. container_id ( tcx) ;
958
- format ! ( " (from trait `{}`)" , tcx. def_path_str( trait_def_id) )
959
- } else {
960
- String :: new ( )
961
- } ;
962
- label. push ( format ! ( "`{}`{}" , item. name, postfix) ) ;
963
- }
964
- if !label. is_empty ( ) {
965
- err. span_label (
966
- * span,
967
- format ! (
968
- "associated type{} {} must be specified" ,
969
- pluralize!( label. len( ) ) ,
970
- label. join( ", " ) ,
971
- ) ,
972
- ) ;
973
- }
933
+ let mut names: FxIndexMap < _ , usize > = FxIndexMap :: default ( ) ;
934
+ for item in & missing_assoc_types {
935
+ types_count += 1 ;
936
+ * names. entry ( item. name ) . or_insert ( 0 ) += 1 ;
937
+ }
938
+ let mut label = vec ! [ ] ;
939
+ for item in & missing_assoc_types {
940
+ let postfix = if names[ & item. name ] > 1 {
941
+ let trait_def_id = item. container_id ( tcx) ;
942
+ format ! ( " (from trait `{}`)" , tcx. def_path_str( trait_def_id) )
943
+ } else {
944
+ String :: new ( )
945
+ } ;
946
+ label. push ( format ! ( "`{}`{}" , item. name, postfix) ) ;
947
+ }
948
+ if !label. is_empty ( ) {
949
+ err. span_label (
950
+ principal_span,
951
+ format ! (
952
+ "associated type{} {} must be specified" ,
953
+ pluralize!( label. len( ) ) ,
954
+ label. join( ", " ) ,
955
+ ) ,
956
+ ) ;
974
957
}
975
958
}
976
959
suggestions. sort_by_key ( |& ( span, _) | span) ;
0 commit comments