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