@@ -39,12 +39,13 @@ use super::sub::Sub;
39
39
use super :: InferCtxt ;
40
40
use super :: { MiscVariable , TypeTrace } ;
41
41
42
+ use hir:: def_id:: DefId ;
42
43
use ty:: { IntType , UintType } ;
43
44
use ty:: { self , Ty , TyCtxt } ;
44
45
use 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 } ;
48
49
49
50
use syntax:: ast;
50
51
use syntax_pos:: Span ;
@@ -207,11 +208,16 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
207
208
// `'?2` and `?3` are fresh region/type inference
208
209
// variables. (Down below, we will relate `a_ty <: b_ty`,
209
210
// 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) ?;
211
212
debug ! ( "instantiate(a_ty={:?}, dir={:?}, b_vid={:?}, generalized b_ty={:?})" ,
212
213
a_ty, dir, b_vid, b_ty) ;
213
214
self . infcx . type_variables . borrow_mut ( ) . instantiate ( b_vid, b_ty) ;
214
215
216
+ if needs_wf {
217
+ self . obligations . push ( Obligation :: new ( self . trace . cause . clone ( ) ,
218
+ ty:: Predicate :: WellFormed ( b_ty) ) ) ;
219
+ }
220
+
215
221
// Finally, relate `b_ty` to `a_ty`, as described in previous comment.
216
222
//
217
223
// FIXME(#16847): This code is non-ideal because all these subtype
@@ -230,50 +236,148 @@ impl<'infcx, 'gcx, 'tcx> CombineFields<'infcx, 'gcx, 'tcx> {
230
236
231
237
/// Attempts to generalize `ty` for the type variable `for_vid`.
232
238
/// 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).
237
242
///
238
243
/// Preconditions:
239
244
///
240
245
/// - `for_vid` is a "root vid"
241
246
fn generalize ( & self ,
242
247
ty : Ty < ' tcx > ,
243
248
for_vid : ty:: TyVid ,
244
- is_eq_relation : bool )
245
- -> RelateResult < ' tcx , Ty < ' tcx > >
249
+ dir : RelationDir )
250
+ -> RelateResult < ' tcx , Generalization < ' tcx > >
246
251
{
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
+
247
265
let mut generalize = Generalizer {
248
266
infcx : self . infcx ,
249
267
span : self . trace . cause . span ,
250
268
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 ,
253
271
} ;
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 } )
260
276
}
261
277
}
262
278
263
279
struct Generalizer < ' cx , ' gcx : ' cx +' tcx , ' tcx : ' cx > {
264
280
infcx : & ' cx InferCtxt < ' cx , ' gcx , ' tcx > ,
265
281
span : Span ,
266
282
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`
269
285
}
270
286
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 > {
273
323
self . infcx . tcx
274
324
}
275
325
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
+
277
381
// Check to see whether the type we are genealizing references
278
382
// any other type variable related to `vid` via
279
383
// 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
286
390
if sub_vid == self . for_vid_sub_root {
287
391
// If sub-roots are equal, then `for_vid` and
288
392
// `vid` are related via subtyping.
289
- self . cycle_detected = true ;
290
- self . tcx ( ) . types . err
393
+ return Err ( TypeError :: CyclicTy ) ;
291
394
} else {
292
395
match variables. probe_root ( vid) {
293
396
Some ( u) => {
294
397
drop ( variables) ;
295
- self . fold_ty ( u)
398
+ self . relate ( & u , & u)
296
399
}
297
400
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 => ( ) ,
307
414
}
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) ;
308
422
}
309
423
}
310
424
}
311
425
}
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
+ }
312
433
_ => {
313
- t . super_fold_with ( self )
434
+ relate :: super_relate_tys ( self , t , t )
314
435
}
315
436
}
316
437
}
317
438
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
+
319
443
match * r {
320
444
// Never make variables for regions bound within the type itself,
321
445
// nor for erased regions.
322
446
ty:: ReLateBound ( ..) |
323
- ty:: ReErased => { return r; }
447
+ ty:: ReErased => {
448
+ return Ok ( r) ;
449
+ }
324
450
325
451
// Early-bound regions should really have been substituted away before
326
452
// we get to this point.
@@ -342,15 +468,16 @@ impl<'cx, 'gcx, 'tcx> ty::fold::TypeFolder<'gcx, 'tcx> for Generalizer<'cx, 'gcx
342
468
ty:: ReScope ( ..) |
343
469
ty:: ReVar ( ..) |
344
470
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 => ( ) ,
347
474
}
348
475
}
349
476
}
350
477
351
478
// FIXME: This is non-ideal because we don't give a
352
479
// 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 ) ) )
354
481
}
355
482
}
356
483
0 commit comments