@@ -15,7 +15,7 @@ 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 , TypeVisitor } ;
18
+ use rustc:: ty:: fold:: { TypeFoldable , TypeFolder , 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 } ;
@@ -128,7 +128,7 @@ struct TypeRelating<'cx, 'bccx: 'cx, 'gcx: 'tcx, 'tcx: 'bccx> {
128
128
/// how can we enforce that? I guess I could add some kind of
129
129
/// "minimum universe constraint" that we can feed to the NLL checker.
130
130
/// --> also, we know this doesn't happen
131
- canonical_var_values : IndexVec < CanonicalVar , Option < ScopesAndKind < ' tcx > > > ,
131
+ canonical_var_values : IndexVec < CanonicalVar , Option < Kind < ' tcx > > > ,
132
132
}
133
133
134
134
#[ derive( Clone , Debug ) ]
@@ -264,6 +264,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
264
264
/// equated, then equate it again.
265
265
fn equate_var (
266
266
& mut self ,
267
+ universal_regions : & UniversalRegions < ' tcx > ,
267
268
var : CanonicalVar ,
268
269
b_kind : Kind < ' tcx > ,
269
270
) -> RelateResult < ' tcx , Kind < ' tcx > > {
@@ -274,21 +275,25 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
274
275
275
276
// The canonical variable already had a value. Equate that
276
277
// value with `b`.
277
- let old_value = self . canonical_var_values [ var] . clone ( ) ;
278
- if let Some ( ScopesAndKind { scopes, kind } ) = old_value {
279
- debug ! ( "equate_var: installing kind={:?} scopes={:?}" , kind, scopes) ;
280
- let old_a_scopes = mem:: replace ( & mut self . a_scopes , scopes) ;
281
- let result = self . relate ( & kind, & b_kind) ;
278
+ if let Some ( a_kind) = self . canonical_var_values [ var] {
279
+ debug ! ( "equate_var: a_kind={:?}" , a_kind) ;
280
+
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) ;
282
287
self . a_scopes = old_a_scopes;
288
+
283
289
debug ! ( "equate_var: complete, result = {:?}" , result) ;
284
290
return result;
285
291
}
286
292
287
293
// Not yet. Capture the value from the RHS and carry on.
288
- self . canonical_var_values [ var] = Some ( ScopesAndKind {
289
- scopes : self . b_scopes . clone ( ) ,
290
- kind : b_kind,
291
- } ) ;
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) ;
292
297
debug ! (
293
298
"equate_var: capturing value {:?}" ,
294
299
self . canonical_var_values[ var]
@@ -303,6 +308,31 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelating<'cx, 'bccx, 'gcx, 'tcx> {
303
308
// of over look this right now.
304
309
Ok ( b_kind)
305
310
}
311
+
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 (
320
+ & self ,
321
+ universal_regions : & UniversalRegions < ' tcx > ,
322
+ scopes : & [ BoundRegionScope ] ,
323
+ kind : Kind < ' tcx > ,
324
+ ) -> Kind < ' tcx > {
325
+ let k = kind. fold_with ( & mut BoundReplacer {
326
+ type_rel : self ,
327
+ first_free_index : ty:: INNERMOST ,
328
+ universal_regions,
329
+ scopes : scopes,
330
+ } ) ;
331
+
332
+ assert ! ( !k. has_escaping_regions( ) ) ;
333
+
334
+ k
335
+ }
306
336
}
307
337
308
338
impl < ' cx , ' bccx , ' gcx , ' tcx > TypeRelation < ' cx , ' gcx , ' tcx >
@@ -352,8 +382,21 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
352
382
// Watch out for the case that we are matching a `?T` against the
353
383
// right-hand side.
354
384
if let ty:: Infer ( ty:: CanonicalTy ( var) ) = a. sty {
355
- self . equate_var ( var, b. into ( ) ) ?;
356
- Ok ( a)
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
+ }
357
400
} else {
358
401
debug ! (
359
402
"tys(a={:?}, b={:?}, variance={:?})" ,
@@ -374,7 +417,7 @@ impl<'cx, 'bccx, 'gcx, 'tcx> TypeRelation<'cx, 'gcx, 'tcx>
374
417
} ) = self . borrowck_context
375
418
{
376
419
if let ty:: ReCanonical ( var) = a {
377
- self . equate_var ( * var, b. into ( ) ) ?;
420
+ self . equate_var ( universal_regions , * var, b. into ( ) ) ?;
378
421
return Ok ( a) ;
379
422
}
380
423
@@ -545,3 +588,49 @@ impl<'cx, 'gcx, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'cx, 'gcx, 'tcx> {
545
588
false
546
589
}
547
590
}
591
+
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 > {
600
+ type_rel : & ' me TypeRelating < ' me , ' bccx , ' gcx , ' tcx > ,
601
+ first_free_index : ty:: DebruijnIndex ,
602
+ universal_regions : & ' me UniversalRegions < ' tcx > ,
603
+ scopes : & ' me [ BoundRegionScope ] ,
604
+ }
605
+
606
+ impl TypeFolder < ' gcx , ' tcx > for BoundReplacer < ' me , ' bccx , ' gcx , ' tcx > {
607
+ fn tcx ( & self ) -> TyCtxt < ' _ , ' gcx , ' tcx > {
608
+ self . type_rel . tcx ( )
609
+ }
610
+
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
616
+ }
617
+
618
+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
619
+ let tcx = self . tcx ( ) ;
620
+
621
+ if let ty:: ReLateBound ( debruijn, _) = r {
622
+ if * debruijn < self . first_free_index {
623
+ return r;
624
+ }
625
+ }
626
+
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
+ ) ;
633
+
634
+ tcx. mk_region ( ty:: ReVar ( region_vid) )
635
+ }
636
+ }
0 commit comments