@@ -2495,10 +2495,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2495
2495
// Try alternative arbitrary self types that could fulfill this call.
2496
2496
// FIXME: probe for all types that *could* be arbitrary self-types, not
2497
2497
// just this list.
2498
- for ( rcvr_ty, post) in & [
2499
- ( rcvr_ty, "" ) ,
2500
- ( Ty :: new_mut_ref ( self . tcx , self . tcx . lifetimes . re_erased , rcvr_ty) , "&mut " ) ,
2501
- ( Ty :: new_imm_ref ( self . tcx , self . tcx . lifetimes . re_erased , rcvr_ty) , "&" ) ,
2498
+ for ( rcvr_ty, post, pin_call) in & [
2499
+ ( rcvr_ty, "" , "" ) ,
2500
+ (
2501
+ Ty :: new_mut_ref ( self . tcx , self . tcx . lifetimes . re_erased , rcvr_ty) ,
2502
+ "&mut " ,
2503
+ "as_mut" ,
2504
+ ) ,
2505
+ ( Ty :: new_imm_ref ( self . tcx , self . tcx . lifetimes . re_erased , rcvr_ty) , "&" , "as_ref" ) ,
2502
2506
] {
2503
2507
match self . lookup_probe_for_diagnostic (
2504
2508
item_name,
@@ -2532,6 +2536,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2532
2536
Err ( _) => ( ) ,
2533
2537
}
2534
2538
2539
+ let pred = ty:: TraitRef :: new (
2540
+ self . tcx ,
2541
+ self . tcx . lang_items ( ) . unpin_trait ( ) . unwrap ( ) ,
2542
+ [ * rcvr_ty] ,
2543
+ ) ;
2544
+ let unpin = self . predicate_must_hold_considering_regions ( & Obligation :: new (
2545
+ self . tcx ,
2546
+ ObligationCause :: misc ( rcvr. span , self . body_id ) ,
2547
+ self . param_env ,
2548
+ pred,
2549
+ ) ) ;
2535
2550
for ( rcvr_ty, pre) in & [
2536
2551
( Ty :: new_lang_item ( self . tcx , * rcvr_ty, LangItem :: OwnedBox ) , "Box::new" ) ,
2537
2552
( Ty :: new_lang_item ( self . tcx , * rcvr_ty, LangItem :: Pin ) , "Pin::new" ) ,
@@ -2555,7 +2570,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2555
2570
// Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
2556
2571
// implement the `AsRef` trait.
2557
2572
let skip = skippable. contains ( & did)
2558
- || ( ( "Pin::new" == * pre) && ( sym:: as_ref == item_name. name ) )
2573
+ || ( ( "Pin::new" == * pre) && ( ( sym:: as_ref == item_name. name ) || !unpin ) )
2559
2574
|| inputs_len. is_some_and ( |inputs_len| pick. item . kind == ty:: AssocKind :: Fn && self . tcx . fn_sig ( pick. item . def_id ) . skip_binder ( ) . skip_binder ( ) . inputs ( ) . len ( ) != inputs_len) ;
2560
2575
// Make sure the method is defined for the *actual* receiver: we don't
2561
2576
// want to treat `Box<Self>` as a receiver if it only works because of
@@ -2567,7 +2582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2567
2582
) ;
2568
2583
err. multipart_suggestion (
2569
2584
"consider wrapping the receiver expression with the \
2570
- appropriate type",
2585
+ appropriate type",
2571
2586
vec ! [
2572
2587
( rcvr. span. shrink_to_lo( ) , format!( "{pre}({post}" ) ) ,
2573
2588
( rcvr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
@@ -2579,6 +2594,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
2579
2594
}
2580
2595
}
2581
2596
}
2597
+ // We special case the situation where `Pin::new` wouldn't work, and isntead
2598
+ // suggest using the `pin!()` macro instead.
2599
+ if let Some ( new_rcvr_t) = Ty :: new_lang_item ( self . tcx , * rcvr_ty, LangItem :: Pin )
2600
+ && !alt_rcvr_sugg
2601
+ && !unpin
2602
+ && sym:: as_ref != item_name. name
2603
+ && * pin_call != ""
2604
+ && let Ok ( pick) = self . lookup_probe_for_diagnostic (
2605
+ item_name,
2606
+ new_rcvr_t,
2607
+ rcvr,
2608
+ ProbeScope :: AllTraits ,
2609
+ return_type,
2610
+ )
2611
+ && !skippable. contains ( & Some ( pick. item . container_id ( self . tcx ) ) )
2612
+ && pick. autoderefs == 0
2613
+ && inputs_len. is_some_and ( |inputs_len| pick. item . kind == ty:: AssocKind :: Fn && self . tcx . fn_sig ( pick. item . def_id ) . skip_binder ( ) . skip_binder ( ) . inputs ( ) . len ( ) == inputs_len)
2614
+ {
2615
+ let indent = self . tcx . sess
2616
+ . source_map ( )
2617
+ . indentation_before ( rcvr. span )
2618
+ . unwrap_or_else ( || " " . to_string ( ) ) ;
2619
+ err. multipart_suggestion (
2620
+ "consider pinning the expression" ,
2621
+ vec ! [
2622
+ ( rcvr. span. shrink_to_lo( ) , format!( "let mut pinned = std::pin::pin!(" ) ) ,
2623
+ ( rcvr. span. shrink_to_hi( ) , format!( ");\n {indent}pinned.{pin_call}()" ) ) ,
2624
+ ] ,
2625
+ Applicability :: MaybeIncorrect ,
2626
+ ) ;
2627
+ // We don't care about the other suggestions.
2628
+ alt_rcvr_sugg = true ;
2629
+ }
2582
2630
}
2583
2631
}
2584
2632
if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
0 commit comments