@@ -14,11 +14,17 @@ use rustc_hir::def::DefKind;
1414use rustc_hir:: def_id:: DefId ;
1515use rustc_hir:: lang_items:: LangItem ;
1616use rustc_hir:: { ExprKind , Node , QPath } ;
17- use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
17+ use rustc_infer:: infer:: {
18+ type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ,
19+ RegionVariableOrigin ,
20+ } ;
21+ use rustc_middle:: infer:: unify_key:: { ConstVariableOrigin , ConstVariableOriginKind } ;
1822use rustc_middle:: traits:: util:: supertraits;
1923use rustc_middle:: ty:: fast_reject:: { simplify_type, TreatParams } ;
2024use rustc_middle:: ty:: print:: with_crate_prefix;
21- use rustc_middle:: ty:: { self , DefIdTree , ToPredicate , Ty , TyCtxt , TypeVisitable } ;
25+ use rustc_middle:: ty:: {
26+ self , DefIdTree , GenericArg , GenericArgKind , ToPredicate , Ty , TyCtxt , TypeVisitable ,
27+ } ;
2228use rustc_middle:: ty:: { IsSuggestable , ToPolyTraitRef } ;
2329use rustc_span:: symbol:: { kw, sym, Ident } ;
2430use rustc_span:: Symbol ;
@@ -280,7 +286,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
280286 ) {
281287 return None ;
282288 }
283-
284289 span = item_name. span ;
285290
286291 // Don't show generic arguments when the method can't be found in any implementation (#81576).
@@ -393,28 +398,118 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
393398 custom_span_label = true ;
394399 }
395400 if static_candidates. len ( ) == 1 {
396- let ty_str =
397- if let Some ( CandidateSource :: Impl ( impl_did) ) = static_candidates. get ( 0 ) {
398- // When the "method" is resolved through dereferencing, we really want the
399- // original type that has the associated function for accurate suggestions.
400- // (#61411)
401- let ty = tcx. at ( span) . type_of ( * impl_did) ;
402- match ( & ty. peel_refs ( ) . kind ( ) , & actual. peel_refs ( ) . kind ( ) ) {
403- ( ty:: Adt ( def, _) , ty:: Adt ( def_actual, _) ) if def == def_actual => {
404- // Use `actual` as it will have more `substs` filled in.
405- self . ty_to_value_string ( actual. peel_refs ( ) )
401+ let mut has_unsuggestable_args = false ;
402+ let ty_str = if let Some ( CandidateSource :: Impl ( impl_did) ) =
403+ static_candidates. get ( 0 )
404+ {
405+ // When the "method" is resolved through dereferencing, we really want the
406+ // original type that has the associated function for accurate suggestions.
407+ // (#61411)
408+ let ty = tcx. at ( span) . type_of ( * impl_did) ;
409+ match ( & ty. peel_refs ( ) . kind ( ) , & actual. peel_refs ( ) . kind ( ) ) {
410+ ( ty:: Adt ( def, _) , ty:: Adt ( def_actual, substs) ) if def == def_actual => {
411+ // If there are any inferred arguments, (`{integer}`), we should replace
412+ // them with underscores to allow the compiler to infer them
413+ let infer_substs: Vec < GenericArg < ' _ > > = substs
414+ . into_iter ( )
415+ . map ( |arg| {
416+ if !arg. is_suggestable ( tcx, true ) {
417+ has_unsuggestable_args = true ;
418+ match arg. unpack ( ) {
419+ GenericArgKind :: Lifetime ( _) => self
420+ . next_region_var ( RegionVariableOrigin :: MiscVariable (
421+ rustc_span:: DUMMY_SP ,
422+ ) )
423+ . into ( ) ,
424+ GenericArgKind :: Type ( _) => self
425+ . next_ty_var ( TypeVariableOrigin {
426+ span : rustc_span:: DUMMY_SP ,
427+ kind : TypeVariableOriginKind :: MiscVariable ,
428+ } )
429+ . into ( ) ,
430+ GenericArgKind :: Const ( arg) => self
431+ . next_const_var (
432+ arg. ty ( ) ,
433+ ConstVariableOrigin {
434+ span : rustc_span:: DUMMY_SP ,
435+ kind : ConstVariableOriginKind :: MiscVariable ,
436+ } ,
437+ )
438+ . into ( ) ,
439+ }
440+ } else {
441+ arg
442+ }
443+ } )
444+ . collect :: < Vec < _ > > ( ) ;
445+
446+ tcx. value_path_str_with_substs (
447+ def_actual. did ( ) ,
448+ tcx. intern_substs ( & infer_substs) ,
449+ )
450+ }
451+ _ => self . ty_to_value_string ( ty. peel_refs ( ) ) ,
452+ }
453+ } else {
454+ self . ty_to_value_string ( actual. peel_refs ( ) )
455+ } ;
456+ if let SelfSource :: MethodCall ( _) = source {
457+ let first_arg = if let Some ( CandidateSource :: Impl ( impl_did) ) = static_candidates. get ( 0 ) &&
458+ let Some ( assoc) = self . associated_value ( * impl_did, item_name) {
459+ let sig = self . tcx . fn_sig ( assoc. def_id ) ;
460+ if let Some ( first) = sig. inputs ( ) . skip_binder ( ) . get ( 0 ) {
461+ if first. peel_refs ( ) == rcvr_ty. peel_refs ( ) {
462+ None
463+ } else {
464+ Some ( if first. is_region_ptr ( ) {
465+ if first. is_mutable_ptr ( ) { "&mut " } else { "&" }
466+ } else {
467+ ""
468+ } )
406469 }
407- _ => self . ty_to_value_string ( ty. peel_refs ( ) ) ,
470+ } else {
471+ None
408472 }
409473 } else {
410- self . ty_to_value_string ( actual. peel_refs ( ) )
474+ None
475+ } ;
476+ let mut applicability = Applicability :: MachineApplicable ;
477+ let args = if let Some ( ( receiver, args) ) = args {
478+ // The first arg is the same kind as the receiver
479+ let explicit_args = if first_arg. is_some ( ) {
480+ std:: iter:: once ( receiver) . chain ( args. iter ( ) ) . collect :: < Vec < _ > > ( )
481+ } else {
482+ // There is no `Self` kind to infer the arguments from
483+ if has_unsuggestable_args {
484+ applicability = Applicability :: HasPlaceholders ;
485+ }
486+ args. iter ( ) . collect ( )
487+ } ;
488+ format ! (
489+ "({}{})" ,
490+ first_arg. unwrap_or( "" ) ,
491+ explicit_args
492+ . iter( )
493+ . map( |arg| tcx
494+ . sess
495+ . source_map( )
496+ . span_to_snippet( arg. span)
497+ . unwrap_or_else( |_| {
498+ applicability = Applicability :: HasPlaceholders ;
499+ "_" . to_owned( )
500+ } ) )
501+ . collect:: <Vec <_>>( )
502+ . join( ", " ) ,
503+ )
504+ } else {
505+ applicability = Applicability :: HasPlaceholders ;
506+ "(...)" . to_owned ( )
411507 } ;
412- if let SelfSource :: MethodCall ( expr) = source {
413508 err. span_suggestion (
414- expr . span . to ( span ) ,
509+ sugg_span ,
415510 "use associated function syntax instead" ,
416- format ! ( "{}::{}" , ty_str, item_name) ,
417- Applicability :: MachineApplicable ,
511+ format ! ( "{}::{}{} " , ty_str, item_name, args ) ,
512+ applicability ,
418513 ) ;
419514 } else {
420515 err. help ( & format ! ( "try with `{}::{}`" , ty_str, item_name, ) ) ;
@@ -1827,7 +1922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
18271922 /// Print out the type for use in value namespace.
18281923 fn ty_to_value_string ( & self , ty : Ty < ' tcx > ) -> String {
18291924 match ty. kind ( ) {
1830- ty:: Adt ( def, substs) => format ! ( "{}" , ty :: Instance :: new ( def. did( ) , substs) ) ,
1925+ ty:: Adt ( def, substs) => self . tcx . def_path_str_with_substs ( def. did ( ) , substs) ,
18311926 _ => self . ty_to_string ( ty) ,
18321927 }
18331928 }
0 commit comments