@@ -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,18 @@ 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] , 
588+ 
589+         let  mut  coercion = match  reborrow { 
590+             None  => { 
591+                 self . unify_and ( coerce_target,  target,  [ ] ,  Adjust :: Pointer ( PointerCoercion :: Unsize ) ) ?
587592            } 
588-         } ) ?; 
593+             Some ( ( ref  deref,  ref  autoref) )  => self . unify_and ( 
594+                 coerce_target, 
595+                 target, 
596+                 [ deref. clone ( ) ,  autoref. clone ( ) ] , 
597+                 Adjust :: Pointer ( PointerCoercion :: Unsize ) , 
598+             ) ?, 
599+         } ; 
589600
590601        let  mut  selcx = traits:: SelectionContext :: new ( self ) ; 
591602
@@ -708,7 +719,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
708719            && let  ty:: Dynamic ( b_data,  _,  ty:: DynStar )  = b. kind ( ) 
709720            && a_data. principal_def_id ( )  == b_data. principal_def_id ( ) 
710721        { 
711-             return  self . unify_and ( a,  b,  |_|  vec ! [ ] ) ; 
722+             return  self . unify ( a,  b) ; 
712723        } 
713724
714725        // Check the obligations of the cast -- for example, when casting 
@@ -808,23 +819,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
808819
809820        // To complete the reborrow, we need to make sure we can unify the inner types, and if so we 
810821        // add the adjustments. 
811-         self . unify_and ( a,  b,  |_inner_ty| { 
812-             vec ! [ Adjustment  {  kind:  Adjust :: ReborrowPin ( mut_b) ,  target:  b } ] 
813-         } ) 
822+         self . unify_and ( a,  b,  [ ] ,  Adjust :: ReborrowPin ( mut_b) ) 
814823    } 
815824
816-     fn  coerce_from_safe_fn < F ,   G > ( 
825+     fn  coerce_from_safe_fn ( 
817826        & self , 
818-         a :  Ty < ' tcx > , 
819827        fn_ty_a :  ty:: PolyFnSig < ' tcx > , 
820828        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-     { 
829+         adjustment :  Option < Adjust > , 
830+     )  -> CoerceResult < ' tcx >  { 
828831        self . commit_if_ok ( |snapshot| { 
829832            let  outer_universe = self . infcx . universe ( ) ; 
830833
@@ -833,9 +836,26 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
833836                && hdr_b. safety . is_unsafe ( ) 
834837            { 
835838                let  unsafe_a = self . tcx . safe_to_unsafe_fn_ty ( fn_ty_a) ; 
836-                 self . unify_and ( unsafe_a,  b,  to_unsafe) 
839+                 match  adjustment { 
840+                     Some ( kind)  => self . unify_and ( 
841+                         unsafe_a, 
842+                         b, 
843+                         [ Adjustment  {  kind,  target :  Ty :: new_fn_ptr ( self . tcx ,  fn_ty_a)  } ] , 
844+                         Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) , 
845+                     ) , 
846+                     None  => self . unify_and ( 
847+                         unsafe_a, 
848+                         b, 
849+                         [ ] , 
850+                         Adjust :: Pointer ( PointerCoercion :: UnsafeFnPointer ) , 
851+                     ) , 
852+                 } 
837853            }  else  { 
838-                 self . unify_and ( a,  b,  normal) 
854+                 let  a = Ty :: new_fn_ptr ( self . tcx ,  fn_ty_a) ; 
855+                 match  adjustment { 
856+                     Some ( adjust)  => self . unify_and ( a,  b,  [ ] ,  adjust) , 
857+                     None  => self . unify ( a,  b) , 
858+                 } 
839859            } ; 
840860
841861            // FIXME(#73154): This is a hack. Currently LUB can generate 
@@ -852,7 +872,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
852872
853873    fn  coerce_from_fn_pointer ( 
854874        & self , 
855-         a :  Ty < ' tcx > , 
856875        fn_ty_a :  ty:: PolyFnSig < ' tcx > , 
857876        b :  Ty < ' tcx > , 
858877    )  -> CoerceResult < ' tcx >  { 
@@ -861,15 +880,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
861880         //! 
862881
863882        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-         ) 
883+         debug ! ( ?fn_ty_a,  ?b,  "coerce_from_fn_pointer" ) ; 
884+ 
885+         self . coerce_from_safe_fn ( fn_ty_a,  b,  None ) 
873886    } 
874887
875888    fn  coerce_from_fn_item ( & self ,  a :  Ty < ' tcx > ,  b :  Ty < ' tcx > )  -> CoerceResult < ' tcx >  { 
@@ -916,30 +929,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
916929                    self . at ( & self . cause ,  self . param_env ) . normalize ( a_sig) ; 
917930                obligations. extend ( o1) ; 
918931
919-                 let  a_fn_pointer = Ty :: new_fn_ptr ( self . tcx ,  a_sig) ; 
920932                let  InferOk  {  value,  obligations :  o2 }  = self . coerce_from_safe_fn ( 
921-                     a_fn_pointer, 
922933                    a_sig, 
923934                    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 ) ) , 
935+                     Some ( Adjust :: Pointer ( PointerCoercion :: ReifyFnPointer ) ) , 
937936                ) ?; 
938937
939938                obligations. extend ( o2) ; 
940939                Ok ( InferOk  {  value,  obligations } ) 
941940            } 
942-             _ => self . unify_and ( a,  b,  identity ) , 
941+             _ => self . unify ( a,  b) , 
943942        } 
944943    } 
945944
@@ -983,10 +982,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
983982                self . unify_and ( 
984983                    pointer_ty, 
985984                    b, 
986-                     simple ( Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ) , 
985+                     [ ] , 
986+                     Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) , 
987987                ) 
988988            } 
989-             _ => self . unify_and ( a,  b,  identity ) , 
989+             _ => self . unify ( a,  b) , 
990990        } 
991991    } 
992992
@@ -1001,7 +1001,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10011001        let  ( is_ref,  mt_a)  = match  * a. kind ( )  { 
10021002            ty:: Ref ( _,  ty,  mutbl)  => ( true ,  ty:: TypeAndMut  {  ty,  mutbl } ) , 
10031003            ty:: RawPtr ( ty,  mutbl)  => ( false ,  ty:: TypeAndMut  {  ty,  mutbl } ) , 
1004-             _ => return  self . unify_and ( a,  b,  identity ) , 
1004+             _ => return  self . unify ( a,  b) , 
10051005        } ; 
10061006        coerce_mutbls ( mt_a. mutbl ,  mutbl_b) ?; 
10071007
@@ -1011,16 +1011,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
10111011        // representation, we still register an Adjust::DerefRef so that 
10121012        // regionck knows that the region for `a` must be valid here. 
10131013        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-             } ) 
1014+             self . unify_and ( 
1015+                 a_raw , 
1016+                 b , 
1017+                 [ Adjustment  {  kind :  Adjust :: Deref ( None ) ,  target :  mt_a . ty   } ] , 
1018+                 Adjust :: Borrow ( AutoBorrow :: RawPtr ( mutbl_b ) ) , 
1019+             ) 
10201020        }  else  if  mt_a. mutbl  != mutbl_b { 
1021-             self . unify_and ( a_raw,  b,  simple ( Adjust :: Pointer ( PointerCoercion :: MutToConstPointer ) ) ) 
1021+             self . unify_and ( a_raw,  b,  [ ] ,   Adjust :: Pointer ( PointerCoercion :: MutToConstPointer ) ) 
10221022        }  else  { 
1023-             self . unify_and ( a_raw,  b,  identity ) 
1023+             self . unify ( a_raw,  b) 
10241024        } 
10251025    } 
10261026} 
@@ -1118,9 +1118,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
11181118        let  cause = self . cause ( DUMMY_SP ,  ObligationCauseCode :: ExprAssignable ) ; 
11191119        // We don't ever need two-phase here since we throw out the result of the coercion. 
11201120        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 ) ) 
1121+         coerce. autoderef ( DUMMY_SP ,  expr_ty ) . find_map ( | ( ty ,  steps ) |  { 
1122+             self . probe ( |_| coerce . unify_raw ( ty ,  target ) ) . ok ( ) . map ( |_| steps ) 
1123+         } ) 
11241124    } 
11251125
11261126    /// Given a type, this function will calculate and return the type given 
0 commit comments