@@ -1093,12 +1093,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10931093 exprs. len( )
10941094 ) ;
10951095
1096- // The following check fixes #88097, where the compiler erroneously
1097- // attempted to coerce a closure type to itself via a function pointer.
1098- if prev_ty == new_ty {
1099- return Ok ( prev_ty) ;
1100- }
1101-
11021096 let is_force_inline = |ty : Ty < ' tcx > | {
11031097 if let ty:: FnDef ( did, _) = ty. kind ( ) {
11041098 matches ! ( self . tcx. codegen_fn_attrs( did) . inline, InlineAttr :: Force { .. } )
@@ -1123,39 +1117,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11231117 if is_capturing_closure ( prev_ty) || is_capturing_closure ( new_ty) {
11241118 ( None , None )
11251119 } else {
1120+ let lubbed_tys = || self . commit_if_ok ( |snapshot| {
1121+ let outer_universe = self . infcx . universe ( ) ;
1122+
1123+ // We need to eagerly handle nested obligations due to lazy norm.
1124+ let result = if self . next_trait_solver ( ) {
1125+ let ocx = ObligationCtxt :: new ( self ) ;
1126+ let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1127+ if ocx. select_where_possible ( ) . is_empty ( ) {
1128+ Ok ( InferOk { value, obligations : ocx. into_pending_obligations ( ) } )
1129+ } else {
1130+ Err ( TypeError :: Mismatch )
1131+ }
1132+ } else {
1133+ self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1134+ } ;
1135+
1136+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1137+ result
1138+ } ) ;
1139+
11261140 match ( prev_ty. kind ( ) , new_ty. kind ( ) ) {
1127- ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => {
1128- // Don't reify if the function types have a LUB, i.e., they
1129- // are the same function and their parameters have a LUB.
1130- match self . commit_if_ok ( |snapshot| {
1131- let outer_universe = self . infcx . universe ( ) ;
1132-
1133- // We need to eagerly handle nested obligations due to lazy norm.
1134- let result = if self . next_trait_solver ( ) {
1135- let ocx = ObligationCtxt :: new ( self ) ;
1136- let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1137- if ocx. select_where_possible ( ) . is_empty ( ) {
1138- Ok ( InferOk {
1139- value,
1140- obligations : ocx. into_pending_obligations ( ) ,
1141- } )
1142- } else {
1143- Err ( TypeError :: Mismatch )
1144- }
1145- } else {
1146- self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1147- } ;
1148-
1149- self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1150- result
1151- } ) {
1152- // We have a LUB of prev_ty and new_ty, just return it.
1153- Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1154- Err ( _) => {
1155- ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) )
1156- }
1141+ // Don't coerce pairs of fndefs or pairs of closures to fn ptrs
1142+ // if they can just be lubbed.
1143+ //
1144+ // See #88097 or `lub_closures_before_fnptr_coercion.rs` for where
1145+ // we would erroneously coerce closures to fnptrs when attempting to
1146+ // coerce a closure to itself.
1147+ ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => match lubbed_tys ( ) {
1148+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1149+ Err ( _) => ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) ) ,
1150+ } ,
1151+ ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => match lubbed_tys ( ) {
1152+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1153+ Err ( _) => {
1154+ let a_sig = self
1155+ . tcx
1156+ . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1157+ let b_sig = self
1158+ . tcx
1159+ . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1160+ ( Some ( a_sig) , Some ( b_sig) )
11571161 }
1158- }
1162+ } ,
11591163 ( ty:: Closure ( _, args) , ty:: FnDef ( ..) ) => {
11601164 let b_sig = new_ty. fn_sig ( self . tcx ) ;
11611165 let a_sig =
@@ -1168,16 +1172,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11681172 self . tcx . signature_unclosure ( args. as_closure ( ) . sig ( ) , a_sig. safety ( ) ) ;
11691173 ( Some ( a_sig) , Some ( b_sig) )
11701174 }
1171- ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => (
1172- Some (
1173- self . tcx
1174- . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1175- ) ,
1176- Some (
1177- self . tcx
1178- . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1179- ) ,
1180- ) ,
1175+ // ty::FnPtr x ty::FnPtr is fine to just be handled through a normal `unify`
1176+ // call using `lub` which is what will happen on the normal path.
11811177 _ => ( None , None ) ,
11821178 }
11831179 }
0 commit comments