@@ -42,6 +42,7 @@ use rustc_hir as hir;
42
42
use rustc_hir:: def_id:: DefId ;
43
43
use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
44
44
use rustc_infer:: infer:: { Coercion , InferOk , InferResult } ;
45
+ use rustc_infer:: traits:: Obligation ;
45
46
use rustc_middle:: lint:: in_external_macro;
46
47
use rustc_middle:: ty:: adjustment:: {
47
48
Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability , PointerCast ,
@@ -50,7 +51,7 @@ use rustc_middle::ty::error::TypeError;
50
51
use rustc_middle:: ty:: fold:: TypeFoldable ;
51
52
use rustc_middle:: ty:: relate:: RelateResult ;
52
53
use rustc_middle:: ty:: subst:: SubstsRef ;
53
- use rustc_middle:: ty:: { self , Ty , TypeAndMut } ;
54
+ use rustc_middle:: ty:: { self , ToPredicate , Ty , TypeAndMut } ;
54
55
use rustc_session:: parse:: feature_err;
55
56
use rustc_span:: symbol:: sym;
56
57
use rustc_span:: { self , BytePos , Span } ;
@@ -172,7 +173,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
172
173
kind : TypeVariableOriginKind :: AdjustmentType ,
173
174
span : self . cause . span ,
174
175
} ) ;
175
- self . unify_and ( & b , & diverging_ty , simple ( Adjust :: NeverToAny ) )
176
+ self . coerce_from_inference_variable ( diverging_ty , b , simple ( Adjust :: NeverToAny ) )
176
177
} else {
177
178
success ( simple ( Adjust :: NeverToAny ) ( b) , b, vec ! [ ] )
178
179
} ;
@@ -182,7 +183,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
182
183
// we have no information about the source type. This will always
183
184
// ultimately fall back to some form of subtyping.
184
185
if a. is_ty_var ( ) {
185
- return self . coerce_from_inference_variable ( a, b) ;
186
+ return self . coerce_from_inference_variable ( a, b, identity ) ;
186
187
}
187
188
188
189
// Consider coercing the subtype to a DST
@@ -245,11 +246,53 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
245
246
/// Coercing *from* an inference variable. In this case, we have no information
246
247
/// about the source type, so we can't really do a true coercion and we always
247
248
/// fall back to subtyping (`unify_and`).
248
- fn coerce_from_inference_variable ( & self , a : Ty < ' tcx > , b : Ty < ' tcx > ) -> CoerceResult < ' tcx > {
249
+ fn coerce_from_inference_variable (
250
+ & self ,
251
+ a : Ty < ' tcx > ,
252
+ b : Ty < ' tcx > ,
253
+ make_adjustments : impl FnOnce ( Ty < ' tcx > ) -> Vec < Adjustment < ' tcx > > ,
254
+ ) -> CoerceResult < ' tcx > {
255
+ debug ! ( "coerce_from_inference_variable(a={:?}, b={:?})" , a, b) ;
249
256
assert ! ( a. is_ty_var( ) && self . infcx. shallow_resolve( a) == a) ;
250
257
assert ! ( self . infcx. shallow_resolve( b) == b) ;
251
258
252
- self . unify_and ( a, b, identity)
259
+ if b. is_ty_var ( ) {
260
+ // Two unresolved type variables: create a `Coerce` predicate.
261
+ let target_ty = if self . use_lub {
262
+ self . infcx . next_ty_var ( TypeVariableOrigin {
263
+ kind : TypeVariableOriginKind :: LatticeVariable ,
264
+ span : self . cause . span ,
265
+ } )
266
+ } else {
267
+ b
268
+ } ;
269
+
270
+ let mut obligations = Vec :: with_capacity ( 2 ) ;
271
+ for & source_ty in & [ a, b] {
272
+ if source_ty != target_ty {
273
+ obligations. push ( Obligation :: new (
274
+ self . cause . clone ( ) ,
275
+ self . param_env ,
276
+ ty:: PredicateKind :: Coerce ( ty:: CoercePredicate {
277
+ a : source_ty,
278
+ b : target_ty,
279
+ } )
280
+ . to_predicate ( self . tcx ( ) ) ,
281
+ ) ) ;
282
+ }
283
+ }
284
+
285
+ debug ! (
286
+ "coerce_from_inference_variable: two inference variables, target_ty={:?}, obligations={:?}" ,
287
+ target_ty, obligations
288
+ ) ;
289
+ let adjustments = make_adjustments ( target_ty) ;
290
+ InferResult :: Ok ( InferOk { value : ( adjustments, target_ty) , obligations } )
291
+ } else {
292
+ // One unresolved type variable: just apply subtyping, we may be able
293
+ // to do something useful.
294
+ self . unify_and ( a, b, make_adjustments)
295
+ }
253
296
}
254
297
255
298
/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
0 commit comments