@@ -1140,12 +1140,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11401140 exprs. len( )
11411141 ) ;
11421142
1143- // The following check fixes #88097, where the compiler erroneously
1144- // attempted to coerce a closure type to itself via a function pointer.
1145- if prev_ty == new_ty {
1146- return Ok ( prev_ty) ;
1147- }
1148-
11491143 let is_force_inline = |ty : Ty < ' tcx > | {
11501144 if let ty:: FnDef ( did, _) = ty. kind ( ) {
11511145 matches ! ( self . tcx. codegen_fn_attrs( did) . inline, InlineAttr :: Force { .. } )
@@ -1170,39 +1164,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11701164 if is_capturing_closure ( prev_ty) || is_capturing_closure ( new_ty) {
11711165 ( None , None )
11721166 } else {
1167+ let lubbed_tys = || self . commit_if_ok ( |snapshot| {
1168+ let outer_universe = self . infcx . universe ( ) ;
1169+
1170+ // We need to eagerly handle nested obligations due to lazy norm.
1171+ let result = if self . next_trait_solver ( ) {
1172+ let ocx = ObligationCtxt :: new ( self ) ;
1173+ let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1174+ if ocx. try_evaluate_obligations ( ) . is_empty ( ) {
1175+ Ok ( InferOk { value, obligations : ocx. into_pending_obligations ( ) } )
1176+ } else {
1177+ Err ( TypeError :: Mismatch )
1178+ }
1179+ } else {
1180+ self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1181+ } ;
1182+
1183+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1184+ result
1185+ } ) ;
1186+
11731187 match ( prev_ty. kind ( ) , new_ty. kind ( ) ) {
1174- ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => {
1175- // Don't reify if the function types have a LUB, i.e., they
1176- // are the same function and their parameters have a LUB.
1177- match self . commit_if_ok ( |snapshot| {
1178- let outer_universe = self . infcx . universe ( ) ;
1179-
1180- // We need to eagerly handle nested obligations due to lazy norm.
1181- let result = if self . next_trait_solver ( ) {
1182- let ocx = ObligationCtxt :: new ( self ) ;
1183- let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1184- if ocx. try_evaluate_obligations ( ) . is_empty ( ) {
1185- Ok ( InferOk {
1186- value,
1187- obligations : ocx. into_pending_obligations ( ) ,
1188- } )
1189- } else {
1190- Err ( TypeError :: Mismatch )
1191- }
1192- } else {
1193- self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1194- } ;
1195-
1196- self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1197- result
1198- } ) {
1199- // We have a LUB of prev_ty and new_ty, just return it.
1200- Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1201- Err ( _) => {
1202- ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) )
1203- }
1188+ // Don't coerce pairs of fndefs or pairs of closures to fn ptrs
1189+ // if they can just be lubbed.
1190+ //
1191+ // See #88097 or `lub_closures_before_fnptr_coercion.rs` for where
1192+ // we would erroneously coerce closures to fnptrs when attempting to
1193+ // coerce a closure to itself.
1194+ ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => match lubbed_tys ( ) {
1195+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1196+ Err ( _) => ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) ) ,
1197+ } ,
1198+ ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => match lubbed_tys ( ) {
1199+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1200+ Err ( _) => {
1201+ let a_sig = self
1202+ . tcx
1203+ . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1204+ let b_sig = self
1205+ . tcx
1206+ . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1207+ ( Some ( a_sig) , Some ( b_sig) )
12041208 }
1205- }
1209+ } ,
12061210 ( ty:: Closure ( _, args) , ty:: FnDef ( ..) ) => {
12071211 let b_sig = new_ty. fn_sig ( self . tcx ) ;
12081212 let a_sig =
@@ -1215,16 +1219,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12151219 self . tcx . signature_unclosure ( args. as_closure ( ) . sig ( ) , a_sig. safety ( ) ) ;
12161220 ( Some ( a_sig) , Some ( b_sig) )
12171221 }
1218- ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => (
1219- Some (
1220- self . tcx
1221- . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1222- ) ,
1223- Some (
1224- self . tcx
1225- . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1226- ) ,
1227- ) ,
1222+ // ty::FnPtr x ty::FnPtr is fine to just be handled through a normal `unify`
1223+ // call using `lub` which is what will happen on the normal path.
12281224 _ => ( None , None ) ,
12291225 }
12301226 }
0 commit comments