@@ -1036,90 +1036,108 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
1036
1036
} ;
1037
1037
debug ! ( ?bound) ;
1038
1038
1039
- if let Some ( bound2) = matching_candidates. next ( ) {
1040
- debug ! ( ?bound2) ;
1039
+ let Some ( bound2) = matching_candidates. next ( ) else { return Ok ( bound) } ;
1040
+ let mut matching_candidates = matching_candidates. peekable ( ) ;
1041
+
1042
+ let is_receiver_target = |def_id| tcx. is_lang_item ( def_id, rustc_hir:: LangItem :: Receiver ) ;
1043
+ let is_deref_target = |def_id| tcx. is_lang_item ( def_id, rustc_hir:: LangItem :: Deref ) ;
1044
+ // Since `Deref::Target` and `Receiver::Target` are forced to be the same,
1045
+ // the `Deref::Target` should be taken.
1046
+ if assoc_name. name == sym:: Target && matching_candidates. peek ( ) . is_none ( ) {
1047
+ if is_deref_target ( bound. skip_binder ( ) . def_id )
1048
+ && is_receiver_target ( bound2. skip_binder ( ) . def_id )
1049
+ {
1050
+ return Ok ( bound) ;
1051
+ }
1052
+ if is_receiver_target ( bound. skip_binder ( ) . def_id )
1053
+ && is_deref_target ( bound2. skip_binder ( ) . def_id )
1054
+ {
1055
+ return Ok ( bound2) ;
1056
+ }
1057
+ }
1041
1058
1042
- let assoc_kind_str = errors:: assoc_kind_str ( assoc_kind) ;
1043
- let qself_str = qself. to_string ( tcx) ;
1044
- let mut err = self . dcx ( ) . create_err ( crate :: errors:: AmbiguousAssocItem {
1045
- span,
1046
- assoc_kind : assoc_kind_str,
1047
- assoc_name,
1048
- qself : & qself_str,
1049
- } ) ;
1050
- // Provide a more specific error code index entry for equality bindings.
1051
- err. code (
1052
- if let Some ( constraint) = constraint
1053
- && let hir:: AssocItemConstraintKind :: Equality { .. } = constraint. kind
1054
- {
1055
- E0222
1056
- } else {
1057
- E0221
1058
- } ,
1059
- ) ;
1059
+ debug ! ( ?bound2) ;
1060
1060
1061
- // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
1062
- // FIXME: Turn this into a structured, translateable & more actionable suggestion.
1063
- let mut where_bounds = vec ! [ ] ;
1064
- for bound in [ bound, bound2] . into_iter ( ) . chain ( matching_candidates) {
1065
- let bound_id = bound. def_id ( ) ;
1066
- let bound_span = tcx
1067
- . associated_items ( bound_id)
1068
- . find_by_name_and_kind ( tcx, assoc_name, assoc_kind, bound_id)
1069
- . and_then ( |item| tcx. hir ( ) . span_if_local ( item. def_id ) ) ;
1070
-
1071
- if let Some ( bound_span) = bound_span {
1072
- err. span_label (
1073
- bound_span,
1074
- format ! ( "ambiguous `{assoc_name}` from `{}`" , bound. print_trait_sugared( ) , ) ,
1075
- ) ;
1076
- if let Some ( constraint) = constraint {
1077
- match constraint. kind {
1078
- hir:: AssocItemConstraintKind :: Equality { term } => {
1079
- let term: ty:: Term < ' _ > = match term {
1080
- hir:: Term :: Ty ( ty) => self . lower_ty ( ty) . into ( ) ,
1081
- hir:: Term :: Const ( ct) => {
1082
- self . lower_const_arg ( ct, FeedConstTy :: No ) . into ( )
1083
- }
1084
- } ;
1085
- if term. references_error ( ) {
1086
- continue ;
1061
+ let assoc_kind_str = errors:: assoc_kind_str ( assoc_kind) ;
1062
+ let qself_str = qself. to_string ( tcx) ;
1063
+ let mut err = self . dcx ( ) . create_err ( crate :: errors:: AmbiguousAssocItem {
1064
+ span,
1065
+ assoc_kind : assoc_kind_str,
1066
+ assoc_name,
1067
+ qself : & qself_str,
1068
+ } ) ;
1069
+ // Provide a more specific error code index entry for equality bindings.
1070
+ err. code (
1071
+ if let Some ( constraint) = constraint
1072
+ && let hir:: AssocItemConstraintKind :: Equality { .. } = constraint. kind
1073
+ {
1074
+ E0222
1075
+ } else {
1076
+ E0221
1077
+ } ,
1078
+ ) ;
1079
+
1080
+ // FIXME(#97583): Print associated item bindings properly (i.e., not as equality predicates!).
1081
+ // FIXME: Turn this into a structured, translateable & more actionable suggestion.
1082
+ let mut where_bounds = vec ! [ ] ;
1083
+ for bound in [ bound, bound2] . into_iter ( ) . chain ( matching_candidates) {
1084
+ let bound_id = bound. def_id ( ) ;
1085
+ let bound_span = tcx
1086
+ . associated_items ( bound_id)
1087
+ . find_by_name_and_kind ( tcx, assoc_name, assoc_kind, bound_id)
1088
+ . and_then ( |item| tcx. hir ( ) . span_if_local ( item. def_id ) ) ;
1089
+
1090
+ if let Some ( bound_span) = bound_span {
1091
+ err. span_label (
1092
+ bound_span,
1093
+ format ! ( "ambiguous `{assoc_name}` from `{}`" , bound. print_trait_sugared( ) , ) ,
1094
+ ) ;
1095
+ if let Some ( constraint) = constraint {
1096
+ match constraint. kind {
1097
+ hir:: AssocItemConstraintKind :: Equality { term } => {
1098
+ let term: ty:: Term < ' _ > = match term {
1099
+ hir:: Term :: Ty ( ty) => self . lower_ty ( ty) . into ( ) ,
1100
+ hir:: Term :: Const ( ct) => {
1101
+ self . lower_const_arg ( ct, FeedConstTy :: No ) . into ( )
1087
1102
}
1088
- // FIXME(#97583): This isn't syntactically well-formed!
1089
- where_bounds. push ( format ! (
1090
- " T: {trait}::{assoc_name} = {term}" ,
1091
- trait = bound. print_only_trait_path( ) ,
1092
- ) ) ;
1103
+ } ;
1104
+ if term. references_error ( ) {
1105
+ continue ;
1093
1106
}
1094
- // FIXME: Provide a suggestion.
1095
- hir:: AssocItemConstraintKind :: Bound { bounds : _ } => { }
1107
+ // FIXME(#97583): This isn't syntactically well-formed!
1108
+ where_bounds. push ( format ! (
1109
+ " T: {trait}::{assoc_name} = {term}" ,
1110
+ trait = bound. print_only_trait_path( ) ,
1111
+ ) ) ;
1096
1112
}
1097
- } else {
1098
- err. span_suggestion_verbose (
1099
- span. with_hi ( assoc_name. span . lo ( ) ) ,
1100
- "use fully-qualified syntax to disambiguate" ,
1101
- format ! ( "<{qself_str} as {}>::" , bound. print_only_trait_path( ) ) ,
1102
- Applicability :: MaybeIncorrect ,
1103
- ) ;
1113
+ // FIXME: Provide a suggestion.
1114
+ hir:: AssocItemConstraintKind :: Bound { bounds : _ } => { }
1104
1115
}
1105
1116
} else {
1106
- err. note ( format ! (
1107
- "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`" ,
1108
- bound. print_only_trait_path( ) ,
1109
- ) ) ;
1117
+ err. span_suggestion_verbose (
1118
+ span. with_hi ( assoc_name. span . lo ( ) ) ,
1119
+ "use fully-qualified syntax to disambiguate" ,
1120
+ format ! ( "<{qself_str} as {}>::" , bound. print_only_trait_path( ) ) ,
1121
+ Applicability :: MaybeIncorrect ,
1122
+ ) ;
1110
1123
}
1111
- }
1112
- if !where_bounds. is_empty ( ) {
1113
- err. help ( format ! (
1114
- "consider introducing a new type parameter `T` and adding `where` constraints:\
1115
- \n where\n T: {qself_str},\n {}",
1116
- where_bounds. join( ",\n " ) ,
1124
+ } else {
1125
+ err. note ( format ! (
1126
+ "associated {assoc_kind_str} `{assoc_name}` could derive from `{}`" ,
1127
+ bound. print_only_trait_path( ) ,
1117
1128
) ) ;
1118
- let reported = err. emit ( ) ;
1119
- return Err ( reported) ;
1120
1129
}
1121
- err. emit ( ) ;
1122
1130
}
1131
+ if !where_bounds. is_empty ( ) {
1132
+ err. help ( format ! (
1133
+ "consider introducing a new type parameter `T` and adding `where` constraints:\
1134
+ \n where\n T: {qself_str},\n {}",
1135
+ where_bounds. join( ",\n " ) ,
1136
+ ) ) ;
1137
+ let reported = err. emit ( ) ;
1138
+ return Err ( reported) ;
1139
+ }
1140
+ err. emit ( ) ;
1123
1141
1124
1142
Ok ( bound)
1125
1143
}
0 commit comments