@@ -759,7 +759,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
759
759
// `unsafe fn(arg0,arg1,...) -> _`
760
760
let closure_sig = substs_a. as_closure ( ) . sig ( ) ;
761
761
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) ) ;
763
764
debug ! ( "coerce_closure_to_fn(a={:?}, b={:?}, pty={:?})" , a, b, pointer_ty) ;
764
765
self . unify_and (
765
766
pointer_ty,
@@ -875,23 +876,44 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
875
876
debug ! ( "coercion::try_find_coercion_lub({:?}, {:?})" , prev_ty, new_ty) ;
876
877
877
878
// 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
+ }
889
889
}
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) {
891
915
// The signature must match.
892
- let a_sig = prev_ty. fn_sig ( self . tcx ) ;
893
916
let a_sig = self . normalize_associated_types_in ( new. span , & a_sig) ;
894
- let b_sig = new_ty. fn_sig ( self . tcx ) ;
895
917
let b_sig = self . normalize_associated_types_in ( new. span , & b_sig) ;
896
918
let sig = self
897
919
. at ( cause, self . param_env )
@@ -901,17 +923,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
901
923
902
924
// Reify both sides and return the reified fn pointer type.
903
925
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 ( ) ) {
907
937
self . apply_adjustments (
908
938
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 } ] ,
913
940
) ;
914
941
}
942
+ self . apply_adjustments ( new, vec ! [ Adjustment { kind: next_adjustment, target: fn_ptr } ] ) ;
915
943
return Ok ( fn_ptr) ;
916
944
}
917
945
0 commit comments