@@ -1147,12 +1147,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11471147 exprs. len( )
11481148 ) ;
11491149
1150- // The following check fixes #88097, where the compiler erroneously
1151- // attempted to coerce a closure type to itself via a function pointer.
1152- if prev_ty == new_ty {
1153- return Ok ( prev_ty) ;
1154- }
1155-
11561150 let is_force_inline = |ty : Ty < ' tcx > | {
11571151 if let ty:: FnDef ( did, _) = ty. kind ( ) {
11581152 matches ! ( self . tcx. codegen_fn_attrs( did) . inline, InlineAttr :: Force { .. } )
@@ -1177,39 +1171,49 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11771171 if is_capturing_closure ( prev_ty) || is_capturing_closure ( new_ty) {
11781172 ( None , None )
11791173 } else {
1174+ let lubbed_tys = || self . commit_if_ok ( |snapshot| {
1175+ let outer_universe = self . infcx . universe ( ) ;
1176+
1177+ // We need to eagerly handle nested obligations due to lazy norm.
1178+ let result = if self . next_trait_solver ( ) {
1179+ let ocx = ObligationCtxt :: new ( self ) ;
1180+ let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1181+ if ocx. try_evaluate_obligations ( ) . is_empty ( ) {
1182+ Ok ( InferOk { value, obligations : ocx. into_pending_obligations ( ) } )
1183+ } else {
1184+ Err ( TypeError :: Mismatch )
1185+ }
1186+ } else {
1187+ self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1188+ } ;
1189+
1190+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1191+ result
1192+ } ) ;
1193+
11801194 match ( prev_ty. kind ( ) , new_ty. kind ( ) ) {
1181- ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => {
1182- // Don't reify if the function types have a LUB, i.e., they
1183- // are the same function and their parameters have a LUB.
1184- match self . commit_if_ok ( |snapshot| {
1185- let outer_universe = self . infcx . universe ( ) ;
1186-
1187- // We need to eagerly handle nested obligations due to lazy norm.
1188- let result = if self . next_trait_solver ( ) {
1189- let ocx = ObligationCtxt :: new ( self ) ;
1190- let value = ocx. lub ( cause, self . param_env , prev_ty, new_ty) ?;
1191- if ocx. try_evaluate_obligations ( ) . is_empty ( ) {
1192- Ok ( InferOk {
1193- value,
1194- obligations : ocx. into_pending_obligations ( ) ,
1195- } )
1196- } else {
1197- Err ( TypeError :: Mismatch )
1198- }
1199- } else {
1200- self . at ( cause, self . param_env ) . lub ( prev_ty, new_ty)
1201- } ;
1202-
1203- self . leak_check ( outer_universe, Some ( snapshot) ) ?;
1204- result
1205- } ) {
1206- // We have a LUB of prev_ty and new_ty, just return it.
1207- Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1208- Err ( _) => {
1209- ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) )
1210- }
1195+ // Don't coerce pairs of fndefs or pairs of closures to fn ptrs
1196+ // if they can just be lubbed.
1197+ //
1198+ // See #88097 or `lub_closures_before_fnptr_coercion.rs` for where
1199+ // we would erroneously coerce closures to fnptrs when attempting to
1200+ // coerce a closure to itself.
1201+ ( ty:: FnDef ( ..) , ty:: FnDef ( ..) ) => match lubbed_tys ( ) {
1202+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1203+ Err ( _) => ( Some ( prev_ty. fn_sig ( self . tcx ) ) , Some ( new_ty. fn_sig ( self . tcx ) ) ) ,
1204+ } ,
1205+ ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => match lubbed_tys ( ) {
1206+ Ok ( ok) => return Ok ( self . register_infer_ok_obligations ( ok) ) ,
1207+ Err ( _) => {
1208+ let a_sig = self
1209+ . tcx
1210+ . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1211+ let b_sig = self
1212+ . tcx
1213+ . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ;
1214+ ( Some ( a_sig) , Some ( b_sig) )
12111215 }
1212- }
1216+ } ,
12131217 ( ty:: Closure ( _, args) , ty:: FnDef ( ..) ) => {
12141218 let b_sig = new_ty. fn_sig ( self . tcx ) ;
12151219 let a_sig =
@@ -1222,16 +1226,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
12221226 self . tcx . signature_unclosure ( args. as_closure ( ) . sig ( ) , a_sig. safety ( ) ) ;
12231227 ( Some ( a_sig) , Some ( b_sig) )
12241228 }
1225- ( ty:: Closure ( _, args_a) , ty:: Closure ( _, args_b) ) => (
1226- Some (
1227- self . tcx
1228- . signature_unclosure ( args_a. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1229- ) ,
1230- Some (
1231- self . tcx
1232- . signature_unclosure ( args_b. as_closure ( ) . sig ( ) , hir:: Safety :: Safe ) ,
1233- ) ,
1234- ) ,
1229+ // ty::FnPtr x ty::FnPtr is fine to just be handled through a normal `unify`
1230+ // call using `lub` which is what will happen on the normal path.
12351231 _ => ( None , None ) ,
12361232 }
12371233 }
0 commit comments