@@ -797,34 +797,35 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
797797 self . unify_and ( a, b, [ ] , Adjust :: ReborrowPin ( mut_b) )
798798 }
799799
800- fn coerce_from_safe_fn (
800+ // Coerces an fnptr `a` to a fnptr `b`, this is only `fn(..)` to `unsafe fn(..)`.
801+ // Takes an `adjustment` used to get the `a` fnptr in the first place.
802+ fn coerce_fnptrs (
801803 & self ,
802- fn_ty_a : ty:: PolyFnSig < ' tcx > ,
803- b : Ty < ' tcx > ,
804+ a : ty:: PolyFnSig < ' tcx > ,
805+ b : ty :: PolyFnSig < ' tcx > ,
804806 adjustment : Option < Adjust > ,
805807 ) -> CoerceResult < ' tcx > {
806- debug_assert ! ( self . shallow_resolve( b) == b) ;
807-
808808 self . commit_if_ok ( |snapshot| {
809809 let outer_universe = self . infcx . universe ( ) ;
810810
811- let result = if let ty:: FnPtr ( _, hdr_b) = b. kind ( )
812- && fn_ty_a. safety ( ) . is_safe ( )
813- && hdr_b. safety . is_unsafe ( )
814- {
815- let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
811+ let a_ty = Ty :: new_fn_ptr ( self . tcx , a) ;
812+ let b_ty = Ty :: new_fn_ptr ( self . tcx , b) ;
813+
814+ // Handle coercing `fn(..)` to `unsafe fn(..)`
815+ let result = if a. safety ( ) . is_safe ( ) && b. safety ( ) . is_unsafe ( ) {
816+ let unsafe_a_ty = self . tcx . safe_to_unsafe_fn_ty ( a) ;
817+ let adjustment = adjustment. map ( |kind| Adjustment { kind, target : a_ty } ) ;
818+
816819 self . unify_and (
817- unsafe_a,
818- b,
819- adjustment
820- . map ( |kind| Adjustment { kind, target : Ty :: new_fn_ptr ( self . tcx , fn_ty_a) } ) ,
820+ unsafe_a_ty,
821+ b_ty,
822+ adjustment,
821823 Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
822824 )
823825 } else {
824- let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
825826 match adjustment {
826- Some ( adjust) => self . unify_and ( a , b , [ ] , adjust) ,
827- None => self . unify ( a , b ) ,
827+ Some ( adjust) => self . unify_and ( a_ty , b_ty , [ ] , adjust) ,
828+ None => self . unify ( a_ty , b_ty ) ,
828829 }
829830 } ;
830831
@@ -842,13 +843,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
842843
843844 fn coerce_from_fn_pointer (
844845 & self ,
845- fn_ty_a : ty:: PolyFnSig < ' tcx > ,
846+ a_sig : ty:: PolyFnSig < ' tcx > ,
846847 b : Ty < ' tcx > ,
847848 ) -> CoerceResult < ' tcx > {
848- debug ! ( ?fn_ty_a , ?b, "coerce_from_fn_pointer" ) ;
849+ debug ! ( ?a_sig , ?b, "coerce_from_fn_pointer" ) ;
849850 debug_assert ! ( self . shallow_resolve( b) == b) ;
850851
851- self . coerce_from_safe_fn ( fn_ty_a, b, None )
852+ match b. kind ( ) {
853+ ty:: FnPtr ( _, _) => self . coerce_fnptrs ( a_sig, b. fn_sig ( self . tcx ) , None ) ,
854+ _ => self . unify ( Ty :: new_fn_ptr ( self . tcx , a_sig) , b) ,
855+ }
852856 }
853857
854858 fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
@@ -892,9 +896,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
892896 let InferOk { value : a_sig, mut obligations } =
893897 self . at ( & self . cause , self . param_env ) . normalize ( a_sig) ;
894898
895- let InferOk { value, obligations : o2 } = self . coerce_from_safe_fn (
899+ let InferOk { value, obligations : o2 } = self . coerce_fnptrs (
896900 a_sig,
897- b,
901+ b. fn_sig ( self . tcx ) ,
898902 Some ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) ,
899903 ) ?;
900904
@@ -941,6 +945,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
941945 let pointer_ty =
942946 Ty :: new_fn_ptr ( self . tcx , self . tcx . signature_unclosure ( closure_sig, safety) ) ;
943947 debug ! ( "coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})" , a, b, pointer_ty) ;
948+
949+ // We don't use `self.coerce_fnptrs` as handling `fn` to `unsafe fn`
950+ // was trivial to do so ourselves.
944951 self . unify_and (
945952 pointer_ty,
946953 b,
0 commit comments