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