@@ -39,12 +39,13 @@ use super::sub::Sub;
3939use super :: InferCtxt ;
4040use super :: { MiscVariable , TypeTrace } ;
4141
42+ use hir:: def_id:: DefId ;
4243use ty:: { IntType , UintType } ;
4344use ty:: { self , Ty , TyCtxt } ;
4445use ty:: error:: TypeError ;
45- use ty:: fold :: TypeFoldable ;
46- use ty:: relate :: { RelateResult , TypeRelation } ;
47- use traits:: PredicateObligations ;
46+ use ty:: relate :: { self , Relate , RelateResult , TypeRelation } ;
47+ use ty:: subst :: Substs ;
48+ use traits:: { Obligation , PredicateObligations } ;
4849
4950use syntax:: ast;
5051use syntax_pos:: Span ;
@@ -207,11 +208,16 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
207208 // `'?2` and `?3` are fresh region/type inference
208209 // variables. (Down below, we will relate `a_ty <: b_ty`,
209210 // adding constraints like `'x: '?2` and `?1 <: ?3`.)
210- let b_ty = self . generalize ( a_ty, b_vid, dir == EqTo ) ?;
211+ let Generalization { ty : b_ty, needs_wf } = self . generalize ( a_ty, b_vid, dir) ?;
211212 debug ! ( "instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})" ,
212213 a_ty, dir, b_vid, b_ty) ;
213214 self . infcx . type_variables . borrow_mut ( ) . instantiate ( b_vid, b_ty) ;
214215
216+ if needs_wf {
217+ self . obligations . push ( Obligation :: new ( self . trace . cause . clone ( ) ,
218+ ty:: Predicate :: WellFormed ( b_ty) ) ) ;
219+ }
220+
215221 // Finally, relate `b_ty` to `a_ty`, as described in previous comment.
216222 //
217223 // FIXME(#16847): This code is non-ideal because all these subtype
@@ -230,50 +236,148 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
230236
231237 /// Attempts to generalize `ty` for the type variable `for_vid`.
232238 /// This checks for cycle -- that is, whether the type `ty`
233- /// references `for_vid`. If `is_eq_relation` is false, it will
234- /// also replace all regions/unbound-type-variables with fresh
235- /// variables. Returns `TyError` in the case of a cycle, `Ok`
236- /// otherwise.
239+ /// references `for_vid`. The `dir` is the "direction" for which we
240+ /// a performing the generalization (i.e., are we producing a type
241+ /// that can be used as a supertype etc).
237242 ///
238243 /// Preconditions:
239244 ///
240245 /// - `for_vid` is a "root vid"
241246 fn generalize ( & self ,
242247 ty : Ty < ' tcx > ,
243248 for_vid : ty:: TyVid ,
244- is_eq_relation : bool )
245- -> RelateResult < ' tcx , Ty < ' tcx > >
249+ dir : RelationDir )
250+ -> RelateResult < ' tcx , Generalization < ' tcx > >
246251 {
252+ // Determine the ambient variance within which `ty` appears.
253+ // The surrounding equation is:
254+ //
255+ // ty [op] ty2
256+ //
257+ // where `op` is either `==`, `<:`, or `:>`. This maps quite
258+ // naturally.
259+ let ambient_variance = match dir {
260+ RelationDir :: EqTo => ty:: Invariant ,
261+ RelationDir :: SubtypeOf => ty:: Covariant ,
262+ RelationDir :: SupertypeOf => ty:: Contravariant ,
263+ } ;
264+
247265 let mut generalize = Generalizer {
248266 infcx : self . infcx ,
249267 span : self . trace . cause . span ,
250268 for_vid_sub_root : self . infcx . type_variables . borrow_mut ( ) . sub_root_var ( for_vid) ,
251- is_eq_relation : is_eq_relation ,
252- cycle_detected : false
269+ ambient_variance : ambient_variance ,
270+ needs_wf : false ,
253271 } ;
254- let u = ty. fold_with ( & mut generalize) ;
255- if generalize. cycle_detected {
256- Err ( TypeError :: CyclicTy )
257- } else {
258- Ok ( u)
259- }
272+
273+ let ty = generalize. relate ( & ty, & ty) ?;
274+ let needs_wf = generalize. needs_wf ;
275+ Ok ( Generalization { ty, needs_wf } )
260276 }
261277}
262278
263279struct Generalizer < ' cx , ' gcx : ' cx +' tcx , ' tcx : ' cx > {
264280 infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
265281 span : Span ,
266282 for_vid_sub_root : ty:: TyVid ,
267- is_eq_relation : bool ,
268- cycle_detected : bool ,
283+ ambient_variance : ty :: Variance ,
284+ needs_wf : bool , // see the field `needs_wf` in `Generalization`
269285}
270286
271- impl < ' cx , ' gcx , ' tcx > ty:: fold:: TypeFolder < ' gcx , ' tcx > for Generalizer < ' cx , ' gcx , ' tcx > {
272- fn tcx < ' a > ( & ' a self ) -> TyCtxt < ' a , ' gcx , ' tcx > {
287+ /// Result from a generalization operation. This includes
288+ /// not only the generalized type, but also a bool flag
289+ /// indicating whether further WF checks are needed.q
290+ struct Generalization < ' tcx > {
291+ ty : Ty < ' tcx > ,
292+
293+ /// If true, then the generalized type may not be well-formed,
294+ /// even if the source type is well-formed, so we should add an
295+ /// additional check to enforce that it is. This arises in
296+ /// particular around 'bivariant' type parameters that are only
297+ /// constrained by a where-clause. As an example, imagine a type:
298+ ///
299+ /// struct Foo<A, B> where A: Iterator<Item=B> {
300+ /// data: A
301+ /// }
302+ ///
303+ /// here, `A` will be covariant, but `B` is
304+ /// unconstrained. However, whatever it is, for `Foo` to be WF, it
305+ /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
306+ /// then after generalization we will wind up with a type like
307+ /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
308+ /// ?D>` (or `>:`), we will wind up with the requirement that `?A
309+ /// <: ?C`, but no particular relationship between `?B` and `?D`
310+ /// (after all, we do not know the variance of the normalized form
311+ /// of `A::Item` with respect to `A`). If we do nothing else, this
312+ /// may mean that `?D` goes unconstrained (as in #41677). So, in
313+ /// this scenario where we create a new type variable in a
314+ /// bivariant context, we set the `needs_wf` flag to true. This
315+ /// will force the calling code to check that `WF(Foo<?C, ?D>)`
316+ /// holds, which in turn implies that `?C::Item == ?D`. So once
317+ /// `?C` is constrained, that should suffice to restrict `?D`.
318+ needs_wf : bool ,
319+ }
320+
321+ impl < ' cx , ' gcx , ' tcx > TypeRelation < ' cx , ' gcx , ' tcx > for Generalizer < ' cx , ' gcx , ' tcx > {
322+ fn tcx ( & self ) -> TyCtxt < ' cx , ' gcx , ' tcx > {
273323 self . infcx . tcx
274324 }
275325
276- fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
326+ fn tag ( & self ) -> & ' static str {
327+ "Generalizer"
328+ }
329+
330+ fn a_is_expected ( & self ) -> bool {
331+ true
332+ }
333+
334+ fn binders < T > ( & mut self , a : & ty:: Binder < T > , b : & ty:: Binder < T > )
335+ -> RelateResult < ' tcx , ty:: Binder < T > >
336+ where T : Relate < ' tcx >
337+ {
338+ Ok ( ty:: Binder ( self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?) )
339+ }
340+
341+ fn relate_item_substs ( & mut self ,
342+ item_def_id : DefId ,
343+ a_subst : & ' tcx Substs < ' tcx > ,
344+ b_subst : & ' tcx Substs < ' tcx > )
345+ -> RelateResult < ' tcx , & ' tcx Substs < ' tcx > >
346+ {
347+ if self . ambient_variance == ty:: Variance :: Invariant {
348+ // Avoid fetching the variance if we are in an invariant
349+ // context; no need, and it can induce dependency cycles
350+ // (e.g. #41849).
351+ relate:: relate_substs ( self , None , a_subst, b_subst)
352+ } else {
353+ let variances;
354+ let opt_variances = if self . tcx ( ) . variance_computed . get ( ) {
355+ variances = self . tcx ( ) . item_variances ( item_def_id) ;
356+ Some ( & * variances)
357+ } else {
358+ None
359+ } ;
360+ relate:: relate_substs ( self , opt_variances, a_subst, b_subst)
361+ }
362+ }
363+
364+ fn relate_with_variance < T : Relate < ' tcx > > ( & mut self ,
365+ variance : ty:: Variance ,
366+ a : & T ,
367+ b : & T )
368+ -> RelateResult < ' tcx , T >
369+ {
370+ let old_ambient_variance = self . ambient_variance ;
371+ self . ambient_variance = self . ambient_variance . xform ( variance) ;
372+
373+ let result = self . relate ( a, b) ;
374+ self . ambient_variance = old_ambient_variance;
375+ result
376+ }
377+
378+ fn tys ( & mut self , t : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
379+ assert_eq ! ( t, t2) ; // we are abusing TypeRelation here; both LHS and RHS ought to be ==
380+
277381 // Check to see whether the type we are genealizing references
278382 // any other type variable related to `vid` via
279383 // subtyping. This is basically our "occurs check", preventing
@@ -286,41 +390,63 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
286390 if sub_vid == self . for_vid_sub_root {
287391 // If sub-roots are equal, then `for_vid` and
288392 // `vid` are related via subtyping.
289- self . cycle_detected = true ;
290- self . tcx ( ) . types . err
393+ return Err ( TypeError :: CyclicTy ) ;
291394 } else {
292395 match variables. probe_root ( vid) {
293396 Some ( u) => {
294397 drop ( variables) ;
295- self . fold_ty ( u)
398+ self . relate ( & u , & u)
296399 }
297400 None => {
298- if !self . is_eq_relation {
299- let origin = variables. origin ( vid) ;
300- let new_var_id = variables. new_var ( false , origin, None ) ;
301- let u = self . tcx ( ) . mk_var ( new_var_id) ;
302- debug ! ( "generalize: replacing original vid={:?} with new={:?}" ,
303- vid, u) ;
304- u
305- } else {
306- t
401+ match self . ambient_variance {
402+ // Invariant: no need to make a fresh type variable.
403+ ty:: Invariant => return Ok ( t) ,
404+
405+ // Bivariant: make a fresh var, but we
406+ // may need a WF predicate. See
407+ // comment on `needs_wf` field for
408+ // more info.
409+ ty:: Bivariant => self . needs_wf = true ,
410+
411+ // Co/contravariant: this will be
412+ // sufficiently constrained later on.
413+ ty:: Covariant | ty:: Contravariant => ( ) ,
307414 }
415+
416+ let origin = variables. origin ( vid) ;
417+ let new_var_id = variables. new_var ( false , origin, None ) ;
418+ let u = self . tcx ( ) . mk_var ( new_var_id) ;
419+ debug ! ( "generalize: replacing original vid={:?} with new={:?}" ,
420+ vid, u) ;
421+ return Ok ( u) ;
308422 }
309423 }
310424 }
311425 }
426+ ty:: TyInfer ( ty:: IntVar ( _) ) |
427+ ty:: TyInfer ( ty:: FloatVar ( _) ) => {
428+ // No matter what mode we are in,
429+ // integer/floating-point types must be equal to be
430+ // relatable.
431+ Ok ( t)
432+ }
312433 _ => {
313- t . super_fold_with ( self )
434+ relate :: super_relate_tys ( self , t , t )
314435 }
315436 }
316437 }
317438
318- fn fold_region ( & mut self , r : & ' tcx ty:: Region ) -> & ' tcx ty:: Region {
439+ fn regions ( & mut self , r : & ' tcx ty:: Region , r2 : & ' tcx ty:: Region )
440+ -> RelateResult < ' tcx , & ' tcx ty:: Region > {
441+ assert_eq ! ( r, r2) ; // we are abusing TypeRelation here; both LHS and RHS ought to be ==
442+
319443 match * r {
320444 // Never make variables for regions bound within the type itself,
321445 // nor for erased regions.
322446 ty:: ReLateBound ( ..) |
323- ty:: ReErased => { return r; }
447+ ty:: ReErased => {
448+ return Ok ( r) ;
449+ }
324450
325451 // Early-bound regions should really have been substituted away before
326452 // we get to this point.
@@ -342,15 +468,16 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
342468 ty:: ReScope ( ..) |
343469 ty:: ReVar ( ..) |
344470 ty:: ReFree ( ..) => {
345- if self . is_eq_relation {
346- return r;
471+ match self . ambient_variance {
472+ ty:: Invariant => return Ok ( r) ,
473+ ty:: Bivariant | ty:: Covariant | ty:: Contravariant => ( ) ,
347474 }
348475 }
349476 }
350477
351478 // FIXME: This is non-ideal because we don't give a
352479 // very descriptive origin for this region variable.
353- self . infcx . next_region_var ( MiscVariable ( self . span ) )
480+ Ok ( self . infcx . next_region_var ( MiscVariable ( self . span ) ) )
354481 }
355482}
356483
0 commit comments