@@ -743,34 +743,35 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
743743 self . unify_and ( a, b, [ ] , Adjust :: ReborrowPin ( mut_b) )
744744 }
745745
746- fn coerce_from_safe_fn (
746+ // Coerces an fnptr `a` to a fnptr `b`, this is only `fn(..)` to `unsafe fn(..)`.
747+ // Takes an `adjustment` used to get the `a` fnptr in the first place.
748+ fn coerce_fnptrs (
747749 & self ,
748- fn_ty_a : ty:: PolyFnSig < ' tcx > ,
749- b : Ty < ' tcx > ,
750+ a : ty:: PolyFnSig < ' tcx > ,
751+ b : ty :: PolyFnSig < ' tcx > ,
750752 adjustment : Option < Adjust > ,
751753 ) -> CoerceResult < ' tcx > {
752- debug_assert ! ( self . shallow_resolve( b) == b) ;
753-
754754 self . commit_if_ok ( |snapshot| {
755755 let outer_universe = self . infcx . universe ( ) ;
756756
757- let result = if let ty:: FnPtr ( _, hdr_b) = b. kind ( )
758- && fn_ty_a. safety ( ) . is_safe ( )
759- && hdr_b. safety . is_unsafe ( )
760- {
761- let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
757+ let a_ty = Ty :: new_fn_ptr ( self . tcx , a) ;
758+ let b_ty = Ty :: new_fn_ptr ( self . tcx , b) ;
759+
760+ // Handle coercing `fn(..)` to `unsafe fn(..)`
761+ let result = if a. safety ( ) . is_safe ( ) && b. safety ( ) . is_unsafe ( ) {
762+ let unsafe_a_ty = self . tcx . safe_to_unsafe_fn_ty ( a) ;
763+ let adjustment = adjustment. map ( |kind| Adjustment { kind, target : a_ty } ) ;
764+
762765 self . unify_and (
763- unsafe_a,
764- b,
765- adjustment
766- . map ( |kind| Adjustment { kind, target : Ty :: new_fn_ptr ( self . tcx , fn_ty_a) } ) ,
766+ unsafe_a_ty,
767+ b_ty,
768+ adjustment,
767769 Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
768770 )
769771 } else {
770- let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
771772 match adjustment {
772- Some ( adjust) => self . unify_and ( a , b , [ ] , adjust) ,
773- None => self . unify ( a , b ) ,
773+ Some ( adjust) => self . unify_and ( a_ty , b_ty , [ ] , adjust) ,
774+ None => self . unify ( a_ty , b_ty ) ,
774775 }
775776 } ;
776777
@@ -788,13 +789,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
788789
789790 fn coerce_from_fn_pointer (
790791 & self ,
791- fn_ty_a : ty:: PolyFnSig < ' tcx > ,
792+ a_sig : ty:: PolyFnSig < ' tcx > ,
792793 b : Ty < ' tcx > ,
793794 ) -> CoerceResult < ' tcx > {
794- debug ! ( ?fn_ty_a , ?b, "coerce_from_fn_pointer" ) ;
795+ debug ! ( ?a_sig , ?b, "coerce_from_fn_pointer" ) ;
795796 debug_assert ! ( self . shallow_resolve( b) == b) ;
796797
797- self . coerce_from_safe_fn ( fn_ty_a, b, None )
798+ match b. kind ( ) {
799+ ty:: FnPtr ( _, _) => self . coerce_fnptrs ( a_sig, b. fn_sig ( self . tcx ) , None ) ,
800+ _ => self . unify ( Ty :: new_fn_ptr ( self . tcx , a_sig) , b) ,
801+ }
798802 }
799803
800804 fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
@@ -838,9 +842,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
838842 let InferOk { value : a_sig, mut obligations } =
839843 self . at ( & self . cause , self . param_env ) . normalize ( a_sig) ;
840844
841- let InferOk { value, obligations : o2 } = self . coerce_from_safe_fn (
845+ let InferOk { value, obligations : o2 } = self . coerce_fnptrs (
842846 a_sig,
843- b,
847+ b. fn_sig ( self . tcx ) ,
844848 Some ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) ,
845849 ) ?;
846850
@@ -887,6 +891,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
887891 let pointer_ty =
888892 Ty :: new_fn_ptr ( self . tcx , self . tcx . signature_unclosure ( closure_sig, safety) ) ;
889893 debug ! ( "coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})" , a, b, pointer_ty) ;
894+
895+ // We don't use `self.coerce_fnptrs` as handling `fn` to `unsafe fn`
896+ // was trivial to do so ourselves.
890897 self . unify_and (
891898 pointer_ty,
892899 b,
0 commit comments