@@ -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
}
@@ -1103,6 +1107,13 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1103
1107
unstable_candidates. as_deref_mut ( ) ,
1104
1108
)
1105
1109
} )
1110
+ . or_else ( || {
1111
+ self . pick_reborrow_pin_method (
1112
+ step,
1113
+ self_ty,
1114
+ unstable_candidates. as_deref_mut ( ) ,
1115
+ )
1116
+ } )
1106
1117
} )
1107
1118
} )
1108
1119
}
@@ -1127,13 +1138,28 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1127
1138
r. map ( |mut pick| {
1128
1139
pick. autoderefs = step. autoderefs ;
1129
1140
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
+ _ => ( ) ,
1137
1163
}
1138
1164
1139
1165
pick
@@ -1164,6 +1190,43 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
1164
1190
} )
1165
1191
}
1166
1192
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
+
1167
1230
/// If `self_ty` is `*mut T` then this picks `*const T` methods. The reason why we have a
1168
1231
/// special case for this is because going from `*mut T` to `*const T` with autoderefs and
1169
1232
/// autorefs would require dereferencing the pointer, which is not safe.
0 commit comments