@@ -3,8 +3,11 @@ use std::{fmt, marker::PhantomData};
33use syntax:: ast;
44
55use crate :: ty:: {
6- self , AdtDef , Binder , BoundTy , ExistentialPredicate , InferTy , List , ParamTy , PolyFnSig ,
7- ProjectionTy , Region , SubstsRef , Ty , TypeAndMut ,
6+ self ,
7+ context:: { Lift , TyCtxt } ,
8+ fold:: { TypeFoldable , TypeFolder , TypeVisitor } ,
9+ AdtDef , Binder , BoundTy , ExistentialPredicate , InferTy , List , ParamTy , PolyFnSig , ProjectionTy ,
10+ Region , SubstsRef , Ty , TypeAndMut ,
811} ;
912use rustc_hir:: { self as hir, def_id:: DefId } ;
1013
@@ -13,12 +16,39 @@ pub use self::ViewKind::*;
1316/// `View<'tcx, T>` contains a value of `T` but stores the `Ty<'tcx>` ptr that contains the `T`
1417/// This allows for cheap access to the `Ty<'tcx>` without needing to ask the type interner or
1518/// losing the `T` type.
16- #[ derive( TypeFoldable , Eq , PartialEq , Hash , Lift ) ]
19+ #[ derive( Eq , PartialEq , Hash ) ]
1720pub struct View < ' tcx , T > {
1821 ty : Ty < ' tcx > ,
1922 _marker : PhantomData < T > ,
2023}
2124
25+ impl < ' a , ' tcx , T > Lift < ' tcx > for View < ' a , T >
26+ where
27+ T : TyDeref < ' a > + Lift < ' tcx > ,
28+ T :: Lifted : TyDeref < ' tcx > ,
29+ {
30+ type Lifted = View < ' tcx , T :: Lifted > ;
31+ fn lift_to_tcx ( & self , tcx : TyCtxt < ' tcx > ) -> Option < Self :: Lifted > {
32+ tcx. lift ( & * * self ) . map ( |t| View :: intern ( tcx, t) )
33+ }
34+ }
35+
36+ impl < ' tcx , T > TypeFoldable < ' tcx > for View < ' tcx , T >
37+ where
38+ T : TyDeref < ' tcx > + TypeFoldable < ' tcx > + PartialEq ,
39+ {
40+ fn super_fold_with < F : TypeFolder < ' tcx > > ( & self , folder : & mut F ) -> Self {
41+ let tcx = folder. tcx ( ) ;
42+ let old_t = & * * self ;
43+ let new_t = old_t. super_fold_with ( folder) ;
44+ if * old_t == new_t { * self } else { Self :: intern ( tcx, new_t) }
45+ }
46+
47+ fn super_visit_with < V : TypeVisitor < ' tcx > > ( & self , visitor : & mut V ) -> bool {
48+ ( * * self ) . super_visit_with ( visitor)
49+ }
50+ }
51+
2252impl < T > Copy for View < ' _ , T > { }
2353
2454impl < T > Clone for View < ' _ , T > {
@@ -70,6 +100,12 @@ where
70100 T :: ty_deref ( ty) ?;
71101 Some ( View { ty, _marker : PhantomData } )
72102 }
103+
104+ #[ inline]
105+ pub fn intern ( tcx : TyCtxt < ' tcx > , t : T ) -> Self {
106+ let ty = t. intern ( tcx) ;
107+ View { ty, _marker : PhantomData }
108+ }
73109}
74110
75111impl < ' tcx , T > View < ' tcx , T > {
@@ -82,12 +118,18 @@ impl<'tcx, T> View<'tcx, T> {
82118/// SAFETY If `Some` is returned for `ty` then `Some` must always be returned for any subsequent
83119/// call with the same `Ty` value
84120pub unsafe trait TyDeref < ' tcx > : Sized + ' tcx {
121+ fn intern ( self , tcx : TyCtxt < ' tcx > ) -> Ty < ' tcx > ;
85122 fn ty_deref ( ty : Ty < ' tcx > ) -> Option < & ' tcx Self > ;
86123}
87124
88125macro_rules! impl_ty_deref {
89126 ( $ty: ty, $variant: ident) => {
90127 unsafe impl <' tcx> TyDeref <' tcx> for $ty {
128+ #[ inline]
129+ fn intern( self , tcx: TyCtxt <' tcx>) -> Ty <' tcx> {
130+ tcx. mk_ty( ty:: $variant( self ) )
131+ }
132+
91133 #[ inline]
92134 fn ty_deref( ty: Ty <' tcx>) -> Option <& ' tcx Self > {
93135 match & ty. kind {
0 commit comments