@@ -42,6 +42,7 @@ use rustc_hir as hir;
4242use rustc_hir:: def_id:: DefId ;
4343use rustc_infer:: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind } ;
4444use rustc_infer:: infer:: { Coercion , InferOk , InferResult } ;
45+ use rustc_infer:: traits:: Obligation ;
4546use rustc_middle:: lint:: in_external_macro;
4647use rustc_middle:: ty:: adjustment:: {
4748 Adjust , Adjustment , AllowTwoPhase , AutoBorrow , AutoBorrowMutability , PointerCast ,
@@ -50,7 +51,7 @@ use rustc_middle::ty::error::TypeError;
5051use rustc_middle:: ty:: fold:: TypeFoldable ;
5152use rustc_middle:: ty:: relate:: RelateResult ;
5253use rustc_middle:: ty:: subst:: SubstsRef ;
53- use rustc_middle:: ty:: { self , Ty , TypeAndMut } ;
54+ use rustc_middle:: ty:: { self , ToPredicate , Ty , TypeAndMut } ;
5455use rustc_session:: parse:: feature_err;
5556use rustc_span:: symbol:: sym;
5657use rustc_span:: { self , BytePos , Span } ;
@@ -172,7 +173,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
172173 kind : TypeVariableOriginKind :: AdjustmentType ,
173174 span : self . cause . span ,
174175 } ) ;
175- self . unify_and ( & b , & diverging_ty , simple ( Adjust :: NeverToAny ) )
176+ self . coerce_from_inference_variable ( diverging_ty , b , simple ( Adjust :: NeverToAny ) )
176177 } else {
177178 success ( simple ( Adjust :: NeverToAny ) ( b) , b, vec ! [ ] )
178179 } ;
@@ -182,7 +183,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
182183 // we have no information about the source type. This will always
183184 // ultimately fall back to some form of subtyping.
184185 if a. is_ty_var ( ) {
185- return self . coerce_from_inference_variable ( a, b) ;
186+ return self . coerce_from_inference_variable ( a, b, identity ) ;
186187 }
187188
188189 // Consider coercing the subtype to a DST
@@ -245,11 +246,53 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
245246 /// Coercing *from* an inference variable. In this case, we have no information
246247 /// about the source type, so we can't really do a true coercion and we always
247248 /// 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) ;
249256 assert ! ( a. is_ty_var( ) && self . infcx. shallow_resolve( a) == a) ;
250257 assert ! ( self . infcx. shallow_resolve( b) == b) ;
251258
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+ }
253296 }
254297
255298 /// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
0 commit comments