@@ -123,7 +123,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
123123
124124 fn unify_raw ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> InferResult < ' tcx , Ty < ' tcx > > {
125125 debug ! ( "unify(a: {:?}, b: {:?}, use_lub: {})" , a, b, self . use_lub) ;
126- self . commit_if_ok ( |_| {
126+ self . commit_if_ok ( |snapshot| {
127+ let outer_universe = self . infcx . universe ( ) ;
128+
127129 let at = self . at ( & self . cause , self . fcx . param_env ) ;
128130
129131 let res = if self . use_lub {
@@ -136,7 +138,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
136138 // In the new solver, lazy norm may allow us to shallowly equate
137139 // more types, but we emit possibly impossible-to-satisfy obligations.
138140 // Filter these cases out to make sure our coercion is more accurate.
139- match res {
141+ let res = match res {
140142 Ok ( InferOk { value, obligations } ) if self . next_trait_solver ( ) => {
141143 let ocx = ObligationCtxt :: new ( self ) ;
142144 ocx. register_obligations ( obligations) ;
@@ -147,7 +149,27 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
147149 }
148150 }
149151 res => res,
150- }
152+ } ;
153+
154+ // We leak check here mostly because lub operations are
155+ // kind of scuffed around binders. Instead of computing an actual
156+ // lub'd binder we instead:
157+ // - Equate the binders
158+ // - Return the lhs of the lub operation
159+ //
160+ // In order to actually ensure that equating the binders *does*
161+ // result in equal binders, and that the lhs is actually a supertype
162+ // of the rhs, we must perform a leak check here.
163+ //
164+ // Leak checking even when `use_lub` is false causes us to emit some
165+ // errors in dead code where borrowck would otherwise not catch the
166+ // subtyping errors. This is not soundness critical.
167+ //
168+ // FIXME: Ideally the actual `eq/sub/lub` would handle leak checks
169+ // themselves whenever a binder is entered.
170+ self . leak_check ( outer_universe, Some ( snapshot) ) ?;
171+
172+ res
151173 } )
152174 }
153175
@@ -751,40 +773,26 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
751773 b : ty:: PolyFnSig < ' tcx > ,
752774 adjustment : Option < Adjust > ,
753775 ) -> CoerceResult < ' tcx > {
754- self . commit_if_ok ( |snapshot| {
755- let outer_universe = self . infcx . universe ( ) ;
756-
757- let a_ty = Ty :: new_fn_ptr ( self . tcx , a) ;
758- let b_ty = Ty :: new_fn_ptr ( self . tcx , b) ;
776+ let a_ty = Ty :: new_fn_ptr ( self . tcx , a) ;
777+ let b_ty = Ty :: new_fn_ptr ( self . tcx , b) ;
759778
760- // Handle coercing `fn(..)` to `unsafe fn(..)`
761- let result = if a. safety ( ) . is_safe ( ) && b. safety ( ) . is_unsafe ( ) {
762- let unsafe_a_ty = self . tcx . safe_to_unsafe_fn_ty ( a) ;
763- let adjustment = adjustment. map ( |kind| Adjustment { kind, target : a_ty } ) ;
779+ // Handle coercing `fn(..)` to `unsafe fn(..)`
780+ if a. safety ( ) . is_safe ( ) && b. safety ( ) . is_unsafe ( ) {
781+ let unsafe_a_ty = self . tcx . safe_to_unsafe_fn_ty ( a) ;
782+ let adjustment = adjustment. map ( |kind| Adjustment { kind, target : a_ty } ) ;
764783
765- self . unify_and (
766- unsafe_a_ty,
767- b_ty,
768- adjustment,
769- Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
770- )
771- } else {
772- match adjustment {
773- Some ( adjust) => self . unify_and ( a_ty, b_ty, [ ] , adjust) ,
774- None => self . unify ( a_ty, b_ty) ,
775- }
776- } ;
777-
778- // FIXME(#73154): This is a hack. Currently LUB can generate
779- // unsolvable constraints. Additionally, it returns `a`
780- // unconditionally, even when the "LUB" is `b`. In the future, we
781- // want the coerced type to be the actual supertype of these two,
782- // but for now, we want to just error to ensure we don't lock
783- // ourselves into a specific behavior with NLL.
784- self . leak_check ( outer_universe, Some ( snapshot) ) ?;
785-
786- result
787- } )
784+ self . unify_and (
785+ unsafe_a_ty,
786+ b_ty,
787+ adjustment,
788+ Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
789+ )
790+ } else {
791+ match adjustment {
792+ Some ( adjust) => self . unify_and ( a_ty, b_ty, [ ] , adjust) ,
793+ None => self . unify ( a_ty, b_ty) ,
794+ }
795+ }
788796 }
789797
790798 fn coerce_from_fn_pointer (
0 commit comments