@@ -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,30 @@ 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+ adjustments : impl IntoIterator < Item = Adjustment < ' tcx > > ,
167+ final_adjustment : Adjust ,
168+ ) -> CoerceResult < ' tcx > {
169+ self . unify_raw ( a, b) . and_then ( |InferOk { value : ty, obligations } | {
170+ success (
171+ adjustments
172+ . into_iter ( )
173+ . chain ( std:: iter:: once ( Adjustment { target : ty, kind : final_adjustment } ) )
174+ . collect ( ) ,
175+ ty,
176+ obligations,
177+ )
178+ } )
171179 }
172180
173181 #[ instrument( skip( self ) ) ]
@@ -180,18 +188,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
180188 // Coercing from `!` to any type is allowed:
181189 if a. is_never ( ) {
182190 if self . coerce_never {
183- return success ( simple ( Adjust :: NeverToAny ) ( b) , b, PredicateObligations :: new ( ) ) ;
191+ return success (
192+ vec ! [ Adjustment { kind: Adjust :: NeverToAny , target: b } ] ,
193+ b,
194+ PredicateObligations :: new ( ) ,
195+ ) ;
184196 } else {
185197 // Otherwise the only coercion we can do is unification.
186- return self . unify_and ( a, b, identity ) ;
198+ return self . unify ( a, b) ;
187199 }
188200 }
189201
190202 // Coercing *from* an unresolved inference variable means that
191203 // we have no information about the source type. This will always
192204 // ultimately fall back to some form of subtyping.
193205 if a. is_ty_var ( ) {
194- return self . coerce_from_inference_variable ( a, b, identity ) ;
206+ return self . coerce_from_inference_variable ( a, b) ;
195207 }
196208
197209 // Consider coercing the subtype to a DST
@@ -247,7 +259,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
247259 ty:: FnPtr ( a_sig_tys, a_hdr) => {
248260 // We permit coercion of fn pointers to drop the
249261 // unsafe qualifier.
250- self . coerce_from_fn_pointer ( a , a_sig_tys. with ( a_hdr) , b)
262+ self . coerce_from_fn_pointer ( a_sig_tys. with ( a_hdr) , b)
251263 }
252264 ty:: Closure ( closure_def_id_a, args_a) => {
253265 // Non-capturing closures are coercible to
@@ -257,20 +269,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
257269 }
258270 _ => {
259271 // Otherwise, just use unification rules.
260- self . unify_and ( a, b, identity )
272+ self . unify ( a, b)
261273 }
262274 }
263275 }
264276
265277 /// Coercing *from* an inference variable. In this case, we have no information
266278 /// about the source type, so we can't really do a true coercion and we always
267279 /// 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 > {
280+ fn coerce_from_inference_variable ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
274281 debug ! ( "coerce_from_inference_variable(a={:?}, b={:?})" , a, b) ;
275282 assert ! ( a. is_ty_var( ) && self . shallow_resolve( a) == a) ;
276283 assert ! ( self . shallow_resolve( b) == b) ;
@@ -298,12 +305,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
298305 "coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}" ,
299306 target_ty, obligations
300307 ) ;
301- let adjustments = make_adjustments ( target_ty) ;
302- InferResult :: Ok ( InferOk { value : ( adjustments, target_ty) , obligations } )
308+ success ( vec ! [ ] , target_ty, obligations)
303309 } else {
304310 // One unresolved type variable: just apply subtyping, we may be able
305311 // to do something useful.
306- self . unify_and ( a, b, make_adjustments )
312+ self . unify ( a, b)
307313 }
308314 }
309315
@@ -331,7 +337,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
331337 coerce_mutbls ( mt_a. mutbl , mutbl_b) ?;
332338 ( r_a, mt_a)
333339 }
334- _ => return self . unify_and ( a, b, identity ) ,
340+ _ => return self . unify ( a, b) ,
335341 } ;
336342
337343 let span = self . cause . span ;
@@ -437,7 +443,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
437443 referent_ty,
438444 mutbl_b, // [1] above
439445 ) ;
440- match self . unify ( derefd_ty_a, b) {
446+ match self . unify_raw ( derefd_ty_a, b) {
441447 Ok ( ok) => {
442448 found = Some ( ok) ;
443449 break ;
@@ -579,13 +585,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
579585 // We only have the latter, so we use an inference variable
580586 // for the former and let type inference do the rest.
581587 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 } ;
584- match reborrow {
585- None => vec ! [ unsize ] ,
586- Some ( ( ref deref, ref autoref) ) => vec ! [ deref. clone ( ) , autoref. clone ( ) , unsize ] ,
587- }
588- } ) ?;
588+
589+ let mut coercion = self . unify_and (
590+ coerce_target ,
591+ target ,
592+ reborrow . into_iter ( ) . flat_map ( | ( deref, autoref) | [ deref, autoref] ) ,
593+ Adjust :: Pointer ( PointerCoercion :: Unsize ) ,
594+ ) ?;
589595
590596 let mut selcx = traits:: SelectionContext :: new ( self ) ;
591597
@@ -708,7 +714,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
708714 && let ty:: Dynamic ( b_data, _, ty:: DynStar ) = b. kind ( )
709715 && a_data. principal_def_id ( ) == b_data. principal_def_id ( )
710716 {
711- return self . unify_and ( a, b, |_| vec ! [ ] ) ;
717+ return self . unify ( a, b) ;
712718 }
713719
714720 // Check the obligations of the cast -- for example, when casting
@@ -808,23 +814,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
808814
809815 // To complete the reborrow, we need to make sure we can unify the inner types, and if so we
810816 // add the adjustments.
811- self . unify_and ( a, b, |_inner_ty| {
812- vec ! [ Adjustment { kind: Adjust :: ReborrowPin ( mut_b) , target: b } ]
813- } )
817+ self . unify_and ( a, b, [ ] , Adjust :: ReborrowPin ( mut_b) )
814818 }
815819
816- fn coerce_from_safe_fn < F , G > (
820+ fn coerce_from_safe_fn (
817821 & self ,
818- a : Ty < ' tcx > ,
819822 fn_ty_a : ty:: PolyFnSig < ' tcx > ,
820823 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- {
824+ adjustment : Option < Adjust > ,
825+ ) -> CoerceResult < ' tcx > {
828826 self . commit_if_ok ( |snapshot| {
829827 let outer_universe = self . infcx . universe ( ) ;
830828
@@ -833,9 +831,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
833831 && hdr_b. safety . is_unsafe ( )
834832 {
835833 let unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ;
836- self . unify_and ( unsafe_a, b, to_unsafe)
834+ self . unify_and (
835+ unsafe_a,
836+ b,
837+ adjustment
838+ . map ( |kind| Adjustment { kind, target : Ty :: new_fn_ptr ( self . tcx , fn_ty_a) } ) ,
839+ Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) ,
840+ )
837841 } else {
838- self . unify_and ( a, b, normal)
842+ let a = Ty :: new_fn_ptr ( self . tcx , fn_ty_a) ;
843+ match adjustment {
844+ Some ( adjust) => self . unify_and ( a, b, [ ] , adjust) ,
845+ None => self . unify ( a, b) ,
846+ }
839847 } ;
840848
841849 // FIXME(#73154): This is a hack. Currently LUB can generate
@@ -852,7 +860,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
852860
853861 fn coerce_from_fn_pointer (
854862 & self ,
855- a : Ty < ' tcx > ,
856863 fn_ty_a : ty:: PolyFnSig < ' tcx > ,
857864 b : Ty < ' tcx > ,
858865 ) -> CoerceResult < ' tcx > {
@@ -861,15 +868,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
861868 //!
862869
863870 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- )
871+ debug ! ( ?fn_ty_a, ?b, "coerce_from_fn_pointer" ) ;
872+
873+ self . coerce_from_safe_fn ( fn_ty_a, b, None )
873874 }
874875
875876 fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
@@ -916,30 +917,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
916917 self . at ( & self . cause , self . param_env ) . normalize ( a_sig) ;
917918 obligations. extend ( o1) ;
918919
919- let a_fn_pointer = Ty :: new_fn_ptr ( self . tcx , a_sig) ;
920920 let InferOk { value, obligations : o2 } = self . coerce_from_safe_fn (
921- a_fn_pointer,
922921 a_sig,
923922 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 ) ) ,
923+ Some ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) ,
937924 ) ?;
938925
939926 obligations. extend ( o2) ;
940927 Ok ( InferOk { value, obligations } )
941928 }
942- _ => self . unify_and ( a, b, identity ) ,
929+ _ => self . unify ( a, b) ,
943930 }
944931 }
945932
@@ -983,10 +970,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
983970 self . unify_and (
984971 pointer_ty,
985972 b,
986- simple ( Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ) ,
973+ [ ] ,
974+ Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ,
987975 )
988976 }
989- _ => self . unify_and ( a, b, identity ) ,
977+ _ => self . unify ( a, b) ,
990978 }
991979 }
992980
@@ -1001,7 +989,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
1001989 let ( is_ref, mt_a) = match * a. kind ( ) {
1002990 ty:: Ref ( _, ty, mutbl) => ( true , ty:: TypeAndMut { ty, mutbl } ) ,
1003991 ty:: RawPtr ( ty, mutbl) => ( false , ty:: TypeAndMut { ty, mutbl } ) ,
1004- _ => return self . unify_and ( a, b, identity ) ,
992+ _ => return self . unify ( a, b) ,
1005993 } ;
1006994 coerce_mutbls ( mt_a. mutbl , mutbl_b) ?;
1007995
@@ -1011,16 +999,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
1011999 // representation, we still register an Adjust::DerefRef so that
10121000 // regionck knows that the region for `a` must be valid here.
10131001 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- } )
1002+ self . unify_and (
1003+ a_raw ,
1004+ b ,
1005+ [ Adjustment { kind : Adjust :: Deref ( None ) , target : mt_a . ty } ] ,
1006+ Adjust :: Borrow ( AutoBorrow :: RawPtr ( mutbl_b ) ) ,
1007+ )
10201008 } else if mt_a. mutbl != mutbl_b {
1021- self . unify_and ( a_raw, b, simple ( Adjust :: Pointer ( PointerCoercion :: MutToConstPointer ) ) )
1009+ self . unify_and ( a_raw, b, [ ] , Adjust :: Pointer ( PointerCoercion :: MutToConstPointer ) )
10221010 } else {
1023- self . unify_and ( a_raw, b, identity )
1011+ self . unify ( a_raw, b)
10241012 }
10251013 }
10261014}
@@ -1118,9 +1106,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11181106 let cause = self . cause ( DUMMY_SP , ObligationCauseCode :: ExprAssignable ) ;
11191107 // We don't ever need two-phase here since we throw out the result of the coercion.
11201108 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 ) )
1109+ coerce. autoderef ( DUMMY_SP , expr_ty ) . find_map ( | ( ty , steps ) | {
1110+ self . probe ( |_| coerce . unify_raw ( ty , target ) ) . ok ( ) . map ( |_| steps )
1111+ } )
11241112 }
11251113
11261114 /// Given a type, this function will calculate and return the type given
0 commit comments