@@ -1036,90 +1036,108 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
10361036 } ;
10371037 debug ! ( ?bound) ;
10381038
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+ }
10411058
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) ;
10601060
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 ( )
10871102 }
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 ;
10931106 }
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+ ) ) ;
10961112 }
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 : _ } => { }
11041115 }
11051116 } 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+ ) ;
11101123 }
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( ) ,
11171128 ) ) ;
1118- let reported = err. emit ( ) ;
1119- return Err ( reported) ;
11201129 }
1121- err. emit ( ) ;
11221130 }
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 ( ) ;
11231141
11241142 Ok ( bound)
11251143 }
0 commit comments