@@ -3,8 +3,11 @@ use std::{fmt, marker::PhantomData};
3
3
use syntax:: ast;
4
4
5
5
use 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 ,
8
11
} ;
9
12
use rustc_hir:: { self as hir, def_id:: DefId } ;
10
13
@@ -13,12 +16,39 @@ pub use self::ViewKind::*;
13
16
/// `View<'tcx, T>` contains a value of `T` but stores the `Ty<'tcx>` ptr that contains the `T`
14
17
/// This allows for cheap access to the `Ty<'tcx>` without needing to ask the type interner or
15
18
/// losing the `T` type.
16
- #[ derive( TypeFoldable , Eq , PartialEq , Hash , Lift ) ]
19
+ #[ derive( Eq , PartialEq , Hash ) ]
17
20
pub struct View < ' tcx , T > {
18
21
ty : Ty < ' tcx > ,
19
22
_marker : PhantomData < T > ,
20
23
}
21
24
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
+
22
52
impl < T > Copy for View < ' _ , T > { }
23
53
24
54
impl < T > Clone for View < ' _ , T > {
@@ -70,6 +100,12 @@ where
70
100
T :: ty_deref ( ty) ?;
71
101
Some ( View { ty, _marker : PhantomData } )
72
102
}
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
+ }
73
109
}
74
110
75
111
impl < ' tcx , T > View < ' tcx , T > {
@@ -82,12 +118,18 @@ impl<'tcx, T> View<'tcx, T> {
82
118
/// SAFETY If `Some` is returned for `ty` then `Some` must always be returned for any subsequent
83
119
/// call with the same `Ty` value
84
120
pub unsafe trait TyDeref < ' tcx > : Sized + ' tcx {
121
+ fn intern ( self , tcx : TyCtxt < ' tcx > ) -> Ty < ' tcx > ;
85
122
fn ty_deref ( ty : Ty < ' tcx > ) -> Option < & ' tcx Self > ;
86
123
}
87
124
88
125
macro_rules! impl_ty_deref {
89
126
( $ty: ty, $variant: ident) => {
90
127
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
+
91
133
#[ inline]
92
134
fn ty_deref( ty: Ty <' tcx>) -> Option <& ' tcx Self > {
93
135
match & ty. kind {
0 commit comments