@@ -15,13 +15,12 @@ use borrow_check::nll::ToRegionVid;
15
15
use rustc:: infer:: canonical:: { Canonical , CanonicalVarInfos } ;
16
16
use rustc:: infer:: { InferCtxt , NLLRegionVariableOrigin } ;
17
17
use rustc:: traits:: query:: Fallible ;
18
- use rustc:: ty:: fold:: { TypeFoldable , TypeFolder , TypeVisitor } ;
18
+ use rustc:: ty:: fold:: { TypeFoldable , TypeVisitor } ;
19
19
use rustc:: ty:: relate:: { self , Relate , RelateResult , TypeRelation } ;
20
20
use rustc:: ty:: subst:: Kind ;
21
21
use rustc:: ty:: { self , CanonicalTy , CanonicalVar , RegionVid , Ty , TyCtxt } ;
22
22
use rustc_data_structures:: fx:: FxHashMap ;
23
23
use rustc_data_structures:: indexed_vec:: IndexVec ;
24
- use std:: mem;
25
24
26
25
pub ( super ) fn sub_types < ' tcx > (
27
26
infcx : & InferCtxt < ' _ , ' _ , ' tcx > ,
@@ -262,76 +261,52 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
262
261
/// When we encounter a canonical variable `var` in the output,
263
262
/// equate it with `kind`. If the variable has been previously
264
263
/// equated, then equate it again.
265
- fn equate_var (
264
+ fn relate_var (
266
265
& mut self ,
267
- universal_regions : & UniversalRegions < ' tcx > ,
268
266
var : CanonicalVar ,
269
267
b_kind : Kind < ' tcx > ,
270
268
) -> RelateResult < ' tcx , Kind < ' tcx > > {
271
269
debug ! ( "equate_var(var={:?}, b_kind={:?})" , var, b_kind) ;
272
270
273
- // We only encounter canonical variables when equating.
274
- assert_eq ! ( self . ambient_variance, ty:: Variance :: Invariant ) ;
275
-
276
- // The canonical variable already had a value. Equate that
277
- // value with `b`.
278
- if let Some ( a_kind) = self . canonical_var_values [ var] {
279
- debug ! ( "equate_var: a_kind={:?}" , a_kind) ;
271
+ let generalized_kind = match self . canonical_var_values [ var] {
272
+ Some ( v) => v,
273
+ None => {
274
+ let generalized_kind = self . generalize_value ( b_kind) ;
275
+ self . canonical_var_values [ var] = Some ( generalized_kind) ;
276
+ generalized_kind
277
+ }
278
+ } ;
280
279
281
- // The values we extract from `canonical_var_values` have
282
- // been "instantiated" and hence the set of scopes we have
283
- // doesn't matter -- just to be sure, put an empty vector
284
- // in there.
285
- let old_a_scopes = mem:: replace ( & mut self . a_scopes , vec ! [ ] ) ;
286
- let result = self . relate ( & a_kind, & b_kind) ;
287
- self . a_scopes = old_a_scopes;
280
+ // The generalized values we extract from `canonical_var_values` have
281
+ // been fully instantiated and hence the set of scopes we have
282
+ // doesn't matter -- just to be sure, put an empty vector
283
+ // in there.
284
+ let old_a_scopes = :: std:: mem:: replace ( & mut self . a_scopes , vec ! [ ] ) ;
288
285
289
- debug ! ( "equate_var: complete, result = {:?}" , result) ;
290
- return result;
291
- }
286
+ // Relate the generalized kind to the original one.
287
+ let result = self . relate ( & generalized_kind, & b_kind) ;
292
288
293
- // Not yet. Capture the value from the RHS and carry on.
294
- let closed_kind =
295
- self . instantiate_traversed_binders ( universal_regions, & self . b_scopes , b_kind) ;
296
- self . canonical_var_values [ var] = Some ( closed_kind) ;
297
- debug ! (
298
- "equate_var: capturing value {:?}" ,
299
- self . canonical_var_values[ var]
300
- ) ;
289
+ // Restore the old scopes now.
290
+ self . a_scopes = old_a_scopes;
301
291
302
- // FIXME -- technically, we should add some sort of
303
- // assertion that this value can be named in the universe
304
- // of the canonical variable. But in practice these
305
- // canonical variables only arise presently in cases where
306
- // they are in the root universe and the main typeck has
307
- // ensured there are no universe errors. So we just kind
308
- // of over look this right now.
309
- Ok ( b_kind)
292
+ debug ! ( "equate_var: complete, result = {:?}" , result) ;
293
+ return result;
310
294
}
311
295
312
- /// As we traverse types and pass through binders, we push the
313
- /// values for each of the regions bound by those binders onto
314
- /// `scopes`. This function goes through `kind` and replaces any
315
- /// references into those scopes with the corresponding free
316
- /// region. Thus the resulting value should have no escaping
317
- /// references to bound things and can be transported into other
318
- /// scopes.
319
- fn instantiate_traversed_binders (
296
+ fn generalize_value (
320
297
& self ,
321
- universal_regions : & UniversalRegions < ' tcx > ,
322
- scopes : & [ BoundRegionScope ] ,
323
298
kind : Kind < ' tcx > ,
324
299
) -> Kind < ' tcx > {
325
- let k = kind . fold_with ( & mut BoundReplacer {
300
+ TypeGeneralizer {
326
301
type_rel : self ,
327
302
first_free_index : ty:: INNERMOST ,
328
- universal_regions,
329
- scopes : scopes,
330
- } ) ;
303
+ ambient_variance : self . ambient_variance ,
331
304
332
- assert ! ( !k. has_escaping_regions( ) ) ;
333
-
334
- k
305
+ // These always correspond to an `_` or `'_` written by
306
+ // user, and those are always in the root universe.
307
+ universe : ty:: UniverseIndex :: ROOT ,
308
+ } . relate ( & kind, & kind)
309
+ . unwrap ( )
335
310
}
336
311
}
337
312
@@ -382,21 +357,8 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
382
357
// Watch out for the case that we are matching a `?T` against the
383
358
// right-hand side.
384
359
if let ty:: Infer ( ty:: CanonicalTy ( var) ) = a. sty {
385
- if let Some ( & mut BorrowCheckContext {
386
- universal_regions, ..
387
- } ) = self . borrowck_context
388
- {
389
- self . equate_var ( universal_regions, var, b. into ( ) ) ?;
390
- Ok ( a)
391
- } else {
392
- // if NLL is not enabled just ignore these variables
393
- // for now; in that case we're just doing a "sanity
394
- // check" anyway, and this only affects user-given
395
- // annotations like `let x: Vec<_> = ...` -- and then
396
- // only if the user uses type aliases to make a type
397
- // variable repeat more than once.
398
- Ok ( a)
399
- }
360
+ self . relate_var ( var, b. into ( ) ) ?;
361
+ Ok ( a)
400
362
} else {
401
363
debug ! (
402
364
"tys(a={:?}, b={:?}, variance={:?})" ,
@@ -417,7 +379,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
417
379
} ) = self . borrowck_context
418
380
{
419
381
if let ty:: ReCanonical ( var) = a {
420
- self . equate_var ( universal_regions , * var, b. into ( ) ) ?;
382
+ self . relate_var ( * var, b. into ( ) ) ?;
421
383
return Ok ( a) ;
422
384
}
423
385
@@ -589,48 +551,142 @@ impl<'cx, 'gcx, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'cx, 'gcx, 'tcx> {
589
551
}
590
552
}
591
553
592
- /// When we encounter a binder like `for<..> fn(..)`, we actually have
593
- /// to walk the `fn` value to find all the values bound by the `for`
594
- /// (these are not explicitly present in the ty representation right
595
- /// now). This visitor handles that: it descends the type, tracking
596
- /// binder depth, and finds late-bound regions targeting the
597
- /// `for<..`>. For each of those, it creates an entry in
598
- /// `bound_region_scope`.
599
- struct BoundReplacer < ' me , ' bccx : ' me , ' gcx : ' tcx , ' tcx : ' bccx > {
554
+ /// The "type generalize" is used when handling inference variables.
555
+ ///
556
+ /// The basic strategy for handling a constraint like `?A <: B` is to
557
+ /// apply a "generalization strategy" to the type `B` -- this replaces
558
+ /// all the lifetimes in the type `B` with fresh inference
559
+ /// variables. (You can read more about the strategy in this [blog
560
+ /// post].)
561
+ ///
562
+ /// As an example, if we had `?A <: &'x u32`, we would generalize `&'x
563
+ /// u32` to `&'0 u32` where `'0` is a fresh variable. This becomes the
564
+ /// value of `A`. Finally, we relate `&'0 u32 <: &'x u32`, which
565
+ /// establishes `'0: 'x` as a constraint.
566
+ ///
567
+ /// As a side-effect of this generalization procedure, we also replace
568
+ /// all the bound regions that we have traversed with concrete values,
569
+ /// so that the resulting generalized type is independent from the
570
+ /// scopes.
571
+ ///
572
+ /// [blog post]: http://smallcultfollowing.com/babysteps/blog/2014/07/09/an-experimental-new-type-inference-scheme-for-rust/
573
+ struct TypeGeneralizer < ' me , ' bccx : ' me , ' gcx : ' tcx , ' tcx : ' bccx > {
600
574
type_rel : & ' me TypeRelating < ' me , ' bccx , ' gcx , ' tcx > ,
575
+
576
+ /// After we generalize this type, we are going to relative it to
577
+ /// some other type. What will be the variance at this point?
578
+ ambient_variance : ty:: Variance ,
579
+
601
580
first_free_index : ty:: DebruijnIndex ,
602
- universal_regions : & ' me UniversalRegions < ' tcx > ,
603
- scopes : & ' me [ BoundRegionScope ] ,
581
+
582
+ universe : ty :: UniverseIndex ,
604
583
}
605
584
606
- impl TypeFolder < ' gcx , ' tcx > for BoundReplacer < ' me , ' bccx , ' gcx , ' tcx > {
607
- fn tcx ( & self ) -> TyCtxt < ' _ , ' gcx , ' tcx > {
608
- self . type_rel . tcx ( )
585
+ impl TypeRelation < ' me , ' gcx , ' tcx > for TypeGeneralizer < ' me , ' bbcx , ' gcx , ' tcx > {
586
+ fn tcx ( & self ) -> TyCtxt < ' me , ' gcx , ' tcx > {
587
+ self . type_rel . infcx . tcx
609
588
}
610
589
611
- fn fold_binder < T : TypeFoldable < ' tcx > > ( & mut self , t : & ty:: Binder < T > ) -> ty:: Binder < T > {
612
- self . first_free_index . shift_in ( 1 ) ;
613
- let result = t. super_fold_with ( self ) ;
614
- self . first_free_index . shift_out ( 1 ) ;
615
- result
590
+ fn tag ( & self ) -> & ' static str {
591
+ "nll::generalizer"
592
+ }
593
+
594
+ fn a_is_expected ( & self ) -> bool {
595
+ true
616
596
}
617
597
618
- fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
619
- let tcx = self . tcx ( ) ;
598
+ fn relate_with_variance < T : Relate < ' tcx > > (
599
+ & mut self ,
600
+ variance : ty:: Variance ,
601
+ a : & T ,
602
+ b : & T ,
603
+ ) -> RelateResult < ' tcx , T > {
604
+ debug ! (
605
+ "TypeGeneralizer::relate_with_variance(variance={:?}, a={:?}, b={:?})" ,
606
+ variance, a, b
607
+ ) ;
608
+
609
+ let old_ambient_variance = self . ambient_variance ;
610
+ self . ambient_variance = self . ambient_variance . xform ( variance) ;
620
611
621
- if let ty:: ReLateBound ( debruijn, _) = r {
612
+ debug ! (
613
+ "TypeGeneralizer::relate_with_variance: ambient_variance = {:?}" ,
614
+ self . ambient_variance
615
+ ) ;
616
+
617
+ let r = self . relate ( a, b) ?;
618
+
619
+ self . ambient_variance = old_ambient_variance;
620
+
621
+ debug ! ( "TypeGeneralizer::relate_with_variance: r={:?}" , r) ;
622
+
623
+ Ok ( r)
624
+ }
625
+
626
+ fn tys ( & mut self , a : Ty < ' tcx > , _: Ty < ' tcx > ) -> RelateResult < ' tcx , Ty < ' tcx > > {
627
+ debug ! ( "TypeGeneralizer::tys(a={:?})" , a, ) ;
628
+
629
+ match a. sty {
630
+ ty:: Infer ( ty:: TyVar ( _) ) | ty:: Infer ( ty:: IntVar ( _) ) | ty:: Infer ( ty:: FloatVar ( _) ) => {
631
+ bug ! (
632
+ "unexpected inference variable encountered in NLL generalization: {:?}" ,
633
+ a
634
+ ) ;
635
+ }
636
+
637
+ _ => relate:: super_relate_tys ( self , a, a) ,
638
+ }
639
+ }
640
+
641
+ fn regions (
642
+ & mut self ,
643
+ a : ty:: Region < ' tcx > ,
644
+ _: ty:: Region < ' tcx > ,
645
+ ) -> RelateResult < ' tcx , ty:: Region < ' tcx > > {
646
+ debug ! ( "TypeGeneralizer::regions(a={:?})" , a, ) ;
647
+
648
+ if let ty:: ReLateBound ( debruijn, _) = a {
622
649
if * debruijn < self . first_free_index {
623
- return r ;
650
+ return Ok ( a ) ;
624
651
}
625
652
}
626
653
627
- let region_vid = self . type_rel . replace_bound_region (
628
- self . universal_regions ,
629
- r,
630
- self . first_free_index ,
631
- self . scopes ,
632
- ) ;
654
+ // For now, we just always create a fresh region variable to
655
+ // replace all the regions in the source type. In the main
656
+ // type checker, we special case the case where the ambient
657
+ // variance is `Invariant` and try to avoid creating a fresh
658
+ // region variable, but since this comes up so much less in
659
+ // NLL (only when users use `_` etc) it is much less
660
+ // important.
661
+ //
662
+ // As an aside, since these new variables are created in
663
+ // `self.universe` universe, this also serves to enforce the
664
+ // universe scoping rules.
665
+ //
666
+ // FIXME -- if the ambient variance is bivariant, though, we
667
+ // may however need to check well-formedness or risk a problem
668
+ // like #41677 again.
669
+
670
+ let replacement_region_vid = self . type_rel
671
+ . infcx
672
+ . next_nll_region_var_in_universe ( NLLRegionVariableOrigin :: Existential , self . universe ) ;
673
+
674
+ Ok ( replacement_region_vid)
675
+ }
633
676
634
- tcx. mk_region ( ty:: ReVar ( region_vid) )
677
+ fn binders < T > (
678
+ & mut self ,
679
+ a : & ty:: Binder < T > ,
680
+ _: & ty:: Binder < T > ,
681
+ ) -> RelateResult < ' tcx , ty:: Binder < T > >
682
+ where
683
+ T : Relate < ' tcx > ,
684
+ {
685
+ debug ! ( "TypeGeneralizer::binders(a={:?})" , a, ) ;
686
+
687
+ self . first_free_index . shift_in ( 1 ) ;
688
+ let result = self . relate ( a. skip_binder ( ) , a. skip_binder ( ) ) ?;
689
+ self . first_free_index . shift_out ( 1 ) ;
690
+ Ok ( ty:: Binder :: bind ( result) )
635
691
}
636
692
}
0 commit comments