@@ -29,6 +29,7 @@ use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
29
29
use crate :: ty:: subst:: Kind ;
30
30
use crate :: ty:: { self , Ty , TyCtxt } ;
31
31
use rustc_data_structures:: fx:: FxHashMap ;
32
+ use std:: fmt:: Debug ;
32
33
33
34
#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
34
35
pub enum NormalizationStrategy {
@@ -294,14 +295,34 @@ where
294
295
}
295
296
}
296
297
297
- /// Relate a type inference variable with a value type.
298
- fn relate_ty_var (
298
+ /// Relate a type inference variable with a value type. This works
299
+ /// by creating a "generalization" G of the value where all the
300
+ /// lifetimes are replaced with fresh inference values. This
301
+ /// genearlization G becomes the value of the inference variable,
302
+ /// and is then related in turn to the value. So e.g. if you had
303
+ /// `vid = ?0` and `value = &'a u32`, we might first instantiate
304
+ /// `?0` to a type like `&'0 u32` where `'0` is a fresh variable,
305
+ /// and then relate `&'0 u32` with `&'a u32` (resulting in
306
+ /// relations between `'0` and `'a`).
307
+ ///
308
+ /// The variable `pair` can be either a `(vid, ty)` or `(ty, vid)`
309
+ /// -- in other words, it is always a (unresolved) inference
310
+ /// variable `vid` and a type `ty` that are being related, but the
311
+ /// vid may appear either as the "a" type or the "b" type,
312
+ /// depending on where it appears in the tuple. The trait
313
+ /// `VidValuePair` lets us work with the vid/type while preserving
314
+ /// the "sidedness" when necessary -- the sidedness is relevant in
315
+ /// particular for the variance and set of in-scope things.
316
+ fn relate_ty_var < PAIR : VidValuePair < ' tcx > > (
299
317
& mut self ,
300
- vid : ty:: TyVid ,
301
- value_ty : Ty < ' tcx > ,
318
+ pair : PAIR ,
302
319
) -> RelateResult < ' tcx , Ty < ' tcx > > {
303
- debug ! ( "relate_ty_var(vid={:?}, value_ty={:?})" , vid, value_ty) ;
320
+ debug ! ( "relate_ty_var({:?})" , pair) ;
321
+
322
+ let vid = pair. vid ( ) ;
323
+ let value_ty = pair. value_ty ( ) ;
304
324
325
+ // FIXME -- this logic assumes invariance, but that is wrong
305
326
match value_ty. sty {
306
327
ty:: Infer ( ty:: TyVar ( value_vid) ) => {
307
328
// Two type variables: just equate them.
@@ -338,13 +359,13 @@ where
338
359
// been fully instantiated and hence the set of scopes we have
339
360
// doesn't matter -- just to be sure, put an empty vector
340
361
// in there.
341
- let old_a_scopes = :: std:: mem:: replace ( & mut self . a_scopes , vec ! [ ] ) ;
362
+ let old_a_scopes = :: std:: mem:: replace ( pair . vid_scopes ( self ) , vec ! [ ] ) ;
342
363
343
364
// Relate the generalized kind to the original one.
344
- let result = self . relate ( & generalized_ty , & value_ty ) ;
365
+ let result = pair . relate_generalized_ty ( self , generalized_ty ) ;
345
366
346
367
// Restore the old scopes now.
347
- self . a_scopes = old_a_scopes;
368
+ * pair . vid_scopes ( self ) = old_a_scopes;
348
369
349
370
debug ! ( "relate_ty_var: complete, result = {:?}" , result) ;
350
371
result
@@ -370,6 +391,104 @@ where
370
391
}
371
392
}
372
393
394
+ /// When we instantiate a inference variable with a value in
395
+ /// `relate_ty_var`, we always have the pair of a `TyVid` and a `Ty`,
396
+ /// but the ordering may vary (depending on whether the inference
397
+ /// variable was found on the `a` or `b` sides). Therefore, this trait
398
+ /// allows us to factor out common code, while preserving the order
399
+ /// when needed.
400
+ trait VidValuePair < ' tcx > : Debug {
401
+ /// Extract the inference variable (which could be either the
402
+ /// first or second part of the tuple).
403
+ fn vid ( & self ) -> ty:: TyVid ;
404
+
405
+ /// Extract the value it is being related to (which will be the
406
+ /// opposite part of the tuple from the vid).
407
+ fn value_ty ( & self ) -> Ty < ' tcx > ;
408
+
409
+ /// Extract the scopes that apply to whichever side of the tuple
410
+ /// the vid was found on. See the comment where this is called
411
+ /// for more details on why we want them.
412
+ fn vid_scopes < D : TypeRelatingDelegate < ' tcx > > (
413
+ & self ,
414
+ relate : & ' r mut TypeRelating < ' _ , ' _ , ' tcx , D > ,
415
+ ) -> & ' r mut Vec < BoundRegionScope < ' tcx > > ;
416
+
417
+ /// Given a generalized type G that should replace the vid, relate
418
+ /// G to the value, putting G on whichever side the vid would have
419
+ /// appeared.
420
+ fn relate_generalized_ty < D > (
421
+ & self ,
422
+ relate : & mut TypeRelating < ' _ , ' _ , ' tcx , D > ,
423
+ generalized_ty : Ty < ' tcx > ,
424
+ ) -> RelateResult < ' tcx , Ty < ' tcx > >
425
+ where
426
+ D : TypeRelatingDelegate < ' tcx > ;
427
+ }
428
+
429
+ impl VidValuePair < ' tcx > for ( ty:: TyVid , Ty < ' tcx > ) {
430
+ fn vid ( & self ) -> ty:: TyVid {
431
+ self . 0
432
+ }
433
+
434
+ fn value_ty ( & self ) -> Ty < ' tcx > {
435
+ self . 1
436
+ }
437
+
438
+ fn vid_scopes < D > (
439
+ & self ,
440
+ relate : & ' r mut TypeRelating < ' _ , ' _ , ' tcx , D > ,
441
+ ) -> & ' r mut Vec < BoundRegionScope < ' tcx > >
442
+ where
443
+ D : TypeRelatingDelegate < ' tcx > ,
444
+ {
445
+ & mut relate. a_scopes
446
+ }
447
+
448
+ fn relate_generalized_ty < D > (
449
+ & self ,
450
+ relate : & mut TypeRelating < ' _ , ' _ , ' tcx , D > ,
451
+ generalized_ty : Ty < ' tcx > ,
452
+ ) -> RelateResult < ' tcx , Ty < ' tcx > >
453
+ where
454
+ D : TypeRelatingDelegate < ' tcx > ,
455
+ {
456
+ relate. relate ( & generalized_ty, & self . value_ty ( ) )
457
+ }
458
+ }
459
+
460
+ // In this case, the "vid" is the "b" type.
461
+ impl VidValuePair < ' tcx > for ( Ty < ' tcx > , ty:: TyVid ) {
462
+ fn vid ( & self ) -> ty:: TyVid {
463
+ self . 1
464
+ }
465
+
466
+ fn value_ty ( & self ) -> Ty < ' tcx > {
467
+ self . 0
468
+ }
469
+
470
+ fn vid_scopes < D > (
471
+ & self ,
472
+ relate : & ' r mut TypeRelating < ' _ , ' _ , ' tcx , D > ,
473
+ ) -> & ' r mut Vec < BoundRegionScope < ' tcx > >
474
+ where
475
+ D : TypeRelatingDelegate < ' tcx > ,
476
+ {
477
+ & mut relate. b_scopes
478
+ }
479
+
480
+ fn relate_generalized_ty < D > (
481
+ & self ,
482
+ relate : & mut TypeRelating < ' _ , ' _ , ' tcx , D > ,
483
+ generalized_ty : Ty < ' tcx > ,
484
+ ) -> RelateResult < ' tcx , Ty < ' tcx > >
485
+ where
486
+ D : TypeRelatingDelegate < ' tcx > ,
487
+ {
488
+ relate. relate ( & self . value_ty ( ) , & generalized_ty)
489
+ }
490
+ }
491
+
373
492
impl < D > TypeRelation < ' me , ' gcx , ' tcx > for TypeRelating < ' me , ' gcx , ' tcx , D >
374
493
where
375
494
D : TypeRelatingDelegate < ' tcx > ,
@@ -427,17 +546,11 @@ where
427
546
// Forbid inference variables in the RHS.
428
547
bug ! ( "unexpected inference var {:?}" , b)
429
548
} else {
430
- // We swap the order of `a` and `b` in the call to
431
- // `relate_ty_var` below, so swap the corresponding scopes
432
- // as well.
433
- std:: mem:: swap ( & mut self . a_scopes , & mut self . b_scopes ) ;
434
- let res = self . relate_ty_var ( vid, a) ;
435
- std:: mem:: swap ( & mut self . a_scopes , & mut self . b_scopes ) ;
436
- res
549
+ self . relate_ty_var ( ( a, vid) )
437
550
}
438
551
}
439
552
440
- ( & ty:: Infer ( ty:: TyVar ( vid) ) , _) => self . relate_ty_var ( vid, b) ,
553
+ ( & ty:: Infer ( ty:: TyVar ( vid) ) , _) => self . relate_ty_var ( ( vid, b) ) ,
441
554
442
555
( & ty:: Projection ( projection_ty) , _)
443
556
if D :: normalization ( ) == NormalizationStrategy :: Lazy =>
@@ -448,12 +561,7 @@ where
448
561
( _, & ty:: Projection ( projection_ty) )
449
562
if D :: normalization ( ) == NormalizationStrategy :: Lazy =>
450
563
{
451
- // Swap the respective scopes of `a` and `b` (see comment
452
- // above).
453
- std:: mem:: swap ( & mut self . a_scopes , & mut self . b_scopes ) ;
454
- let res = self . relate_projection_ty ( projection_ty, a) ;
455
- std:: mem:: swap ( & mut self . a_scopes , & mut self . b_scopes ) ;
456
- Ok ( res)
564
+ Ok ( self . relate_projection_ty ( projection_ty, a) )
457
565
}
458
566
459
567
_ => {
0 commit comments