@@ -136,7 +136,7 @@ enum ProbeResult {
136136/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
137137#[ derive( Debug , PartialEq , Copy , Clone ) ]
138138pub ( crate ) enum AutorefOrPtrAdjustment {
139- /// Receiver has type `T`, add `&` or `&mut` (it `T` is `mut`), and maybe also "unsize" it.
139+ /// Receiver has type `T`, add `&` or `&mut` (if `T` is `mut`), and maybe also "unsize" it.
140140 /// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
141141 Autoref {
142142 mutbl : hir:: Mutability ,
@@ -147,13 +147,17 @@ pub(crate) enum AutorefOrPtrAdjustment {
147147 } ,
148148 /// Receiver has type `*mut T`, convert to `*const T`
149149 ToConstPtr ,
150+
151+ /// Reborrow a `Pin<&mut T>` or `Pin<&T>`.
152+ ReborrowPin ( hir:: Mutability ) ,
150153}
151154
152155impl AutorefOrPtrAdjustment {
153156 fn get_unsize ( & self ) -> bool {
154157 match self {
155158 AutorefOrPtrAdjustment :: Autoref { mutbl : _, unsize } => * unsize,
156159 AutorefOrPtrAdjustment :: ToConstPtr => false ,
160+ AutorefOrPtrAdjustment :: ReborrowPin ( _) => false ,
157161 }
158162 }
159163}
@@ -1103,6 +1107,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11031107 unstable_candidates. as_deref_mut ( ) ,
11041108 )
11051109 } )
1110+ . or_else ( || {
1111+ self . pick_reborrow_pin_method (
1112+ step,
1113+ self_ty,
1114+ unstable_candidates. as_deref_mut ( ) ,
1115+ )
1116+ } )
11061117 } )
11071118 } )
11081119 }
@@ -1127,13 +1138,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11271138 r. map ( |mut pick| {
11281139 pick. autoderefs = step. autoderefs ;
11291140
1130- // Insert a `&*` or `&mut *` if this is a reference type:
1131- if let ty:: Ref ( _, _, mutbl) = * step. self_ty . value . value . kind ( ) {
1132- pick. autoderefs += 1 ;
1133- pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
1134- mutbl,
1135- unsize : pick. autoref_or_ptr_adjustment . is_some_and ( |a| a. get_unsize ( ) ) ,
1136- } )
1141+ match * step. self_ty . value . value . kind ( ) {
1142+ // Insert a `&*` or `&mut *` if this is a reference type:
1143+ ty:: Ref ( _, _, mutbl) => {
1144+ pick. autoderefs += 1 ;
1145+ pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
1146+ mutbl,
1147+ unsize : pick. autoref_or_ptr_adjustment . is_some_and ( |a| a. get_unsize ( ) ) ,
1148+ } )
1149+ }
1150+
1151+ ty:: Adt ( def, args)
1152+ if self . tcx . features ( ) . pin_ergonomics
1153+ && self . tcx . is_lang_item ( def. did ( ) , hir:: LangItem :: Pin ) =>
1154+ {
1155+ // make sure this is a pinned reference (and not a `Pin<Box>` or something)
1156+ if let ty:: Ref ( _, _, mutbl) = args[ 0 ] . expect_ty ( ) . kind ( ) {
1157+ pick. autoref_or_ptr_adjustment =
1158+ Some ( AutorefOrPtrAdjustment :: ReborrowPin ( * mutbl) ) ;
1159+ }
1160+ }
1161+
1162+ _ => ( ) ,
11371163 }
11381164
11391165 pick
@@ -1164,6 +1190,43 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
11641190 } )
11651191 }
11661192
1193+ /// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
1194+ #[ instrument( level = "debug" , skip( self , step, unstable_candidates) ) ]
1195+ fn pick_reborrow_pin_method (
1196+ & self ,
1197+ step : & CandidateStep < ' tcx > ,
1198+ self_ty : Ty < ' tcx > ,
1199+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1200+ ) -> Option < PickResult < ' tcx > > {
1201+ if !self . tcx . features ( ) . pin_ergonomics {
1202+ return None ;
1203+ }
1204+
1205+ // make sure self is a Pin<&mut T>
1206+ let inner_ty = match self_ty. kind ( ) {
1207+ ty:: Adt ( def, args) if self . tcx . is_lang_item ( def. did ( ) , hir:: LangItem :: Pin ) => {
1208+ match args[ 0 ] . expect_ty ( ) . kind ( ) {
1209+ ty:: Ref ( _, ty, hir:: Mutability :: Mut ) => * ty,
1210+ _ => {
1211+ return None ;
1212+ }
1213+ }
1214+ }
1215+ _ => return None ,
1216+ } ;
1217+
1218+ let region = self . tcx . lifetimes . re_erased ;
1219+ let autopin_ty = Ty :: new_pinned_ref ( self . tcx , region, inner_ty, hir:: Mutability :: Not ) ;
1220+ self . pick_method ( autopin_ty, unstable_candidates) . map ( |r| {
1221+ r. map ( |mut pick| {
1222+ pick. autoderefs = step. autoderefs ;
1223+ pick. autoref_or_ptr_adjustment =
1224+ Some ( AutorefOrPtrAdjustment :: ReborrowPin ( hir:: Mutability :: Not ) ) ;
1225+ pick
1226+ } )
1227+ } )
1228+ }
1229+
11671230 /// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a
11681231 /// special case for this is because going from `*mut T` to `*const T` with autoderefs and
11691232 /// autorefs would require dereferencing the pointer, which is not safe.
0 commit comments