@@ -29,6 +29,7 @@ use crate::ty::relate::{self, Relate, RelateResult, TypeRelation};
2929use crate :: ty:: subst:: Kind ;
3030use crate :: ty:: { self , Ty , TyCtxt } ;
3131use rustc_data_structures:: fx:: FxHashMap ;
32+ use std:: fmt:: Debug ;
3233
3334#[ derive( Copy , Clone , PartialEq , Eq , Hash , Debug ) ]
3435pub enum NormalizationStrategy {
@@ -294,14 +295,34 @@ where
294295 }
295296 }
296297
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 > > (
299317 & mut self ,
300- vid : ty:: TyVid ,
301- value_ty : Ty < ' tcx > ,
318+ pair : PAIR ,
302319 ) -> 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 ( ) ;
304324
325+ // FIXME -- this logic assumes invariance, but that is wrong
305326 match value_ty. sty {
306327 ty:: Infer ( ty:: TyVar ( value_vid) ) => {
307328 // Two type variables: just equate them.
@@ -338,13 +359,13 @@ where
338359 // been fully instantiated and hence the set of scopes we have
339360 // doesn't matter -- just to be sure, put an empty vector
340361 // 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 ! [ ] ) ;
342363
343364 // 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 ) ;
345366
346367 // Restore the old scopes now.
347- self . a_scopes = old_a_scopes;
368+ * pair . vid_scopes ( self ) = old_a_scopes;
348369
349370 debug ! ( "relate_ty_var: complete, result = {:?}" , result) ;
350371 result
@@ -370,6 +391,104 @@ where
370391 }
371392}
372393
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+
373492impl < D > TypeRelation < ' me , ' gcx , ' tcx > for TypeRelating < ' me , ' gcx , ' tcx , D >
374493where
375494 D : TypeRelatingDelegate < ' tcx > ,
@@ -427,17 +546,11 @@ where
427546 // Forbid inference variables in the RHS.
428547 bug ! ( "unexpected inference var {:?}" , b)
429548 } 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) )
437550 }
438551 }
439552
440- ( & ty:: Infer ( ty:: TyVar ( vid) ) , _) => self . relate_ty_var ( vid, b) ,
553+ ( & ty:: Infer ( ty:: TyVar ( vid) ) , _) => self . relate_ty_var ( ( vid, b) ) ,
441554
442555 ( & ty:: Projection ( projection_ty) , _)
443556 if D :: normalization ( ) == NormalizationStrategy :: Lazy =>
@@ -448,12 +561,7 @@ where
448561 ( _, & ty:: Projection ( projection_ty) )
449562 if D :: normalization ( ) == NormalizationStrategy :: Lazy =>
450563 {
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) )
457565 }
458566
459567 _ => {
0 commit comments