@@ -793,7 +793,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
793793 // `unsafe fn(arg0,arg1,...) -> _`
794794 let closure_sig = substs_a. as_closure ( ) . sig ( ) ;
795795 let unsafety = fn_ty. unsafety ( ) ;
796- let pointer_ty = self . tcx . coerce_closure_fn_ty ( closure_sig, unsafety) ;
796+ let pointer_ty =
797+ self . tcx . mk_fn_ptr ( self . tcx . signature_unclosure ( closure_sig, unsafety) ) ;
797798 debug ! ( "coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})" , a, b, pointer_ty) ;
798799 self . unify_and (
799800 pointer_ty,
@@ -909,23 +910,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
909910 debug ! ( "coercion::try_find_coercion_lub({:?}, {:?})" , prev_ty, new_ty) ;
910911
911912 // Special-case that coercion alone cannot handle:
912- // Two function item types of differing IDs or InternalSubsts.
913- if let ( & ty:: FnDef ( ..) , & ty:: FnDef ( ..) ) = ( & prev_ty. kind , & new_ty. kind ) {
914- // Don't reify if the function types have a LUB, i.e., they
915- // are the same function and their parameters have a LUB.
916- let lub_ty = self
917- . commit_if_ok ( |_| self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty) )
918- . map ( |ok| self . register_infer_ok_obligations ( ok) ) ;
919-
920- if lub_ty. is_ok ( ) {
921- // We have a LUB of prev_ty and new_ty, just return it.
922- return lub_ty;
913+ // Function items or non-capturing closures of differing IDs or InternalSubsts.
914+ let ( a_sig, b_sig) = {
915+ let is_capturing_closure = |ty| {
916+ if let & ty:: Closure ( _, substs) = ty {
917+ substs. as_closure ( ) . upvar_tys ( ) . next ( ) . is_some ( )
918+ } else {
919+ false
920+ }
921+ } ;
922+ if is_capturing_closure ( & prev_ty. kind ) || is_capturing_closure ( & new_ty. kind ) {
923+ ( None , None )
924+ } else {
925+ match ( & prev_ty. kind , & new_ty. kind ) {
926+ ( & ty:: FnDef ( ..) , & ty:: FnDef ( ..) ) => {
927+ // Don't reify if the function types have a LUB, i.e., they
928+ // are the same function and their parameters have a LUB.
929+ match self
930+ . commit_if_ok ( |_| self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty) )
931+ {
932+ // We have a LUB of prev_ty and new_ty, just return it.
933+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
934+ Err ( _) => {
935+ ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) )
936+ }
937+ }
938+ }
939+ ( & ty:: Closure ( _, substs) , & ty:: FnDef ( ..) ) => {
940+ let b_sig = new_ty. fn_sig ( self . tcx ) ;
941+ let a_sig = self
942+ . tcx
943+ . signature_unclosure ( substs. as_closure ( ) . sig ( ) , b_sig. unsafety ( ) ) ;
944+ ( Some ( a_sig) , Some ( b_sig) )
945+ }
946+ ( & ty:: FnDef ( ..) , & ty:: Closure ( _, substs) ) => {
947+ let a_sig = prev_ty. fn_sig ( self . tcx ) ;
948+ let b_sig = self
949+ . tcx
950+ . signature_unclosure ( substs. as_closure ( ) . sig ( ) , a_sig. unsafety ( ) ) ;
951+ ( Some ( a_sig) , Some ( b_sig) )
952+ }
953+ ( & ty:: Closure ( _, substs_a) , & ty:: Closure ( _, substs_b) ) => (
954+ Some ( self . tcx . signature_unclosure (
955+ substs_a. as_closure ( ) . sig ( ) ,
956+ hir:: Unsafety :: Normal ,
957+ ) ) ,
958+ Some ( self . tcx . signature_unclosure (
959+ substs_b. as_closure ( ) . sig ( ) ,
960+ hir:: Unsafety :: Normal ,
961+ ) ) ,
962+ ) ,
963+ _ => ( None , None ) ,
964+ }
923965 }
924-
966+ } ;
967+ if let ( Some ( a_sig) , Some ( b_sig) ) = ( a_sig, b_sig) {
925968 // The signature must match.
926- let a_sig = prev_ty. fn_sig ( self . tcx ) ;
927969 let a_sig = self . normalize_associated_types_in ( new. span , & a_sig) ;
928- let b_sig = new_ty. fn_sig ( self . tcx ) ;
929970 let b_sig = self . normalize_associated_types_in ( new. span , & b_sig) ;
930971 let sig = self
931972 . at ( cause, self . param_env )
@@ -935,17 +976,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
935976
936977 // Reify both sides and return the reified fn pointer type.
937978 let fn_ptr = self . tcx . mk_fn_ptr ( sig) ;
938- for expr in exprs. iter ( ) . map ( |e| e. as_coercion_site ( ) ) . chain ( Some ( new) ) {
939- // The only adjustment that can produce an fn item is
940- // `NeverToAny`, so this should always be valid.
979+ let prev_adjustment = match prev_ty. kind {
980+ ty:: Closure ( ..) => Adjust :: Pointer ( PointerCast :: ClosureFnPointer ( a_sig. unsafety ( ) ) ) ,
981+ ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
982+ _ => unreachable ! ( ) ,
983+ } ;
984+ let next_adjustment = match new_ty. kind {
985+ ty:: Closure ( ..) => Adjust :: Pointer ( PointerCast :: ClosureFnPointer ( b_sig. unsafety ( ) ) ) ,
986+ ty:: FnDef ( ..) => Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
987+ _ => unreachable ! ( ) ,
988+ } ;
989+ for expr in exprs. iter ( ) . map ( |e| e. as_coercion_site ( ) ) {
941990 self . apply_adjustments (
942991 expr,
943- vec ! [ Adjustment {
944- kind: Adjust :: Pointer ( PointerCast :: ReifyFnPointer ) ,
945- target: fn_ptr,
946- } ] ,
992+ vec ! [ Adjustment { kind: prev_adjustment. clone( ) , target: fn_ptr } ] ,
947993 ) ;
948994 }
995+ self . apply_adjustments ( new, vec ! [ Adjustment { kind: next_adjustment, target: fn_ptr } ] ) ;
949996 return Ok ( fn_ptr) ;
950997 }
951998
0 commit comments