@@ -42,9 +42,8 @@ use super::{MiscVariable, TypeTrace};
4242use ty:: { IntType , UintType } ;
4343use ty:: { self , Ty , TyCtxt } ;
4444use ty:: error:: TypeError ;
45- use ty:: fold:: TypeFoldable ;
46- use ty:: relate:: { RelateResult , TypeRelation } ;
47- use traits:: PredicateObligations ;
45+ use ty:: relate:: { self , Relate , RelateResult , TypeRelation } ;
46+ use traits:: { Obligation , PredicateObligations } ;
4847
4948use syntax:: ast;
5049use syntax_pos:: Span ;
@@ -207,11 +206,16 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
207206 // `'?2` and `?3` are fresh region/type inference
208207 // variables. (Down below, we will relate `a_ty <: b_ty`,
209208 // adding constraints like `'x: '?2` and `?1 <: ?3`.)
210- let b_ty = self . generalize ( a_ty, b_vid, dir == EqTo ) ?;
209+ let Generalization { ty : b_ty, needs_wf } = self . generalize ( a_ty, b_vid, dir) ?;
211210 debug ! ( "instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})" ,
212211 a_ty, dir, b_vid, b_ty) ;
213212 self . infcx . type_variables . borrow_mut ( ) . instantiate ( b_vid, b_ty) ;
214213
214+ if needs_wf {
215+ self . obligations . push ( Obligation :: new ( self . trace . cause . clone ( ) ,
216+ ty:: Predicate :: WellFormed ( b_ty) ) ) ;
217+ }
218+
215219 // Finally, relate `b_ty` to `a_ty`, as described in previous comment.
216220 //
217221 // FIXME(#16847): This code is non-ideal because all these subtype
@@ -230,50 +234,125 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
230234
231235 /// Attempts to generalize `ty` for the type variable `for_vid`.
232236 /// 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.
237+ /// references `for_vid`. The `dir` is the "direction" for which we
238+ /// a performing the generalization (i.e., are we producing a type
239+ /// that can be used as a supertype etc).
237240 ///
238241 /// Preconditions:
239242 ///
240243 /// - `for_vid` is a "root vid"
241244 fn generalize ( & self ,
242245 ty : Ty < ' tcx > ,
243246 for_vid : ty:: TyVid ,
244- is_eq_relation : bool )
245- -> RelateResult < ' tcx , Ty < ' tcx > >
247+ dir : RelationDir )
248+ -> RelateResult < ' tcx , Generalization < ' tcx > >
246249 {
250+ // Determine the ambient variance within which `ty` appears.
251+ // The surrounding equation is:
252+ //
253+ // ty [op] ty2
254+ //
255+ // where `op` is either `==`, `<:`, or `:>`. This maps quite
256+ // naturally.
257+ let ambient_variance = match dir {
258+ RelationDir :: EqTo => ty:: Invariant ,
259+ RelationDir :: SubtypeOf => ty:: Covariant ,
260+ RelationDir :: SupertypeOf => ty:: Contravariant ,
261+ } ;
262+
247263 let mut generalize = Generalizer {
248264 infcx : self . infcx ,
249265 span : self . trace . cause . span ,
250266 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
267+ ambient_variance : ambient_variance ,
268+ needs_wf : false ,
253269 } ;
254- let u = ty. fold_with ( & mut generalize) ;
255- if generalize. cycle_detected {
256- Err ( TypeError :: CyclicTy )
257- } else {
258- Ok ( u)
259- }
270+
271+ let ty = generalize. relate ( & ty, & ty) ?;
272+ let needs_wf = generalize. needs_wf ;
273+ Ok ( Generalization { ty, needs_wf } )
260274 }
261275}
262276
263277struct Generalizer < ' cx , ' gcx : ' cx +' tcx , ' tcx : ' cx > {
264278 infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
265279 span : Span ,
266280 for_vid_sub_root : ty:: TyVid ,
267- is_eq_relation : bool ,
268- cycle_detected : bool ,
281+ ambient_variance : ty :: Variance ,
282+ needs_wf : bool , // see the field `needs_wf` in `Generalization`
269283}
270284
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 > {
285+ /// Result from a generalization operation. This includes
286+ /// not only the generalized type, but also a bool flag
287+ /// indicating whether further WF checks are needed.q
288+ struct Generalization < ' tcx > {
289+ ty : Ty < ' tcx > ,
290+
291+ /// If true, then the generalized type may not be well-formed,
292+ /// even if the source type is well-formed, so we should add an
293+ /// additional check to enforce that it is. This arises in
294+ /// particular around 'bivariant' type parameters that are only
295+ /// constrained by a where-clause. As an example, imagine a type:
296+ ///
297+ /// struct Foo<A, B> where A: Iterator<Item=B> {
298+ /// data: A
299+ /// }
300+ ///
301+ /// here, `A` will be covariant, but `B` is
302+ /// unconstrained. However, whatever it is, for `Foo` to be WF, it
303+ /// must be equal to `A::Item`. If we have an input `Foo<?A, ?B>`,
304+ /// then after generalization we will wind up with a type like
305+ /// `Foo<?C, ?D>`. When we enforce that `Foo<?A, ?B> <: Foo<?C,
306+ /// ?D>` (or `>:`), we will wind up with the requirement that `?A
307+ /// <: ?C`, but no particular relationship between `?B` and `?D`
308+ /// (after all, we do not know the variance of the normalized form
309+ /// of `A::Item` with respect to `A`). If we do nothing else, this
310+ /// may mean that `?D` goes unconstrained (as in #41677). So, in
311+ /// this scenario where we create a new type variable in a
312+ /// bivariant context, we set the `needs_wf` flag to true. This
313+ /// will force the calling code to check that `WF(Foo<?C, ?D>)`
314+ /// holds, which in turn implies that `?C::Item == ?D`. So once
315+ /// `?C` is constrained, that should suffice to restrict `?D`.
316+ needs_wf : bool ,
317+ }
318+
319+ impl < ' cx , ' gcx , ' tcx > TypeRelation < ' cx , ' gcx , ' tcx > for Generalizer < ' cx , ' gcx , ' tcx > {
320+ fn tcx ( & self ) -> TyCtxt < ' cx , ' gcx , ' tcx > {
273321 self . infcx . tcx
274322 }
275323
276- fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
324+ fn tag ( & self ) -> & ' static str {
325+ "Generalizer"
326+ }
327+
328+ fn a_is_expected ( & self ) -> bool {
329+ true
330+ }
331+
332+ fn binders < T > ( & mut self , a : & ty:: Binder < T > , b : & ty:: Binder < T > )
333+ -> RelateResult < ' tcx , ty:: Binder < T > >
334+ where T : Relate < ' tcx >
335+ {
336+ Ok ( ty:: Binder ( self . relate ( a. skip_binder ( ) , b. skip_binder ( ) ) ?) )
337+ }
338+
339+ fn relate_with_variance < T : Relate < ' tcx > > ( & mut self ,
340+ variance : ty:: Variance ,
341+ a : & T ,
342+ b : & T )
343+ -> RelateResult < ' tcx , T >
344+ {
345+ let old_ambient_variance = self . ambient_variance ;
346+ self . ambient_variance = self . ambient_variance . xform ( variance) ;
347+
348+ let result = self . relate ( a, b) ;
349+ self . ambient_variance = old_ambient_variance;
350+ result
351+ }
352+
353+ fn tys ( & mut self , t : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
354+ assert_eq ! ( t, t2) ; // we are abusing TypeRelation here; both LHS and RHS ought to be ==
355+
277356 // Check to see whether the type we are genealizing references
278357 // any other type variable related to `vid` via
279358 // subtyping. This is basically our "occurs check", preventing
@@ -286,41 +365,63 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
286365 if sub_vid == self . for_vid_sub_root {
287366 // If sub-roots are equal, then `for_vid` and
288367 // `vid` are related via subtyping.
289- self . cycle_detected = true ;
290- self . tcx ( ) . types . err
368+ return Err ( TypeError :: CyclicTy ) ;
291369 } else {
292370 match variables. probe_root ( vid) {
293371 Some ( u) => {
294372 drop ( variables) ;
295- self . fold_ty ( u)
373+ self . relate ( & u , & u)
296374 }
297375 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
376+ match self . ambient_variance {
377+ // Invariant: no need to make a fresh type variable.
378+ ty:: Invariant => return Ok ( t) ,
379+
380+ // Bivariant: make a fresh var, but we
381+ // may need a WF predicate. See
382+ // comment on `needs_wf` field for
383+ // more info.
384+ ty:: Bivariant => self . needs_wf = true ,
385+
386+ // Co/contravariant: this will be
387+ // sufficiently constrained later on.
388+ ty:: Covariant | ty:: Contravariant => ( ) ,
307389 }
390+
391+ let origin = variables. origin ( vid) ;
392+ let new_var_id = variables. new_var ( false , origin, None ) ;
393+ let u = self . tcx ( ) . mk_var ( new_var_id) ;
394+ debug ! ( "generalize: replacing original vid={:?} with new={:?}" ,
395+ vid, u) ;
396+ return Ok ( u) ;
308397 }
309398 }
310399 }
311400 }
401+ ty:: TyInfer ( ty:: IntVar ( _) ) |
402+ ty:: TyInfer ( ty:: FloatVar ( _) ) => {
403+ // No matter what mode we are in,
404+ // integer/floating-point types must be equal to be
405+ // relatable.
406+ Ok ( t)
407+ }
312408 _ => {
313- t . super_fold_with ( self )
409+ relate :: super_relate_tys ( self , t , t )
314410 }
315411 }
316412 }
317413
318- fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
414+ fn regions ( & mut self , r : ty:: Region < ' tcx > , r2 : ty:: Region < ' tcx > )
415+ -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
416+ assert_eq ! ( r, r2) ; // we are abusing TypeRelation here; both LHS and RHS ought to be ==
417+
319418 match * r {
320419 // Never make variables for regions bound within the type itself,
321420 // nor for erased regions.
322421 ty:: ReLateBound ( ..) |
323- ty:: ReErased => { return r; }
422+ ty:: ReErased => {
423+ return Ok ( r) ;
424+ }
324425
325426 // Early-bound regions should really have been substituted away before
326427 // we get to this point.
@@ -342,15 +443,16 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
342443 ty:: ReScope ( ..) |
343444 ty:: ReVar ( ..) |
344445 ty:: ReFree ( ..) => {
345- if self . is_eq_relation {
346- return r;
446+ match self . ambient_variance {
447+ ty:: Invariant => return Ok ( r) ,
448+ ty:: Bivariant | ty:: Covariant | ty:: Contravariant => ( ) ,
347449 }
348450 }
349451 }
350452
351453 // FIXME: This is non-ideal because we don't give a
352454 // very descriptive origin for this region variable.
353- self . infcx . next_region_var ( MiscVariable ( self . span ) )
455+ Ok ( self . infcx . next_region_var ( MiscVariable ( self . span ) ) )
354456 }
355457}
356458
0 commit comments