@@ -2495,10 +2495,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
24952495 // Try alternative arbitrary self types that could fulfill this call.
24962496 // FIXME: probe for all types that *could* be arbitrary self-types, not
24972497 // 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" ) ,
25022506 ] {
25032507 match self . lookup_probe_for_diagnostic (
25042508 item_name,
@@ -2532,6 +2536,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25322536 Err ( _) => ( ) ,
25332537 }
25342538
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+ ) ) ;
25352550 for ( rcvr_ty, pre) in & [
25362551 ( Ty :: new_lang_item ( self . tcx , * rcvr_ty, LangItem :: OwnedBox ) , "Box::new" ) ,
25372552 ( Ty :: new_lang_item ( self . tcx , * rcvr_ty, LangItem :: Pin ) , "Pin::new" ) ,
@@ -2555,7 +2570,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25552570 // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
25562571 // implement the `AsRef` trait.
25572572 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 ) )
25592574 || 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) ;
25602575 // Make sure the method is defined for the *actual* receiver: we don't
25612576 // want to treat `Box<Self>` as a receiver if it only works because of
@@ -2567,7 +2582,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25672582 ) ;
25682583 err. multipart_suggestion (
25692584 "consider wrapping the receiver expression with the \
2570- appropriate type",
2585+ appropriate type",
25712586 vec ! [
25722587 ( rcvr. span. shrink_to_lo( ) , format!( "{pre}({post}" ) ) ,
25732588 ( rcvr. span. shrink_to_hi( ) , ")" . to_string( ) ) ,
@@ -2579,6 +2594,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
25792594 }
25802595 }
25812596 }
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+ }
25822630 }
25832631 }
25842632 if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
0 commit comments