@@ -103,15 +103,6 @@ fn coerce_mutbls<'tcx>(
103103 if from_mutbl >= to_mutbl { Ok ( ( ) ) } else { Err ( TypeError :: Mutability ) }
104104}
105105
106- /// Do not require any adjustments, i.e. coerce `x -> x`.
107- fn identity ( _: Ty < ' _ > ) -> Vec < Adjustment < ' _ > > {
108- vec ! [ ]
109- }
110-
111- fn simple < ' tcx > ( kind : Adjust ) -> impl FnOnce ( Ty < ' tcx > ) -> Vec < Adjustment < ' tcx > > {
112- move |target| vec ! [ Adjustment { kind, target } ]
113- }
114-
115106/// This always returns `Ok(...)`.
116107fn success < ' tcx > (
117108 adj : Vec < Adjustment < ' tcx > > ,
@@ -131,7 +122,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
131122 Coerce { fcx, cause, allow_two_phase, use_lub : false , coerce_never }
132123 }
133124
134- fn unify ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> InferResult < ' tcx , Ty < ' tcx > > {
125+ fn unify_raw ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> InferResult < ' tcx , Ty < ' tcx > > {
135126 debug ! ( "unify(a: {:?}, b: {:?}, use_lub: {})" , a, b, self . use_lub) ;
136127 self . commit_if_ok ( |_| {
137128 let at = self . at ( & self . cause , self . fcx . param_env ) ;
@@ -161,13 +152,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
161152 } )
162153 }
163154
155+ /// Unify two types (using sub or lub).
156+ fn unify ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
157+ self . unify_raw ( a, b)
158+ . and_then ( |InferOk { value : ty, obligations } | success ( vec ! [ ] , ty, obligations) )
159+ }
160+
164161 /// Unify two types (using sub or lub) and produce a specific coercion.
165- fn unify_and < F > ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > , f : F ) -> CoerceResult < ' tcx >
166- where
167- F : FnOnce ( Ty < ' tcx > ) -> Vec < Adjustment < ' tcx > > ,
168- {
169- self . unify ( a, b)
170- . and_then ( |InferOk { value : ty, obligations } | success ( f ( ty) , ty, obligations) )
162+ fn unify_and (
163+ & self ,
164+ a : Ty < ' tcx > ,
165+ b : Ty < ' tcx > ,
166+ mut adjustments : Vec < Adjustment < ' tcx > > ,
167+ final_adjustment : Adjust ,
168+ ) -> CoerceResult < ' tcx > {
169+ self . unify_raw ( a, b) . and_then ( |InferOk { value : ty, obligations } | {
170+ adjustments. push ( Adjustment { target : ty, kind : final_adjustment } ) ;
171+ success ( adjustments, ty, obligations)
172+ } )
171173 }
172174
173175 #[ instrument( skip( self ) ) ]
@@ -180,18 +182,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
180182 // Coercing from `!` to any type is allowed:
181183 if a. is_never ( ) {
182184 if self . coerce_never {
183- return success ( simple ( Adjust :: NeverToAny ) ( b) , b, PredicateObligations :: new ( ) ) ;
185+ return success (
186+ vec ! [ Adjustment { kind: Adjust :: NeverToAny , target: b } ] ,
187+ b,
188+ PredicateObligations :: new ( ) ,
189+ ) ;
184190 } else {
185191 // Otherwise the only coercion we can do is unification.
186- return self . unify_and ( a, b, identity ) ;
192+ return self . unify ( a, b) ;
187193 }
188194 }
189195
190196 // Coercing *from* an unresolved inference variable means that
191197 // we have no information about the source type. This will always
192198 // ultimately fall back to some form of subtyping.
193199 if a. is_ty_var ( ) {
194- return self . coerce_from_inference_variable ( a, b, identity ) ;
200+ return self . coerce_from_inference_variable ( a, b) ;
195201 }
196202
197203 // Consider coercing the subtype to a DST
@@ -247,7 +253,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
247253 ty:: FnPtr ( a_sig_tys, a_hdr) => {
248254 // We permit coercion of fn pointers to drop the
249255 // unsafe qualifier.
250- self . coerce_from_fn_pointer ( a , a_sig_tys. with ( a_hdr) , b)
256+ self . coerce_from_fn_pointer ( a_sig_tys. with ( a_hdr) , b)
251257 }
252258 ty:: Closure ( closure_def_id_a, args_a) => {
253259 // Non-capturing closures are coercible to
@@ -257,20 +263,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
257263 }
258264 _ => {
259265 // Otherwise, just use unification rules.
260- self . unify_and ( a, b, identity )
266+ self . unify ( a, b)
261267 }
262268 }
263269 }
264270
265271 /// Coercing *from* an inference variable. In this case, we have no information
266272 /// about the source type, so we can't really do a true coercion and we always
267273 /// fall back to subtyping (`unify_and`).
268- fn coerce_from_inference_variable (
269- & self ,
270- a : Ty < ' tcx > ,
271- b : Ty < ' tcx > ,
272- make_adjustments : impl FnOnce ( Ty < ' tcx > ) -> Vec < Adjustment < ' tcx > > ,
273- ) -> CoerceResult < ' tcx > {
274+ fn coerce_from_inference_variable ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
274275 debug ! ( "coerce_from_inference_variable(a={:?}, b={:?})" , a, b) ;
275276 assert ! ( a. is_ty_var( ) && self . shallow_resolve( a) == a) ;
276277 assert ! ( self . shallow_resolve( b) == b) ;
@@ -298,12 +299,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
298299 "coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}" ,
299300 target_ty, obligations
300301 ) ;
301- let adjustments = make_adjustments ( target_ty) ;
302- InferResult :: Ok ( InferOk { value : ( adjustments, target_ty) , obligations } )
302+ success ( vec ! [ ] , target_ty, obligations)
303303 } else {
304304 // One unresolved type variable: just apply subtyping, we may be able
305305 // to do something useful.
306- self . unify_and ( a, b, make_adjustments )
306+ self . unify ( a, b)
307307 }
308308 }
309309
@@ -331,7 +331,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
331331 coerce_mutbls ( mt_a. mutbl , mutbl_b) ?;
332332 ( r_a, mt_a)
333333 }
334- _ => return self . unify_and ( a, b, identity ) ,
334+ _ => return self . unify ( a, b) ,
335335 } ;
336336
337337 let span = self . cause . span ;
@@ -437,7 +437,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
437437 referent_ty,
438438 mutbl_b, // [1] above
439439 ) ;
440- match self . unify ( derefd_ty_a, b) {
440+ match self . unify_raw ( derefd_ty_a, b) {
441441 Ok ( ok) => {
442442 found = Some ( ok) ;
443443 break ;
@@ -579,13 +579,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
579579 // We only have the latter, so we use an inference variable
580580 // for the former and let type inference do the rest.
581581 let coerce_target = self . next_ty_var ( self . cause . span ) ;
582- let mut coercion = self . unify_and ( coerce_target, target, |target| {
583- let unsize = Adjustment { kind : Adjust :: Pointer ( PointerCoercion :: Unsize ) , target } ;
582+ let mut coercion = self . unify_and (
583+ coerce_target,
584+ target,
584585 match reborrow {
585- None => vec ! [ unsize] ,
586- Some ( ( ref deref, ref autoref) ) => vec ! [ deref. clone( ) , autoref. clone( ) , unsize] ,
587- }
588- } ) ?;
586+ None => vec ! [ ] ,
587+ Some ( ( ref deref, ref autoref) ) => vec ! [ deref. clone( ) , autoref. clone( ) ] ,
588+ } ,
589+ Adjust :: Pointer ( PointerCoercion :: Unsize ) ,
590+ ) ?;
589591
590592 let mut selcx = traits:: SelectionContext :: new ( self ) ;
591593
@@ -708,7 +710,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
708710 && let ty:: Dynamic ( b_data, _, ty:: DynStar ) = b. kind ( )
709711 && a_data. principal_def_id ( ) == b_data. principal_def_id ( )
710712 {
711- return self . unify_and ( a, b, |_| vec ! [ ] ) ;
713+ return self . unify ( a, b) ;
712714 }
713715
714716 // Check the obligations of the cast -- for example, when casting
@@ -808,23 +810,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
808810
809811 // To complete the reborrow, we need to make sure we can unify the inner types, and if so we
810812 // add the adjustments.
811- self . unify_and ( a, b, |_inner_ty| {
812- vec ! [ Adjustment { kind: Adjust :: ReborrowPin ( mut_b) , target: b } ]
813- } )
813+ self . unify_and ( a, b, vec ! [ ] , Adjust :: ReborrowPin ( mut_b) )
814814 }
815815
816- fn coerce_from_safe_fn < F , G > (
816+ fn coerce_from_safe_fn (
817817 & self ,
818- a : Ty < ' tcx > ,
819818 fn_ty_a : ty:: PolyFnSig < ' tcx > ,
820819 b : Ty < ' tcx > ,
821- to_unsafe : F ,
822- normal : G ,
823- ) -> CoerceResult < ' tcx >
824- where
825- F : FnOnce ( Ty < ' tcx > ) -> Vec < Adjustment < ' tcx > > ,
826- G : FnOnce ( Ty < ' tcx > ) -> Vec < Adjustment < ' tcx > > ,
827- {
820+ adjustment : Option < Adjust > ,
821+ ) -> CoerceResult < ' tcx > {
828822 self . commit_if_ok ( |snapshot| {
829823 let outer_universe = self . infcx . universe ( ) ;
830824
@@ -833,9 +827,24 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
833827 && hdr_b. safety . is_unsafe ( )
834828 {
835829 let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
836- self . unify_and ( unsafe_a, b, to_unsafe)
830+ let adjustments = match adjustment {
831+ Some ( kind) => {
832+ vec ! [ Adjustment { kind, target: Ty :: new_fn_ptr( self . tcx, fn_ty_a) } ]
833+ }
834+ None => vec ! [ ] ,
835+ } ;
836+ self . unify_and (
837+ unsafe_a,
838+ b,
839+ adjustments,
840+ Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
841+ )
837842 } else {
838- self . unify_and ( a, b, normal)
843+ let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
844+ match adjustment {
845+ Some ( adjust) => self . unify_and ( a, b, vec ! [ ] , adjust) ,
846+ None => self . unify ( a, b) ,
847+ }
839848 } ;
840849
841850 // FIXME(#73154): This is a hack. Currently LUB can generate
@@ -852,7 +861,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
852861
853862 fn coerce_from_fn_pointer (
854863 & self ,
855- a : Ty < ' tcx > ,
856864 fn_ty_a : ty:: PolyFnSig < ' tcx > ,
857865 b : Ty < ' tcx > ,
858866 ) -> CoerceResult < ' tcx > {
@@ -861,15 +869,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
861869 //!
862870
863871 let b = self . shallow_resolve ( b) ;
864- debug ! ( "coerce_from_fn_pointer(a={:?}, b={:?})" , a, b) ;
865-
866- self . coerce_from_safe_fn (
867- a,
868- fn_ty_a,
869- b,
870- simple ( Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ) ,
871- identity,
872- )
872+ debug ! ( ?fn_ty_a, ?b, "coerce_from_fn_pointer" ) ;
873+
874+ self . coerce_from_safe_fn ( fn_ty_a, b, None )
873875 }
874876
875877 fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
@@ -916,30 +918,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
916918 self . at ( & self . cause , self . param_env ) . normalize ( a_sig) ;
917919 obligations. extend ( o1) ;
918920
919- let a_fn_pointer = Ty :: new_fn_ptr ( self . tcx , a_sig) ;
920921 let InferOk { value, obligations : o2 } = self . coerce_from_safe_fn (
921- a_fn_pointer,
922922 a_sig,
923923 b,
924- |unsafe_ty| {
925- vec ! [
926- Adjustment {
927- kind: Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ,
928- target: a_fn_pointer,
929- } ,
930- Adjustment {
931- kind: Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
932- target: unsafe_ty,
933- } ,
934- ]
935- } ,
936- simple ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) ,
924+ Some ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) ,
937925 ) ?;
938926
939927 obligations. extend ( o2) ;
940928 Ok ( InferOk { value, obligations } )
941929 }
942- _ => self . unify_and ( a, b, identity ) ,
930+ _ => self . unify ( a, b) ,
943931 }
944932 }
945933
@@ -983,10 +971,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
983971 self . unify_and (
984972 pointer_ty,
985973 b,
986- simple ( Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ) ,
974+ vec ! [ ] ,
975+ Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ,
987976 )
988977 }
989- _ => self . unify_and ( a, b, identity ) ,
978+ _ => self . unify ( a, b) ,
990979 }
991980 }
992981
@@ -1001,7 +990,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
1001990 let ( is_ref, mt_a) = match * a. kind ( ) {
1002991 ty:: Ref ( _, ty, mutbl) => ( true , ty:: TypeAndMut { ty, mutbl } ) ,
1003992 ty:: RawPtr ( ty, mutbl) => ( false , ty:: TypeAndMut { ty, mutbl } ) ,
1004- _ => return self . unify_and ( a, b, identity ) ,
993+ _ => return self . unify ( a, b) ,
1005994 } ;
1006995 coerce_mutbls ( mt_a. mutbl , mutbl_b) ?;
1007996
@@ -1011,16 +1000,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10111000 // representation, we still register an Adjust::DerefRef so that
10121001 // regionck knows that the region for `a` must be valid here.
10131002 if is_ref {
1014- self . unify_and ( a_raw , b , |target| {
1015- vec ! [
1016- Adjustment { kind : Adjust :: Deref ( None ) , target : mt_a . ty } ,
1017- Adjustment { kind: Adjust :: Borrow ( AutoBorrow :: RawPtr ( mutbl_b ) ) , target } ,
1018- ]
1019- } )
1003+ self . unify_and (
1004+ a_raw ,
1005+ b ,
1006+ vec ! [ Adjustment { kind: Adjust :: Deref ( None ) , target: mt_a . ty } ] ,
1007+ Adjust :: Borrow ( AutoBorrow :: RawPtr ( mutbl_b ) ) ,
1008+ )
10201009 } else if mt_a. mutbl != mutbl_b {
1021- self . unify_and ( a_raw, b, simple ( Adjust :: Pointer ( PointerCoercion :: MutToConstPointer ) ) )
1010+ self . unify_and ( a_raw, b, vec ! [ ] , Adjust :: Pointer ( PointerCoercion :: MutToConstPointer ) )
10221011 } else {
1023- self . unify_and ( a_raw, b, identity )
1012+ self . unify ( a_raw, b)
10241013 }
10251014 }
10261015}
@@ -1118,9 +1107,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11181107 let cause = self . cause ( DUMMY_SP , ObligationCauseCode :: ExprAssignable ) ;
11191108 // We don't ever need two-phase here since we throw out the result of the coercion.
11201109 let coerce = Coerce :: new ( self , cause, AllowTwoPhase :: No , true ) ;
1121- coerce
1122- . autoderef ( DUMMY_SP , expr_ty )
1123- . find_map ( | ( ty , steps ) | self . probe ( |_| coerce . unify ( ty , target ) ) . ok ( ) . map ( |_| steps ) )
1110+ coerce. autoderef ( DUMMY_SP , expr_ty ) . find_map ( | ( ty , steps ) | {
1111+ self . probe ( |_| coerce . unify_raw ( ty , target ) ) . ok ( ) . map ( |_| steps )
1112+ } )
11241113 }
11251114
11261115 /// Given a type, this function will calculate and return the type given
0 commit comments