@@ -214,6 +214,12 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
214
214
ty:: Dynamic ( predicates, region, ty:: DynStar ) if self . tcx . features ( ) . dyn_star => {
215
215
return self . coerce_dyn_star ( a, b, predicates, region) ;
216
216
}
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
+ }
217
223
_ => { }
218
224
}
219
225
@@ -774,6 +780,59 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
774
780
} )
775
781
}
776
782
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
+
777
836
fn coerce_from_safe_fn < F , G > (
778
837
& self ,
779
838
a : Ty < ' tcx > ,
0 commit comments