@@ -125,7 +125,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
125125
126126 fn unify_raw ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> InferResult < ' tcx , Ty < ' tcx > > {
127127 debug ! ( "unify(a: {:?}, b: {:?}, use_lub: {})" , a, b, self . use_lub) ;
128- self . commit_if_ok ( |_| {
128+ self . commit_if_ok ( |snapshot| {
129+ let outer_universe = self . infcx . universe ( ) ;
130+
129131 let at = self . at ( & self . cause , self . fcx . param_env ) ;
130132
131133 let res = if self . use_lub {
@@ -138,7 +140,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
138140 // In the new solver, lazy norm may allow us to shallowly equate
139141 // more types, but we emit possibly impossible-to-satisfy obligations.
140142 // Filter these cases out to make sure our coercion is more accurate.
141- match res {
143+ let res = match res {
142144 Ok ( InferOk { value, obligations } ) if self . next_trait_solver ( ) => {
143145 let ocx = ObligationCtxt :: new ( self ) ;
144146 ocx. register_obligations ( obligations) ;
@@ -149,7 +151,27 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
149151 }
150152 }
151153 res => res,
152- }
154+ } ;
155+
156+ // We leak check here mostly because lub operations are
157+ // kind of scuffed around binders. Instead of computing an actual
158+ // lub'd binder we instead:
159+ // - Equate the binders
160+ // - Return the lhs of the lub operation
161+ //
162+ // In order to actually ensure that equating the binders *does*
163+ // result in equal binders, and that the lhs is actually a supertype
164+ // of the rhs, we must perform a leak check here.
165+ //
166+ // Leak checking even when `use_lub` is false causes us to emit some
167+ // errors in dead code where borrowck would otherwise not catch the
168+ // subtyping errors. This is not soundness critical.
169+ //
170+ // FIXME: Ideally the actual `eq/sub/lub` would handle leak checks
171+ // themselves whenever a binder is entered.
172+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
173+
174+ res
153175 } )
154176 }
155177
@@ -805,39 +827,25 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
805827 ) -> CoerceResult < ' tcx > {
806828 debug_assert ! ( self . shallow_resolve( b) == b) ;
807829
808- self . commit_if_ok ( |snapshot| {
809- let outer_universe = self . infcx . universe ( ) ;
810-
811- let result = if let ty:: FnPtr ( _, hdr_b) = b. kind ( )
812- && fn_ty_a. safety ( ) . is_safe ( )
813- && hdr_b. safety . is_unsafe ( )
814- {
815- let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
816- self . unify_and (
817- unsafe_a,
818- b,
819- adjustment
820- . map ( |kind| Adjustment { kind, target : Ty :: new_fn_ptr ( self . tcx , fn_ty_a) } ) ,
821- Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
822- )
823- } else {
824- let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
825- match adjustment {
826- Some ( adjust) => self . unify_and ( a, b, [ ] , adjust) ,
827- None => self . unify ( a, b) ,
828- }
829- } ;
830-
831- // FIXME(#73154): This is a hack. Currently LUB can generate
832- // unsolvable constraints. Additionally, it returns `a`
833- // unconditionally, even when the "LUB" is `b`. In the future, we
834- // want the coerced type to be the actual supertype of these two,
835- // but for now, we want to just error to ensure we don't lock
836- // ourselves into a specific behavior with NLL.
837- self . leak_check ( outer_universe, Some ( snapshot) ) ?;
838-
839- result
840- } )
830+ if let ty:: FnPtr ( _, hdr_b) = b. kind ( )
831+ && fn_ty_a. safety ( ) . is_safe ( )
832+ && hdr_b. safety . is_unsafe ( )
833+ {
834+ let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
835+ self . unify_and (
836+ unsafe_a,
837+ b,
838+ adjustment
839+ . map ( |kind| Adjustment { kind, target : Ty :: new_fn_ptr ( self . tcx , fn_ty_a) } ) ,
840+ Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
841+ )
842+ } else {
843+ let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
844+ match adjustment {
845+ Some ( adjust) => self . unify_and ( a, b, [ ] , adjust) ,
846+ None => self . unify ( a, b) ,
847+ }
848+ }
841849 }
842850
843851 fn coerce_from_fn_pointer (
0 commit comments