7
7
//! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
8
8
9
9
use rustc_macros:: extension;
10
- use rustc_middle:: bug;
11
- use rustc_middle:: ty:: { self , FnMutDelegate , GenericArgKind , TyCtxt , TypeFoldable } ;
10
+ use rustc_middle:: ty:: {
11
+ self , DelayedMap , Ty , TyCtxt , TypeFoldable , TypeFolder , TypeSuperFoldable , TypeSuperVisitable ,
12
+ TypeVisitableExt , TypeVisitor ,
13
+ } ;
14
+ use rustc_type_ir:: TypeVisitable ;
12
15
13
16
use crate :: infer:: canonical:: { Canonical , CanonicalVarValues } ;
14
17
@@ -18,11 +21,15 @@ use crate::infer::canonical::{Canonical, CanonicalVarValues};
18
21
impl < ' tcx , V > Canonical < ' tcx , V > {
19
22
/// Instantiate the wrapped value, replacing each canonical value
20
23
/// with the value given in `var_values`.
21
- fn instantiate ( & self , tcx : TyCtxt < ' tcx > , var_values : & CanonicalVarValues < ' tcx > ) -> V
24
+ fn instantiate < const UWU : bool > (
25
+ & self ,
26
+ tcx : TyCtxt < ' tcx > ,
27
+ var_values : & CanonicalVarValues < ' tcx > ,
28
+ ) -> V
22
29
where
23
30
V : TypeFoldable < TyCtxt < ' tcx > > ,
24
31
{
25
- self . instantiate_projected ( tcx, var_values, |value| value. clone ( ) )
32
+ self . instantiate_projected :: < _ , UWU > ( tcx, var_values, |value| value. clone ( ) )
26
33
}
27
34
28
35
/// Allows one to apply a instantiation to some subset of
@@ -31,7 +38,7 @@ impl<'tcx, V> Canonical<'tcx, V> {
31
38
/// variables bound in `self` (usually this extracts from subset
32
39
/// of `self`). Apply the instantiation `var_values` to this value
33
40
/// V, replacing each of the canonical variables.
34
- fn instantiate_projected < T > (
41
+ fn instantiate_projected < T , const UWU : bool > (
35
42
& self ,
36
43
tcx : TyCtxt < ' tcx > ,
37
44
var_values : & CanonicalVarValues < ' tcx > ,
@@ -42,14 +49,14 @@ impl<'tcx, V> Canonical<'tcx, V> {
42
49
{
43
50
assert_eq ! ( self . variables. len( ) , var_values. len( ) ) ;
44
51
let value = projection_fn ( & self . value ) ;
45
- instantiate_value ( tcx, var_values, value)
52
+ instantiate_value_0 :: < _ , UWU > ( tcx, var_values, value)
46
53
}
47
54
}
48
55
49
56
/// Instantiate the values from `var_values` into `value`. `var_values`
50
57
/// must be values for the set of canonical variables that appear in
51
58
/// `value`.
52
- pub ( super ) fn instantiate_value < ' tcx , T > (
59
+ pub ( super ) fn instantiate_value_0 < ' tcx , T , const UWU : bool > (
53
60
tcx : TyCtxt < ' tcx > ,
54
61
var_values : & CanonicalVarValues < ' tcx > ,
55
62
value : T ,
@@ -58,23 +65,160 @@ where
58
65
T : TypeFoldable < TyCtxt < ' tcx > > ,
59
66
{
60
67
if var_values. var_values . is_empty ( ) {
61
- value
62
- } else {
63
- let delegate = FnMutDelegate {
64
- regions : & mut |br : ty:: BoundRegion | match var_values[ br. var ] . kind ( ) {
65
- GenericArgKind :: Lifetime ( l) => l,
66
- r => bug ! ( "{:?} is a region but value is {:?}" , br, r) ,
67
- } ,
68
- types : & mut |bound_ty : ty:: BoundTy | match var_values[ bound_ty. var ] . kind ( ) {
69
- GenericArgKind :: Type ( ty) => ty,
70
- r => bug ! ( "{:?} is a type but value is {:?}" , bound_ty, r) ,
71
- } ,
72
- consts : & mut |bound_ct : ty:: BoundVar | match var_values[ bound_ct] . kind ( ) {
73
- GenericArgKind :: Const ( ct) => ct,
74
- c => bug ! ( "{:?} is a const but value is {:?}" , bound_ct, c) ,
75
- } ,
76
- } ;
77
-
78
- tcx. replace_escaping_bound_vars_uncached ( value, delegate)
68
+ return value;
69
+ }
70
+
71
+ value. fold_with ( & mut BoundVarReplacer :: < UWU > {
72
+ tcx,
73
+ current_index : ty:: INNERMOST ,
74
+ var_values : var_values. var_values ,
75
+ cache : Default :: default ( ) ,
76
+ } )
77
+ }
78
+
79
+ /// Replaces the escaping bound vars (late bound regions or bound types) in a type.
80
+ struct BoundVarReplacer < ' tcx , const UWU : bool > {
81
+ tcx : TyCtxt < ' tcx > ,
82
+
83
+ /// As with `RegionFolder`, represents the index of a binder *just outside*
84
+ /// the ones we have visited.
85
+ current_index : ty:: DebruijnIndex ,
86
+
87
+ var_values : ty:: GenericArgsRef < ' tcx > ,
88
+
89
+ /// This cache only tracks the `DebruijnIndex` and assumes that it does not matter
90
+ /// for the delegate how often its methods get used.
91
+ cache : DelayedMap < ( ty:: DebruijnIndex , Ty < ' tcx > ) , Ty < ' tcx > > ,
92
+ }
93
+
94
+ impl < ' tcx , const UWU : bool > TypeFolder < TyCtxt < ' tcx > > for BoundVarReplacer < ' tcx , UWU > {
95
+ fn cx ( & self ) -> TyCtxt < ' tcx > {
96
+ self . tcx
97
+ }
98
+
99
+ fn fold_binder < T : TypeFoldable < TyCtxt < ' tcx > > > (
100
+ & mut self ,
101
+ t : ty:: Binder < ' tcx , T > ,
102
+ ) -> ty:: Binder < ' tcx , T > {
103
+ self . current_index . shift_in ( 1 ) ;
104
+ let t = t. super_fold_with ( self ) ;
105
+ self . current_index . shift_out ( 1 ) ;
106
+ t
107
+ }
108
+
109
+ fn fold_ty ( & mut self , t : Ty < ' tcx > ) -> Ty < ' tcx > {
110
+ match * t. kind ( ) {
111
+ ty:: Bound ( debruijn, bound_ty) if debruijn == self . current_index => {
112
+ self . var_values [ bound_ty. var . as_usize ( ) ] . expect_ty ( )
113
+ }
114
+ _ => {
115
+ if !t. has_vars_bound_at_or_above ( self . current_index ) {
116
+ t
117
+ } else if let Some ( & t) = self . cache . get ( & ( self . current_index , t) ) {
118
+ t
119
+ } else {
120
+ let res = t. super_fold_with ( self ) ;
121
+ assert ! ( self . cache. insert( ( self . current_index, t) , res) ) ;
122
+ res
123
+ }
124
+ }
125
+ }
126
+ }
127
+
128
+ fn fold_region ( & mut self , r : ty:: Region < ' tcx > ) -> ty:: Region < ' tcx > {
129
+ match r. kind ( ) {
130
+ ty:: ReBound ( debruijn, br) if debruijn == self . current_index => {
131
+ self . var_values [ br. var . as_usize ( ) ] . expect_region ( )
132
+ }
133
+ _ => r,
134
+ }
135
+ }
136
+
137
+ fn fold_const ( & mut self , ct : ty:: Const < ' tcx > ) -> ty:: Const < ' tcx > {
138
+ match ct. kind ( ) {
139
+ ty:: ConstKind :: Bound ( debruijn, bound_const) if debruijn == self . current_index => {
140
+ self . var_values [ bound_const. as_usize ( ) ] . expect_const ( )
141
+ }
142
+ _ => ct. super_fold_with ( self ) ,
143
+ }
144
+ }
145
+
146
+ fn fold_predicate ( & mut self , p : ty:: Predicate < ' tcx > ) -> ty:: Predicate < ' tcx > {
147
+ if p. has_vars_bound_at_or_above ( self . current_index ) { p. super_fold_with ( self ) } else { p }
148
+ }
149
+
150
+ fn fold_clauses ( & mut self , c : ty:: Clauses < ' tcx > ) -> ty:: Clauses < ' tcx > {
151
+ if c. has_vars_bound_at_or_above ( self . current_index ) {
152
+ if self . current_index == ty:: INNERMOST {
153
+ if UWU {
154
+ let index = * self
155
+ . tcx
156
+ . highest_var_in_clauses_cache
157
+ . lock ( )
158
+ . entry ( c)
159
+ . or_insert_with ( || highest_var_in_clauses ( c) ) ;
160
+ let c_args = & self . var_values [ ..=index] ;
161
+ if let Some ( c2) = self . tcx . clauses_cache . lock ( ) . get ( & ( c, c_args) ) {
162
+ c2
163
+ } else {
164
+ let folded = c. super_fold_with ( self ) ;
165
+ self . tcx . clauses_cache . lock ( ) . insert ( ( c, c_args) , folded) ;
166
+ folded
167
+ }
168
+ } else {
169
+ c. super_fold_with ( self )
170
+ }
171
+ } else {
172
+ c. super_fold_with ( self )
173
+ }
174
+ } else {
175
+ c
176
+ }
177
+ }
178
+ }
179
+
180
+ fn highest_var_in_clauses < ' tcx > ( c : ty:: Clauses < ' tcx > ) -> usize {
181
+ struct HighestVarInClauses {
182
+ max_var : usize ,
183
+ current_index : ty:: DebruijnIndex ,
184
+ }
185
+ impl < ' tcx > TypeVisitor < TyCtxt < ' tcx > > for HighestVarInClauses {
186
+ fn visit_binder < T : TypeFoldable < TyCtxt < ' tcx > > > (
187
+ & mut self ,
188
+ t : & ty:: Binder < ' tcx , T > ,
189
+ ) -> Self :: Result {
190
+ self . current_index . shift_in ( 1 ) ;
191
+ let t = t. super_visit_with ( self ) ;
192
+ self . current_index . shift_out ( 1 ) ;
193
+ t
194
+ }
195
+ fn visit_ty ( & mut self , t : Ty < ' tcx > ) {
196
+ if let ty:: Bound ( debruijn, bound_ty) = * t. kind ( )
197
+ && debruijn == self . current_index
198
+ {
199
+ self . max_var = self . max_var . max ( bound_ty. var . as_usize ( ) ) ;
200
+ } else if t. has_vars_bound_at_or_above ( self . current_index ) {
201
+ t. super_visit_with ( self ) ;
202
+ }
203
+ }
204
+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) {
205
+ if let ty:: ReBound ( debruijn, bound_region) = r. kind ( )
206
+ && debruijn == self . current_index
207
+ {
208
+ self . max_var = self . max_var . max ( bound_region. var . as_usize ( ) ) ;
209
+ }
210
+ }
211
+ fn visit_const ( & mut self , ct : ty:: Const < ' tcx > ) {
212
+ if let ty:: ConstKind :: Bound ( debruijn, bound_const) = ct. kind ( )
213
+ && debruijn == self . current_index
214
+ {
215
+ self . max_var = self . max_var . max ( bound_const. as_usize ( ) ) ;
216
+ } else if ct. has_vars_bound_at_or_above ( self . current_index ) {
217
+ ct. super_visit_with ( self ) ;
218
+ }
219
+ }
79
220
}
221
+ let mut visitor = HighestVarInClauses { max_var : 0 , current_index : ty:: INNERMOST } ;
222
+ c. visit_with ( & mut visitor) ;
223
+ visitor. max_var
80
224
}
0 commit comments