@@ -103,15 +103,6 @@ fn coerce_mutbls<'tcx>(
103
103
if from_mutbl >= to_mutbl { Ok ( ( ) ) } else { Err ( TypeError :: Mutability ) }
104
104
}
105
105
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
-
115
106
/// This always returns `Ok(...)`.
116
107
fn success < ' tcx > (
117
108
adj : Vec < Adjustment < ' tcx > > ,
@@ -131,7 +122,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
131
122
Coerce { fcx, cause, allow_two_phase, use_lub : false , coerce_never }
132
123
}
133
124
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 > > {
135
126
debug ! ( "unify(a: {:?}, b: {:?}, use_lub: {})" , a, b, self . use_lub) ;
136
127
self . commit_if_ok ( |_| {
137
128
let at = self . at ( & self . cause , self . fcx . param_env ) ;
@@ -161,13 +152,30 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
161
152
} )
162
153
}
163
154
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
+
164
161
/// 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
+ } )
171
179
}
172
180
173
181
#[ instrument( skip( self ) ) ]
@@ -180,18 +188,22 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
180
188
// Coercing from `!` to any type is allowed:
181
189
if a. is_never ( ) {
182
190
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
+ ) ;
184
196
} else {
185
197
// Otherwise the only coercion we can do is unification.
186
- return self . unify_and ( a, b, identity ) ;
198
+ return self . unify ( a, b) ;
187
199
}
188
200
}
189
201
190
202
// Coercing *from* an unresolved inference variable means that
191
203
// we have no information about the source type. This will always
192
204
// ultimately fall back to some form of subtyping.
193
205
if a. is_ty_var ( ) {
194
- return self . coerce_from_inference_variable ( a, b, identity ) ;
206
+ return self . coerce_from_inference_variable ( a, b) ;
195
207
}
196
208
197
209
// Consider coercing the subtype to a DST
@@ -247,7 +259,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
247
259
ty:: FnPtr ( a_sig_tys, a_hdr) => {
248
260
// We permit coercion of fn pointers to drop the
249
261
// 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)
251
263
}
252
264
ty:: Closure ( closure_def_id_a, args_a) => {
253
265
// Non-capturing closures are coercible to
@@ -257,20 +269,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
257
269
}
258
270
_ => {
259
271
// Otherwise, just use unification rules.
260
- self . unify_and ( a, b, identity )
272
+ self . unify ( a, b)
261
273
}
262
274
}
263
275
}
264
276
265
277
/// Coercing *from* an inference variable. In this case, we have no information
266
278
/// about the source type, so we can't really do a true coercion and we always
267
279
/// 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 > {
274
281
debug ! ( "coerce_from_inference_variable(a={:?}, b={:?})" , a, b) ;
275
282
assert ! ( a. is_ty_var( ) && self . shallow_resolve( a) == a) ;
276
283
assert ! ( self . shallow_resolve( b) == b) ;
@@ -298,12 +305,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
298
305
"coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}" ,
299
306
target_ty, obligations
300
307
) ;
301
- let adjustments = make_adjustments ( target_ty) ;
302
- InferResult :: Ok ( InferOk { value : ( adjustments, target_ty) , obligations } )
308
+ success ( vec ! [ ] , target_ty, obligations)
303
309
} else {
304
310
// One unresolved type variable: just apply subtyping, we may be able
305
311
// to do something useful.
306
- self . unify_and ( a, b, make_adjustments )
312
+ self . unify ( a, b)
307
313
}
308
314
}
309
315
@@ -331,7 +337,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
331
337
coerce_mutbls ( mt_a. mutbl , mutbl_b) ?;
332
338
( r_a, mt_a)
333
339
}
334
- _ => return self . unify_and ( a, b, identity ) ,
340
+ _ => return self . unify ( a, b) ,
335
341
} ;
336
342
337
343
let span = self . cause . span ;
@@ -437,7 +443,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
437
443
referent_ty,
438
444
mutbl_b, // [1] above
439
445
) ;
440
- match self . unify ( derefd_ty_a, b) {
446
+ match self . unify_raw ( derefd_ty_a, b) {
441
447
Ok ( ok) => {
442
448
found = Some ( ok) ;
443
449
break ;
@@ -579,13 +585,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
579
585
// We only have the latter, so we use an inference variable
580
586
// for the former and let type inference do the rest.
581
587
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
+ ) ?;
589
595
590
596
let mut selcx = traits:: SelectionContext :: new ( self ) ;
591
597
@@ -708,7 +714,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
708
714
&& let ty:: Dynamic ( b_data, _, ty:: DynStar ) = b. kind ( )
709
715
&& a_data. principal_def_id ( ) == b_data. principal_def_id ( )
710
716
{
711
- return self . unify_and ( a, b, |_| vec ! [ ] ) ;
717
+ return self . unify ( a, b) ;
712
718
}
713
719
714
720
// Check the obligations of the cast -- for example, when casting
@@ -808,23 +814,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
808
814
809
815
// To complete the reborrow, we need to make sure we can unify the inner types, and if so we
810
816
// 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) )
814
818
}
815
819
816
- fn coerce_from_safe_fn < F , G > (
820
+ fn coerce_from_safe_fn (
817
821
& self ,
818
- a : Ty < ' tcx > ,
819
822
fn_ty_a : ty:: PolyFnSig < ' tcx > ,
820
823
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 > {
828
826
self . commit_if_ok ( |snapshot| {
829
827
let outer_universe = self . infcx . universe ( ) ;
830
828
@@ -833,9 +831,19 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
833
831
&& hdr_b. safety . is_unsafe ( )
834
832
{
835
833
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
+ )
837
841
} 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
+ }
839
847
} ;
840
848
841
849
// FIXME(#73154): This is a hack. Currently LUB can generate
@@ -852,7 +860,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
852
860
853
861
fn coerce_from_fn_pointer (
854
862
& self ,
855
- a : Ty < ' tcx > ,
856
863
fn_ty_a : ty:: PolyFnSig < ' tcx > ,
857
864
b : Ty < ' tcx > ,
858
865
) -> CoerceResult < ' tcx > {
@@ -861,15 +868,9 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
861
868
//!
862
869
863
870
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 )
873
874
}
874
875
875
876
fn coerce_from_fn_item ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
@@ -916,30 +917,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
916
917
self . at ( & self . cause , self . param_env ) . normalize ( a_sig) ;
917
918
obligations. extend ( o1) ;
918
919
919
- let a_fn_pointer = Ty :: new_fn_ptr ( self . tcx , a_sig) ;
920
920
let InferOk { value, obligations : o2 } = self . coerce_from_safe_fn (
921
- a_fn_pointer,
922
921
a_sig,
923
922
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 ) ) ,
937
924
) ?;
938
925
939
926
obligations. extend ( o2) ;
940
927
Ok ( InferOk { value, obligations } )
941
928
}
942
- _ => self . unify_and ( a, b, identity ) ,
929
+ _ => self . unify ( a, b) ,
943
930
}
944
931
}
945
932
@@ -983,10 +970,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
983
970
self . unify_and (
984
971
pointer_ty,
985
972
b,
986
- simple ( Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ) ,
973
+ [ ] ,
974
+ Adjust :: Pointer ( PointerCoercion :: ClosureFnPointer ( safety) ) ,
987
975
)
988
976
}
989
- _ => self . unify_and ( a, b, identity ) ,
977
+ _ => self . unify ( a, b) ,
990
978
}
991
979
}
992
980
@@ -1001,7 +989,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
1001
989
let ( is_ref, mt_a) = match * a. kind ( ) {
1002
990
ty:: Ref ( _, ty, mutbl) => ( true , ty:: TypeAndMut { ty, mutbl } ) ,
1003
991
ty:: RawPtr ( ty, mutbl) => ( false , ty:: TypeAndMut { ty, mutbl } ) ,
1004
- _ => return self . unify_and ( a, b, identity ) ,
992
+ _ => return self . unify ( a, b) ,
1005
993
} ;
1006
994
coerce_mutbls ( mt_a. mutbl , mutbl_b) ?;
1007
995
@@ -1011,16 +999,16 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
1011
999
// representation, we still register an Adjust::DerefRef so that
1012
1000
// regionck knows that the region for `a` must be valid here.
1013
1001
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
+ )
1020
1008
} 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 ) )
1022
1010
} else {
1023
- self . unify_and ( a_raw, b, identity )
1011
+ self . unify ( a_raw, b)
1024
1012
}
1025
1013
}
1026
1014
}
@@ -1118,9 +1106,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1118
1106
let cause = self . cause ( DUMMY_SP , ObligationCauseCode :: ExprAssignable ) ;
1119
1107
// We don't ever need two-phase here since we throw out the result of the coercion.
1120
1108
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
+ } )
1124
1112
}
1125
1113
1126
1114
/// Given a type, this function will calculate and return the type given
0 commit comments