@@ -1260,6 +1260,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12601260 // Dynamic limit to avoid hiding just one candidate, which is silly.
12611261 let limit = if sources. len ( ) == 5 { 5 } else { 4 } ;
12621262
1263+ let mut suggs = vec ! [ ] ;
12631264 for ( idx, source) in sources. iter ( ) . take ( limit) . enumerate ( ) {
12641265 match * source {
12651266 CandidateSource :: Impl ( impl_did) => {
@@ -1322,7 +1323,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13221323 let path = self . tcx . def_path_str ( trait_ref. skip_binder ( ) . def_id ) ;
13231324
13241325 let ty = match item. kind {
1325- ty:: AssocKind :: Const | ty:: AssocKind :: Type => rcvr_ty ,
1326+ ty:: AssocKind :: Const | ty:: AssocKind :: Type => impl_ty ,
13261327 ty:: AssocKind :: Fn => self
13271328 . tcx
13281329 . fn_sig ( item. def_id )
@@ -1334,19 +1335,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13341335 . copied ( )
13351336 . unwrap_or ( rcvr_ty) ,
13361337 } ;
1337- print_disambiguation_help (
1338+ if let Some ( sugg ) = print_disambiguation_help (
13381339 item_name,
13391340 args,
13401341 err,
13411342 path,
13421343 ty,
1344+ Some ( impl_ty) ,
13431345 item. kind ,
13441346 self . tcx . def_kind_descr ( item. kind . as_def_kind ( ) , item. def_id ) ,
13451347 sugg_span,
13461348 idx,
13471349 self . tcx . sess . source_map ( ) ,
13481350 item. fn_has_self_parameter ,
1349- ) ;
1351+ ) {
1352+ suggs. push ( sugg) ;
1353+ }
13501354 }
13511355 }
13521356 CandidateSource :: Trait ( trait_did) => {
@@ -1370,23 +1374,34 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13701374 } ;
13711375 if let Some ( sugg_span) = sugg_span {
13721376 let path = self . tcx . def_path_str ( trait_did) ;
1373- print_disambiguation_help (
1377+ if let Some ( sugg ) = print_disambiguation_help (
13741378 item_name,
13751379 args,
13761380 err,
13771381 path,
13781382 rcvr_ty,
1383+ None ,
13791384 item. kind ,
13801385 self . tcx . def_kind_descr ( item. kind . as_def_kind ( ) , item. def_id ) ,
13811386 sugg_span,
13821387 idx,
13831388 self . tcx . sess . source_map ( ) ,
13841389 item. fn_has_self_parameter ,
1385- ) ;
1390+ ) {
1391+ suggs. push ( sugg) ;
1392+ }
13861393 }
13871394 }
13881395 }
13891396 }
1397+ if !suggs. is_empty ( ) && let Some ( span) = sugg_span {
1398+ err. span_suggestions (
1399+ span. with_hi ( item_name. span . lo ( ) ) ,
1400+ "use fully-qualified syntax to disambiguate" ,
1401+ suggs,
1402+ Applicability :: MachineApplicable ,
1403+ ) ;
1404+ }
13901405 if sources. len ( ) > limit {
13911406 err. note ( format ! ( "and {} others" , sources. len( ) - limit) ) ;
13921407 }
@@ -3146,52 +3161,51 @@ fn print_disambiguation_help<'tcx>(
31463161 err : & mut Diagnostic ,
31473162 trait_name : String ,
31483163 rcvr_ty : Ty < ' _ > ,
3164+ impl_self_ty : Option < Ty < ' _ > > ,
31493165 kind : ty:: AssocKind ,
31503166 def_kind_descr : & ' static str ,
31513167 span : Span ,
31523168 candidate : Option < usize > ,
31533169 source_map : & source_map:: SourceMap ,
31543170 fn_has_self_parameter : bool ,
3155- ) {
3156- let mut applicability = Applicability :: MachineApplicable ;
3157- let ( span, sugg) = if let (
3158- ty:: AssocKind :: Fn ,
3159- Some ( MethodCallComponents { receiver, args, .. } ) ,
3160- ) = ( kind, args)
3161- {
3162- let args = format ! (
3163- "({}{})" ,
3164- rcvr_ty. ref_mutability( ) . map_or( "" , |mutbl| mutbl. ref_prefix_str( ) ) ,
3165- std:: iter:: once( receiver)
3166- . chain( args. iter( ) )
3167- . map( |arg| source_map. span_to_snippet( arg. span) . unwrap_or_else( |_| {
3168- applicability = Applicability :: HasPlaceholders ;
3169- "_" . to_owned( )
3170- } ) )
3171- . collect:: <Vec <_>>( )
3172- . join( ", " ) ,
3173- ) ;
3174- let trait_name = if !fn_has_self_parameter {
3175- format ! ( "<{rcvr_ty} as {trait_name}>" )
3171+ ) -> Option < String > {
3172+ Some (
3173+ if let ( ty:: AssocKind :: Fn , Some ( MethodCallComponents { receiver, args, .. } ) ) = ( kind, args)
3174+ {
3175+ let args = format ! (
3176+ "({}{})" ,
3177+ rcvr_ty. ref_mutability( ) . map_or( "" , |mutbl| mutbl. ref_prefix_str( ) ) ,
3178+ std:: iter:: once( receiver)
3179+ . chain( args. iter( ) )
3180+ . map( |arg| source_map
3181+ . span_to_snippet( arg. span)
3182+ . unwrap_or_else( |_| { "_" . to_owned( ) } ) )
3183+ . collect:: <Vec <_>>( )
3184+ . join( ", " ) ,
3185+ ) ;
3186+ let trait_name = if !fn_has_self_parameter && let Some ( impl_self_ty) = impl_self_ty {
3187+ format ! ( "<{impl_self_ty} as {trait_name}>" )
31763188 } else {
31773189 trait_name
31783190 } ;
3179- ( span, format ! ( "{trait_name}::{item_name}{args}" ) )
3180- } else {
3181- ( span. with_hi ( item_name. span . lo ( ) ) , format ! ( "<{rcvr_ty} as {trait_name}>::" ) )
3182- } ;
3183- err. span_suggestion_verbose (
3184- span,
3185- format ! (
3186- "disambiguate the {} for {}" ,
3187- def_kind_descr,
3188- if let Some ( candidate) = candidate {
3189- format!( "candidate #{candidate}" )
3190- } else {
3191- "the candidate" . to_string( )
3192- } ,
3193- ) ,
3194- sugg,
3195- applicability,
3196- ) ;
3191+ err. span_suggestion_verbose (
3192+ span,
3193+ format ! (
3194+ "disambiguate the {def_kind_descr} for {}" ,
3195+ if let Some ( candidate) = candidate {
3196+ format!( "candidate #{candidate}" )
3197+ } else {
3198+ "the candidate" . to_string( )
3199+ } ,
3200+ ) ,
3201+ format ! ( "{trait_name}::{item_name}{args}" ) ,
3202+ Applicability :: HasPlaceholders ,
3203+ ) ;
3204+ return None ;
3205+ } else if let Some ( impl_self_ty) = impl_self_ty {
3206+ format ! ( "<{impl_self_ty} as {trait_name}>::" )
3207+ } else {
3208+ format ! ( "{trait_name}::" )
3209+ } ,
3210+ )
31973211}
0 commit comments