@@ -136,7 +136,7 @@ enum ProbeResult {
136
136
/// `mut`), or it has type `*mut T` and we convert it to `*const T`.
137
137
#[ derive( Debug , PartialEq , Copy , Clone ) ]
138
138
pub ( 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.
140
140
/// Unsizing is used to convert a `[T; N]` to `[T]`, which only makes sense when autorefing.
141
141
Autoref {
142
142
mutbl : hir:: Mutability ,
@@ -147,13 +147,17 @@ pub(crate) enum AutorefOrPtrAdjustment {
147
147
} ,
148
148
/// Receiver has type `*mut T`, convert to `*const T`
149
149
ToConstPtr ,
150
+
151
+ /// Reborrow a `Pin<&mut T>` or `Pin<&T>`.
152
+ ReborrowPin ( hir:: Mutability ) ,
150
153
}
151
154
152
155
impl AutorefOrPtrAdjustment {
153
156
fn get_unsize ( & self ) -> bool {
154
157
match self {
155
158
AutorefOrPtrAdjustment :: Autoref { mutbl : _, unsize } => * unsize,
156
159
AutorefOrPtrAdjustment :: ToConstPtr => false ,
160
+ AutorefOrPtrAdjustment :: ReborrowPin ( _) => false ,
157
161
}
158
162
}
159
163
}
@@ -1109,6 +1113,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1109
1113
unstable_candidates. as_deref_mut ( ) ,
1110
1114
)
1111
1115
} )
1116
+ . or_else ( || {
1117
+ self . pick_reborrow_pin_method (
1118
+ step,
1119
+ self_ty,
1120
+ unstable_candidates. as_deref_mut ( ) ,
1121
+ )
1122
+ } )
1112
1123
} )
1113
1124
} )
1114
1125
}
@@ -1133,13 +1144,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1133
1144
r. map ( |mut pick| {
1134
1145
pick. autoderefs = step. autoderefs ;
1135
1146
1136
- // Insert a `&*` or `&mut *` if this is a reference type:
1137
- if let ty:: Ref ( _, _, mutbl) = * step. self_ty . value . value . kind ( ) {
1138
- pick. autoderefs += 1 ;
1139
- pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
1140
- mutbl,
1141
- unsize : pick. autoref_or_ptr_adjustment . is_some_and ( |a| a. get_unsize ( ) ) ,
1142
- } )
1147
+ match * step. self_ty . value . value . kind ( ) {
1148
+ // Insert a `&*` or `&mut *` if this is a reference type:
1149
+ ty:: Ref ( _, _, mutbl) => {
1150
+ pick. autoderefs += 1 ;
1151
+ pick. autoref_or_ptr_adjustment = Some ( AutorefOrPtrAdjustment :: Autoref {
1152
+ mutbl,
1153
+ unsize : pick. autoref_or_ptr_adjustment . is_some_and ( |a| a. get_unsize ( ) ) ,
1154
+ } )
1155
+ }
1156
+
1157
+ ty:: Adt ( def, args)
1158
+ if self . tcx . features ( ) . pin_ergonomics
1159
+ && self . tcx . is_lang_item ( def. did ( ) , hir:: LangItem :: Pin ) =>
1160
+ {
1161
+ // make sure this is a pinned reference (and not a `Pin<Box>` or something)
1162
+ if let ty:: Ref ( _, _, mutbl) = args[ 0 ] . expect_ty ( ) . kind ( ) {
1163
+ pick. autoref_or_ptr_adjustment =
1164
+ Some ( AutorefOrPtrAdjustment :: ReborrowPin ( * mutbl) ) ;
1165
+ }
1166
+ }
1167
+
1168
+ _ => ( ) ,
1143
1169
}
1144
1170
1145
1171
pick
@@ -1170,6 +1196,43 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1170
1196
} )
1171
1197
}
1172
1198
1199
+ /// Looks for applicable methods if we reborrow a `Pin<&mut T>` as a `Pin<&T>`.
1200
+ #[ instrument( level = "debug" , skip( self , step, unstable_candidates) ) ]
1201
+ fn pick_reborrow_pin_method (
1202
+ & self ,
1203
+ step : & CandidateStep < ' tcx > ,
1204
+ self_ty : Ty < ' tcx > ,
1205
+ unstable_candidates : Option < & mut Vec < ( Candidate < ' tcx > , Symbol ) > > ,
1206
+ ) -> Option < PickResult < ' tcx > > {
1207
+ if !self . tcx . features ( ) . pin_ergonomics {
1208
+ return None ;
1209
+ }
1210
+
1211
+ // make sure self is a Pin<&mut T>
1212
+ let inner_ty = match self_ty. kind ( ) {
1213
+ ty:: Adt ( def, args) if self . tcx . is_lang_item ( def. did ( ) , hir:: LangItem :: Pin ) => {
1214
+ match args[ 0 ] . expect_ty ( ) . kind ( ) {
1215
+ ty:: Ref ( _, ty, hir:: Mutability :: Mut ) => * ty,
1216
+ _ => {
1217
+ return None ;
1218
+ }
1219
+ }
1220
+ }
1221
+ _ => return None ,
1222
+ } ;
1223
+
1224
+ let region = self . tcx . lifetimes . re_erased ;
1225
+ let autopin_ty = Ty :: new_pinned_ref ( self . tcx , region, inner_ty, hir:: Mutability :: Not ) ;
1226
+ self . pick_method ( autopin_ty, unstable_candidates) . map ( |r| {
1227
+ r. map ( |mut pick| {
1228
+ pick. autoderefs = step. autoderefs ;
1229
+ pick. autoref_or_ptr_adjustment =
1230
+ Some ( AutorefOrPtrAdjustment :: ReborrowPin ( hir:: Mutability :: Not ) ) ;
1231
+ pick
1232
+ } )
1233
+ } )
1234
+ }
1235
+
1173
1236
/// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a
1174
1237
/// special case for this is because going from `*mut T` to `*const T` with autoderefs and
1175
1238
/// autorefs would require dereferencing the pointer, which is not safe.
0 commit comments