@@ -14,11 +14,17 @@ use rustc_hir::def::DefKind;
14
14
use rustc_hir:: def_id:: DefId ;
15
15
use rustc_hir:: lang_items:: LangItem ;
16
16
use 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 } ;
18
22
use rustc_middle:: traits:: util:: supertraits;
19
23
use rustc_middle:: ty:: fast_reject:: { simplify_type, TreatParams } ;
20
24
use 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
+ } ;
22
28
use rustc_middle:: ty:: { IsSuggestable , ToPolyTraitRef } ;
23
29
use rustc_span:: symbol:: { kw, sym, Ident } ;
24
30
use rustc_span:: Symbol ;
@@ -280,7 +286,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
280
286
) {
281
287
return None ;
282
288
}
283
-
284
289
span = item_name. span ;
285
290
286
291
// 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> {
393
398
custom_span_label = true ;
394
399
}
395
400
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
+ } )
406
469
}
407
- _ => self . ty_to_value_string ( ty. peel_refs ( ) ) ,
470
+ } else {
471
+ None
408
472
}
409
473
} 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 ( )
411
507
} ;
412
- if let SelfSource :: MethodCall ( expr) = source {
413
508
err. span_suggestion (
414
- expr . span . to ( span ) ,
509
+ sugg_span ,
415
510
"use associated function syntax instead" ,
416
- format ! ( "{}::{}" , ty_str, item_name) ,
417
- Applicability :: MachineApplicable ,
511
+ format ! ( "{}::{}{} " , ty_str, item_name, args ) ,
512
+ applicability ,
418
513
) ;
419
514
} else {
420
515
err. help ( & format ! ( "try with `{}::{}`" , ty_str, item_name, ) ) ;
@@ -1827,7 +1922,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1827
1922
/// Print out the type for use in value namespace.
1828
1923
fn ty_to_value_string ( & self , ty : Ty < ' tcx > ) -> String {
1829
1924
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) ,
1831
1926
_ => self . ty_to_string ( ty) ,
1832
1927
}
1833
1928
}
0 commit comments