@@ -1122,12 +1122,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11221122 exprs. len( )
11231123 ) ;
11241124
1125- // The following check fixes #88097, where the compiler erroneously
1126- // attempted to coerce a closure type to itself via a function pointer.
1127- if prev_ty == new_ty {
1128- return Ok ( prev_ty) ;
1129- }
1130-
11311125 let is_force_inline = |ty : Ty < ' tcx > | {
11321126 if let ty:: FnDef ( did, _) = ty. kind ( ) {
11331127 matches ! ( self . tcx. codegen_fn_attrs( did) . inline, InlineAttr :: Force { .. } )
@@ -1152,39 +1146,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11521146 if is_capturing_closure ( prev_ty) || is_capturing_closure ( new_ty) {
11531147 ( None , None )
11541148 } else {
1149+ let lubbed_tys = || self . commit_if_ok ( |snapshot| {
1150+ let outer_universe = self . infcx . universe ( ) ;
1151+
1152+ // We need to eagerly handle nested obligations due to lazy norm.
1153+ let result = if self . next_trait_solver ( ) {
1154+ let ocx = ObligationCtxt :: new ( self ) ;
1155+ let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1156+ if ocx. try_evaluate_obligations ( ) . is_empty ( ) {
1157+ Ok ( InferOk { value, obligations : ocx. into_pending_obligations ( ) } )
1158+ } else {
1159+ Err ( TypeError :: Mismatch )
1160+ }
1161+ } else {
1162+ self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1163+ } ;
1164+
1165+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1166+ result
1167+ } ) ;
1168+
11551169 match ( prev_ty. kind ( ) , new_ty. kind ( ) ) {
1156- ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => {
1157- // Don't reify if the function types have a LUB, i.e., they
1158- // are the same function and their parameters have a LUB.
1159- match self . commit_if_ok ( |snapshot| {
1160- let outer_universe = self . infcx . universe ( ) ;
1161-
1162- // We need to eagerly handle nested obligations due to lazy norm.
1163- let result = if self . next_trait_solver ( ) {
1164- let ocx = ObligationCtxt :: new ( self ) ;
1165- let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1166- if ocx. try_evaluate_obligations ( ) . is_empty ( ) {
1167- Ok ( InferOk {
1168- value,
1169- obligations : ocx. into_pending_obligations ( ) ,
1170- } )
1171- } else {
1172- Err ( TypeError :: Mismatch )
1173- }
1174- } else {
1175- self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1176- } ;
1177-
1178- self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1179- result
1180- } ) {
1181- // We have a LUB of prev_ty and new_ty, just return it.
1182- Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1183- Err ( _) => {
1184- ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) )
1185- }
1170+ // Don't coerce pairs of fndefs or pairs of closures to fn ptrs
1171+ // if they can just be lubbed.
1172+ //
1173+ // See #88097 or `lub_closures_before_fnptr_coercion.rs` for where
1174+ // we would erroneously coerce closures to fnptrs when attempting to
1175+ // coerce a closure to itself.
1176+ ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => match lubbed_tys ( ) {
1177+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1178+ Err ( _) => ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) ) ,
1179+ } ,
1180+ ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => match lubbed_tys ( ) {
1181+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1182+ Err ( _) => {
1183+ let a_sig = self
1184+ . tcx
1185+ . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1186+ let b_sig = self
1187+ . tcx
1188+ . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1189+ ( Some ( a_sig) , Some ( b_sig) )
11861190 }
1187- }
1191+ } ,
11881192 ( ty:: Closure ( _, args) , ty:: FnDef ( ..) ) => {
11891193 let b_sig = new_ty. fn_sig ( self . tcx ) ;
11901194 let a_sig =
@@ -1197,16 +1201,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11971201 self . tcx . signature_unclosure ( args. as_closure ( ) . sig ( ) , a_sig. safety ( ) ) ;
11981202 ( Some ( a_sig) , Some ( b_sig) )
11991203 }
1200- ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => (
1201- Some (
1202- self . tcx
1203- . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1204- ) ,
1205- Some (
1206- self . tcx
1207- . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1208- ) ,
1209- ) ,
1204+ // ty::FnPtr x ty::FnPtr is fine to just be handled through a normal `unify`
1205+ // call using `lub` which is what will happen on the normal path.
12101206 _ => ( None , None ) ,
12111207 }
12121208 }
0 commit comments