@@ -772,34 +772,35 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
772772 self . unify_and ( a, b, [ ] , Adjust :: ReborrowPin ( mut_b) )
773773 }
774774
775- fn coerce_from_safe_fn (
775+ // Coerces an fnptr `a` to a fnptr `b`, this is only `fn(..)` to `unsafe fn(..)`.
776+ // Takes an `adjustment` used to get the `a` fnptr in the first place.
777+ fn coerce_fnptrs (
776778 & self ,
777- fn_ty_a : ty:: PolyFnSig < ' tcx > ,
778- b : Ty < ' tcx > ,
779+ a : ty:: PolyFnSig < ' tcx > ,
780+ b : ty :: PolyFnSig < ' tcx > ,
779781 adjustment : Option < Adjust > ,
780782 ) -> CoerceResult < ' tcx > {
781- debug_assert ! ( self . shallow_resolve( b) == b) ;
782-
783783 self . commit_if_ok ( |snapshot| {
784784 let outer_universe = self . infcx . universe ( ) ;
785785
786- let result = if let ty:: FnPtr ( _, hdr_b) = b. kind ( )
787- && fn_ty_a. safety ( ) . is_safe ( )
788- && hdr_b. safety . is_unsafe ( )
789- {
790- let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
786+ let a_ty = Ty :: new_fn_ptr ( self . tcx , a) ;
787+ let b_ty = Ty :: new_fn_ptr ( self . tcx , b) ;
788+
789+ // Handle coercing `fn(..)` to `unsafe fn(..)`
790+ let result = if a. safety ( ) . is_safe ( ) && b. safety ( ) . is_unsafe ( ) {
791+ let unsafe_a_ty = self . tcx . safe_to_unsafe_fn_ty ( a) ;
792+ let adjustment = adjustment. map ( |kind| Adjustment { kind, target : a_ty } ) ;
793+
791794 self . unify_and (
792- unsafe_a,
793- b,
794- adjustment
795- . map ( |kind| Adjustment { kind, target : Ty :: new_fn_ptr ( self . tcx , fn_ty_a) } ) ,
795+ unsafe_a_ty,
796+ b_ty,
797+ adjustment,
796798 Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
797799 )
798800 } else {
799- let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
800801 match adjustment {
801- Some ( adjust) => self . unify_and ( a , b , [ ] , adjust) ,
802- None => self . unify ( a , b ) ,
802+ Some ( adjust) => self . unify_and ( a_ty , b_ty , [ ] , adjust) ,
803+ None => self . unify ( a_ty , b_ty ) ,
803804 }
804805 } ;
805806
@@ -817,13 +818,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
817818
818819 fn coerce_from_fn_pointer (
819820 & self ,
820- fn_ty_a : ty:: PolyFnSig < ' tcx > ,
821+ a_sig : ty:: PolyFnSig < ' tcx > ,
821822 b : Ty < ' tcx > ,
822823 ) -> CoerceResult < ' tcx > {
823- debug ! ( ?fn_ty_a , ?b, "coerce_from_fn_pointer" ) ;
824+ debug ! ( ?a_sig , ?b, "coerce_from_fn_pointer" ) ;
824825 debug_assert ! ( self . shallow_resolve( b) == b) ;
825826
826- self . coerce_from_safe_fn ( fn_ty_a, b, None )
827+ match b. kind ( ) {
828+ ty:: FnPtr ( _, _) => self . coerce_fnptrs ( a_sig, b. fn_sig ( self . tcx ) , None ) ,
829+ _ => self . unify ( Ty :: new_fn_ptr ( self . tcx , a_sig) , b) ,
830+ }
827831 }
828832
829833 fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
@@ -867,9 +871,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
867871 let InferOk { value : a_sig, mut obligations } =
868872 self . at ( & self . cause , self . param_env ) . normalize ( a_sig) ;
869873
870- let InferOk { value, obligations : o2 } = self . coerce_from_safe_fn (
874+ let InferOk { value, obligations : o2 } = self . coerce_fnptrs (
871875 a_sig,
872- b,
876+ b. fn_sig ( self . tcx ) ,
873877 Some ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) ,
874878 ) ?;
875879
@@ -916,6 +920,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
916920 let pointer_ty =
917921 Ty :: new_fn_ptr ( self . tcx , self . tcx . signature_unclosure ( closure_sig, safety) ) ;
918922 debug ! ( "coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})" , a, b, pointer_ty) ;
923+
924+ // We don't use `self.coerce_fnptrs` as handling `fn` to `unsafe fn`
925+ // was trivial to do so ourselves.
919926 self . unify_and (
920927 pointer_ty,
921928 b,
0 commit comments