@@ -214,6 +214,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
214214 ty:: Dynamic ( predicates, region, ty:: DynStar ) if self . tcx . features ( ) . dyn_star => {
215215 return self . coerce_dyn_star ( a, b, predicates, region) ;
216216 }
217+ ty:: Adt ( pin, _)
218+ if self . tcx . features ( ) . pin_ergonomics
219+ && pin. did ( ) == self . tcx . lang_items ( ) . pin_type ( ) . unwrap ( ) =>
220+ {
221+ return self . coerce_pin ( a, b) ;
222+ }
217223 _ => { }
218224 }
219225
@@ -774,6 +780,59 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
774780 } )
775781 }
776782
783+ /// Applies reborrowing for `Pin`
784+ ///
785+ /// We currently only support reborrowing `Pin<&mut T>` as `Pin<&mut T>`. This is accomplished
786+ /// by inserting a call to `Pin::as_mut` during MIR building.
787+ ///
788+ /// In the future we might want to support other reborrowing coercions, such as:
789+ /// - `Pin<&mut T>` as `Pin<&T>`
790+ /// - `Pin<&T>` as `Pin<&T>`
791+ /// - `Pin<Box<T>>` as `Pin<&T>`
792+ /// - `Pin<Box<T>>` as `Pin<&mut T>`
793+ #[ instrument( skip( self ) , level = "trace" ) ]
794+ fn coerce_pin ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
795+ // We need to make sure the two types are compatible for coercion.
796+ // Then we will build a ReborrowPin adjustment and return that as an InferOk.
797+
798+ // Right now we can only reborrow if this is a `Pin<&mut T>`.
799+ let can_reborrow = |ty : Ty < ' tcx > | {
800+ // Get the T out of Pin<T>
801+ let ty = match ty. kind ( ) {
802+ ty:: Adt ( pin, args) if pin. did ( ) == self . tcx . lang_items ( ) . pin_type ( ) . unwrap ( ) => {
803+ args[ 0 ] . expect_ty ( )
804+ }
805+ _ => {
806+ debug ! ( "can't reborrow {:?} as pinned" , ty) ;
807+ return None ;
808+ }
809+ } ;
810+ // Make sure the T is something we understand (just `&mut U` for now)
811+ match ty. kind ( ) {
812+ ty:: Ref ( region, ty, ty:: Mutability :: Mut ) => Some ( ( * region, * ty) ) ,
813+ _ => {
814+ debug ! ( "can't reborrow pin of inner type {:?}" , ty) ;
815+ None
816+ }
817+ }
818+ } ;
819+
820+ let ( _, _a_ty) = can_reborrow ( a) . ok_or ( TypeError :: Mismatch ) ?;
821+ let ( b_region, _b_ty) = can_reborrow ( b) . ok_or ( TypeError :: Mismatch ) ?;
822+
823+ // To complete the reborrow, we need to make sure we can unify the inner types, and if so we
824+ // add the adjustments.
825+ self . unify_and ( a, b, |_inner_ty| {
826+ vec ! [ Adjustment {
827+ kind: Adjust :: ReborrowPin ( AutoBorrow :: Ref (
828+ b_region,
829+ AutoBorrowMutability :: Mut { allow_two_phase_borrow: AllowTwoPhase :: No } ,
830+ ) ) ,
831+ target: b,
832+ } ]
833+ } )
834+ }
835+
777836 fn coerce_from_safe_fn < F , G > (
778837 & self ,
779838 a : Ty < ' tcx > ,
0 commit comments