@@ -759,7 +759,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
759759 // `unsafe fn(arg0,arg1,...) -> _`
760760 let closure_sig = substs_a. as_closure ( ) . sig ( ) ;
761761 let unsafety = fn_ty. unsafety ( ) ;
762- let pointer_ty = self . tcx . coerce_closure_fn_ty ( closure_sig, unsafety) ;
762+ let pointer_ty =
763+ self . tcx . mk_fn_ptr ( self . tcx . signature_unclosure ( closure_sig, unsafety) ) ;
763764 debug ! ( "coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})" , a, b, pointer_ty) ;
764765 self . unify_and (
765766 pointer_ty,
@@ -875,23 +876,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
875876 debug ! ( "coercion::try_find_coercion_lub({:?}, {:?})" , prev_ty, new_ty) ;
876877
877878 // Special-case that coercion alone cannot handle:
878- // Two function item types of differing IDs or InternalSubsts.
879- if let ( & ty:: FnDef ( ..) , & ty:: FnDef ( ..) ) = ( & prev_ty. kind , & new_ty. kind ) {
880- // Don't reify if the function types have a LUB, i.e., they
881- // are the same function and their parameters have a LUB.
882- let lub_ty = self
883- . commit_if_ok ( |_| self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty) )
884- . map ( |ok| self . register_infer_ok_obligations ( ok) ) ;
885-
886- if lub_ty. is_ok ( ) {
887- // We have a LUB of prev_ty and new_ty, just return it.
888- return lub_ty;
879+ // Function items or Closures of differing IDs or InternalSubsts.
880+ let ( a_sig, b_sig) = match ( & prev_ty. kind , & new_ty. kind ) {
881+ ( & ty:: FnDef ( ..) , & ty:: FnDef ( ..) ) => {
882+ // Don't reify if the function types have a LUB, i.e., they
883+ // are the same function and their parameters have a LUB.
884+ match self . commit_if_ok ( |_| self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty) ) {
885+ // We have a LUB of prev_ty and new_ty, just return it.
886+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
887+ Err ( _) => ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) ) ,
888+ }
889889 }
890-
890+ ( & ty:: Closure ( _, substs) , & ty:: FnDef ( ..) ) => {
891+ let b_sig = new_ty. fn_sig ( self . tcx ) ;
892+ let a_sig =
893+ self . tcx . signature_unclosure ( substs. as_closure ( ) . sig ( ) , b_sig. unsafety ( ) ) ;
894+ ( Some ( a_sig) , Some ( b_sig) )
895+ }
896+ ( & ty:: FnDef ( ..) , & ty:: Closure ( _, substs) ) => {
897+ let a_sig = prev_ty. fn_sig ( self . tcx ) ;
898+ let b_sig =
899+ self . tcx . signature_unclosure ( substs. as_closure ( ) . sig ( ) , a_sig. unsafety ( ) ) ;
900+ ( Some ( a_sig) , Some ( b_sig) )
901+ }
902+ ( & ty:: Closure ( _, substs_a) , & ty:: Closure ( _, substs_b) ) => (
903+ Some (
904+ self . tcx
905+ . signature_unclosure ( substs_a. as_closure ( ) . sig ( ) , hir:: Unsafety :: Normal ) ,
906+ ) ,
907+ Some (
908+ self . tcx
909+ . signature_unclosure ( substs_b. as_closure ( ) . sig ( ) , hir:: Unsafety :: Normal ) ,
910+ ) ,
911+ ) ,
912+ _ => ( None , None ) ,
913+ } ;
914+ if let ( Some ( a_sig) , Some ( b_sig) ) = ( a_sig, b_sig) {
891915 // The signature must match.
892- let a_sig = prev_ty. fn_sig ( self . tcx ) ;
893916 let a_sig = self . normalize_associated_types_in ( new. span , & a_sig) ;
894- let b_sig = new_ty. fn_sig ( self . tcx ) ;
895917 let b_sig = self . normalize_associated_types_in ( new. span , & b_sig) ;
896918 let sig = self
897919 . at ( cause, self . param_env )
@@ -901,17 +923,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
901923
902924 // Reify both sides and return the reified fn pointer type.
903925 let fn_ptr = self . tcx . mk_fn_ptr ( sig) ;
904- for expr in exprs. iter ( ) . map ( |e| e. as_coercion_site ( ) ) . chain ( Some ( new) ) {
905- // The only adjustment that can produce an fn item is
906- // `NeverToAny`, so this should always be valid.
926+ let prev_adjustment = match prev_ty. kind {
927+ ty:: Closure ( ..) => Adjust :: Pointer ( PointerCast :: ClosureFnPointer ( a_sig. unsafety ( ) ) ) ,
928+ ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
929+ _ => unreachable ! ( ) ,
930+ } ;
931+ let next_adjustment = match new_ty. kind {
932+ ty:: Closure ( ..) => Adjust :: Pointer ( PointerCast :: ClosureFnPointer ( b_sig. unsafety ( ) ) ) ,
933+ ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
934+ _ => unreachable ! ( ) ,
935+ } ;
936+ for expr in exprs. iter ( ) . map ( |e| e. as_coercion_site ( ) ) {
907937 self . apply_adjustments (
908938 expr,
909- vec ! [ Adjustment {
910- kind: Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
911- target: fn_ptr,
912- } ] ,
939+ vec ! [ Adjustment { kind: prev_adjustment. clone( ) , target: fn_ptr } ] ,
913940 ) ;
914941 }
942+ self . apply_adjustments ( new, vec ! [ Adjustment { kind: next_adjustment, target: fn_ptr } ] ) ;
915943 return Ok ( fn_ptr) ;
916944 }
917945
0 commit comments