@@ -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,63 @@ 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 non-capturing closures of differing IDs or InternalSubsts.
880+ let ( a_sig, b_sig) = {
881+ let is_capturing_closure = |ty| {
882+ if let & ty:: Closure ( _, substs) = ty {
883+ substs. as_closure ( ) . upvar_tys ( ) . next ( ) . is_some ( )
884+ } else {
885+ false
886+ }
887+ } ;
888+ if is_capturing_closure ( & prev_ty. kind ) || is_capturing_closure ( & new_ty. kind ) {
889+ ( None , None )
890+ } else {
891+ match ( & prev_ty. kind , & new_ty. kind ) {
892+ ( & ty:: FnDef ( ..) , & ty:: FnDef ( ..) ) => {
893+ // Don't reify if the function types have a LUB, i.e., they
894+ // are the same function and their parameters have a LUB.
895+ match self
896+ . commit_if_ok ( |_| self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty) )
897+ {
898+ // We have a LUB of prev_ty and new_ty, just return it.
899+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
900+ Err ( _) => {
901+ ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) )
902+ }
903+ }
904+ }
905+ ( & ty:: Closure ( _, substs) , & ty:: FnDef ( ..) ) => {
906+ let b_sig = new_ty. fn_sig ( self . tcx ) ;
907+ let a_sig = self
908+ . tcx
909+ . signature_unclosure ( substs. as_closure ( ) . sig ( ) , b_sig. unsafety ( ) ) ;
910+ ( Some ( a_sig) , Some ( b_sig) )
911+ }
912+ ( & ty:: FnDef ( ..) , & ty:: Closure ( _, substs) ) => {
913+ let a_sig = prev_ty. fn_sig ( self . tcx ) ;
914+ let b_sig = self
915+ . tcx
916+ . signature_unclosure ( substs. as_closure ( ) . sig ( ) , a_sig. unsafety ( ) ) ;
917+ ( Some ( a_sig) , Some ( b_sig) )
918+ }
919+ ( & ty:: Closure ( _, substs_a) , & ty:: Closure ( _, substs_b) ) => (
920+ Some ( self . tcx . signature_unclosure (
921+ substs_a. as_closure ( ) . sig ( ) ,
922+ hir:: Unsafety :: Normal ,
923+ ) ) ,
924+ Some ( self . tcx . signature_unclosure (
925+ substs_b. as_closure ( ) . sig ( ) ,
926+ hir:: Unsafety :: Normal ,
927+ ) ) ,
928+ ) ,
929+ _ => ( None , None ) ,
930+ }
889931 }
890-
932+ } ;
933+ if let ( Some ( a_sig) , Some ( b_sig) ) = ( a_sig, b_sig) {
891934 // The signature must match.
892- let a_sig = prev_ty. fn_sig ( self . tcx ) ;
893935 let a_sig = self . normalize_associated_types_in ( new. span , & a_sig) ;
894- let b_sig = new_ty. fn_sig ( self . tcx ) ;
895936 let b_sig = self . normalize_associated_types_in ( new. span , & b_sig) ;
896937 let sig = self
897938 . at ( cause, self . param_env )
@@ -901,17 +942,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
901942
902943 // Reify both sides and return the reified fn pointer type.
903944 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.
945+ let prev_adjustment = match prev_ty. kind {
946+ ty:: Closure ( ..) => Adjust :: Pointer ( PointerCast :: ClosureFnPointer ( a_sig. unsafety ( ) ) ) ,
947+ ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
948+ _ => unreachable ! ( ) ,
949+ } ;
950+ let next_adjustment = match new_ty. kind {
951+ ty:: Closure ( ..) => Adjust :: Pointer ( PointerCast :: ClosureFnPointer ( b_sig. unsafety ( ) ) ) ,
952+ ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
953+ _ => unreachable ! ( ) ,
954+ } ;
955+ for expr in exprs. iter ( ) . map ( |e| e. as_coercion_site ( ) ) {
907956 self . apply_adjustments (
908957 expr,
909- vec ! [ Adjustment {
910- kind: Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
911- target: fn_ptr,
912- } ] ,
958+ vec ! [ Adjustment { kind: prev_adjustment. clone( ) , target: fn_ptr } ] ,
913959 ) ;
914960 }
961+ self . apply_adjustments ( new, vec ! [ Adjustment { kind: next_adjustment, target: fn_ptr } ] ) ;
915962 return Ok ( fn_ptr) ;
916963 }
917964
0 commit comments