@@ -4,7 +4,7 @@ use std::ops::ControlFlow;
4
4
5
5
use crate :: fold:: { FallibleTypeFolder , TypeFoldable } ;
6
6
use crate :: visit:: { TypeVisitable , TypeVisitor } ;
7
- use crate :: { Interner , UniverseIndex } ;
7
+ use crate :: { Interner , Placeholder , UniverseIndex } ;
8
8
9
9
/// A "canonicalized" type `V` is one where all free inference
10
10
/// variables have been rewritten to "canonical vars". These are
@@ -113,3 +113,257 @@ where
113
113
self . variables . visit_with ( folder)
114
114
}
115
115
}
116
+
117
+ /// Information about a canonical variable that is included with the
118
+ /// canonical value. This is sufficient information for code to create
119
+ /// a copy of the canonical value in some other inference context,
120
+ /// with fresh inference variables replacing the canonical values.
121
+ #[ derive( derivative:: Derivative ) ]
122
+ #[ derivative(
123
+ Clone ( bound = "" ) ,
124
+ Hash ( bound = "" ) ,
125
+ Copy ( bound = "CanonicalVarKind<I>: Copy" ) ,
126
+ Debug ( bound = "" )
127
+ ) ]
128
+ #[ derive( TyDecodable , TyEncodable , HashStable_NoContext ) ]
129
+ pub struct CanonicalVarInfo < I : Interner > {
130
+ pub kind : CanonicalVarKind < I > ,
131
+ }
132
+
133
+ impl < I : Interner > PartialEq for CanonicalVarInfo < I > {
134
+ fn eq ( & self , other : & Self ) -> bool {
135
+ self . kind == other. kind
136
+ }
137
+ }
138
+
139
+ impl < I : Interner > Eq for CanonicalVarInfo < I > { }
140
+
141
+ impl < I : Interner > TypeVisitable < I > for CanonicalVarInfo < I >
142
+ where
143
+ I :: Ty : TypeVisitable < I > ,
144
+ {
145
+ fn visit_with < V : TypeVisitor < I > > ( & self , visitor : & mut V ) -> ControlFlow < V :: BreakTy > {
146
+ self . kind . visit_with ( visitor)
147
+ }
148
+ }
149
+
150
+ impl < I : Interner > TypeFoldable < I > for CanonicalVarInfo < I >
151
+ where
152
+ I :: Ty : TypeFoldable < I > ,
153
+ {
154
+ fn try_fold_with < F : FallibleTypeFolder < I > > ( self , folder : & mut F ) -> Result < Self , F :: Error > {
155
+ Ok ( CanonicalVarInfo { kind : self . kind . try_fold_with ( folder) ? } )
156
+ }
157
+ }
158
+
159
+ impl < I : Interner > CanonicalVarInfo < I > {
160
+ pub fn universe ( & self ) -> UniverseIndex {
161
+ self . kind . universe ( )
162
+ }
163
+
164
+ #[ must_use]
165
+ pub fn with_updated_universe ( self , ui : UniverseIndex ) -> CanonicalVarInfo < I > {
166
+ CanonicalVarInfo { kind : self . kind . with_updated_universe ( ui) }
167
+ }
168
+
169
+ pub fn is_existential ( & self ) -> bool {
170
+ match self . kind {
171
+ CanonicalVarKind :: Ty ( _) => true ,
172
+ CanonicalVarKind :: PlaceholderTy ( _) => false ,
173
+ CanonicalVarKind :: Region ( _) => true ,
174
+ CanonicalVarKind :: PlaceholderRegion ( ..) => false ,
175
+ CanonicalVarKind :: Const ( ..) => true ,
176
+ CanonicalVarKind :: PlaceholderConst ( _, _) => false ,
177
+ CanonicalVarKind :: Effect => true ,
178
+ }
179
+ }
180
+
181
+ pub fn is_region ( & self ) -> bool {
182
+ match self . kind {
183
+ CanonicalVarKind :: Region ( _) | CanonicalVarKind :: PlaceholderRegion ( _) => true ,
184
+ CanonicalVarKind :: Ty ( _)
185
+ | CanonicalVarKind :: PlaceholderTy ( _)
186
+ | CanonicalVarKind :: Const ( _, _)
187
+ | CanonicalVarKind :: PlaceholderConst ( _, _)
188
+ | CanonicalVarKind :: Effect => false ,
189
+ }
190
+ }
191
+
192
+ pub fn expect_placeholder_index ( self ) -> usize {
193
+ match self . kind {
194
+ CanonicalVarKind :: Ty ( _)
195
+ | CanonicalVarKind :: Region ( _)
196
+ | CanonicalVarKind :: Const ( _, _)
197
+ | CanonicalVarKind :: Effect => panic ! ( "expected placeholder: {self:?}" ) ,
198
+
199
+ CanonicalVarKind :: PlaceholderRegion ( placeholder) => placeholder. var ( ) . as_usize ( ) ,
200
+ CanonicalVarKind :: PlaceholderTy ( placeholder) => placeholder. var ( ) . as_usize ( ) ,
201
+ CanonicalVarKind :: PlaceholderConst ( placeholder, _) => placeholder. var ( ) . as_usize ( ) ,
202
+ }
203
+ }
204
+ }
205
+
206
+ /// Describes the "kind" of the canonical variable. This is a "kind"
207
+ /// in the type-theory sense of the term -- i.e., a "meta" type system
208
+ /// that analyzes type-like values.
209
+ #[ derive( derivative:: Derivative ) ]
210
+ #[ derivative( Clone ( bound = "" ) , Hash ( bound = "" ) , Debug ( bound = "" ) ) ]
211
+ #[ derive( TyDecodable , TyEncodable , HashStable_NoContext ) ]
212
+ pub enum CanonicalVarKind < I : Interner > {
213
+ /// Some kind of type inference variable.
214
+ Ty ( CanonicalTyVarKind ) ,
215
+
216
+ /// A "placeholder" that represents "any type".
217
+ PlaceholderTy ( I :: PlaceholderTy ) ,
218
+
219
+ /// Region variable `'?R`.
220
+ Region ( UniverseIndex ) ,
221
+
222
+ /// A "placeholder" that represents "any region". Created when you
223
+ /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
224
+ /// bound region `'a`.
225
+ PlaceholderRegion ( I :: PlaceholderRegion ) ,
226
+
227
+ /// Some kind of const inference variable.
228
+ Const ( UniverseIndex , I :: Ty ) ,
229
+
230
+ /// Effect variable `'?E`.
231
+ Effect ,
232
+
233
+ /// A "placeholder" that represents "any const".
234
+ PlaceholderConst ( I :: PlaceholderConst , I :: Ty ) ,
235
+ }
236
+
237
+ impl < I : Interner > Copy for CanonicalVarKind < I >
238
+ where
239
+ I :: PlaceholderTy : Copy ,
240
+ I :: PlaceholderRegion : Copy ,
241
+ I :: PlaceholderConst : Copy ,
242
+ I :: Ty : Copy ,
243
+ {
244
+ }
245
+
246
+ impl < I : Interner > PartialEq for CanonicalVarKind < I > {
247
+ fn eq ( & self , other : & Self ) -> bool {
248
+ match ( self , other) {
249
+ ( Self :: Ty ( l0) , Self :: Ty ( r0) ) => l0 == r0,
250
+ ( Self :: PlaceholderTy ( l0) , Self :: PlaceholderTy ( r0) ) => l0 == r0,
251
+ ( Self :: Region ( l0) , Self :: Region ( r0) ) => l0 == r0,
252
+ ( Self :: PlaceholderRegion ( l0) , Self :: PlaceholderRegion ( r0) ) => l0 == r0,
253
+ ( Self :: Const ( l0, l1) , Self :: Const ( r0, r1) ) => l0 == r0 && l1 == r1,
254
+ ( Self :: PlaceholderConst ( l0, l1) , Self :: PlaceholderConst ( r0, r1) ) => {
255
+ l0 == r0 && l1 == r1
256
+ }
257
+ _ => std:: mem:: discriminant ( self ) == std:: mem:: discriminant ( other) ,
258
+ }
259
+ }
260
+ }
261
+
262
+ impl < I : Interner > Eq for CanonicalVarKind < I > { }
263
+
264
+ impl < I : Interner > TypeVisitable < I > for CanonicalVarKind < I >
265
+ where
266
+ I :: Ty : TypeVisitable < I > ,
267
+ {
268
+ fn visit_with < V : TypeVisitor < I > > ( & self , visitor : & mut V ) -> ControlFlow < V :: BreakTy > {
269
+ match self {
270
+ CanonicalVarKind :: Ty ( _)
271
+ | CanonicalVarKind :: PlaceholderTy ( _)
272
+ | CanonicalVarKind :: Region ( _)
273
+ | CanonicalVarKind :: PlaceholderRegion ( _)
274
+ | CanonicalVarKind :: Effect => ControlFlow :: Continue ( ( ) ) ,
275
+ CanonicalVarKind :: Const ( _, ty) | CanonicalVarKind :: PlaceholderConst ( _, ty) => {
276
+ ty. visit_with ( visitor)
277
+ }
278
+ }
279
+ }
280
+ }
281
+
282
+ impl < I : Interner > TypeFoldable < I > for CanonicalVarKind < I >
283
+ where
284
+ I :: Ty : TypeFoldable < I > ,
285
+ {
286
+ fn try_fold_with < F : FallibleTypeFolder < I > > ( self , folder : & mut F ) -> Result < Self , F :: Error > {
287
+ Ok ( match self {
288
+ CanonicalVarKind :: Ty ( kind) => CanonicalVarKind :: Ty ( kind) ,
289
+ CanonicalVarKind :: Region ( kind) => CanonicalVarKind :: Region ( kind) ,
290
+ CanonicalVarKind :: Const ( kind, ty) => {
291
+ CanonicalVarKind :: Const ( kind, ty. try_fold_with ( folder) ?)
292
+ }
293
+ CanonicalVarKind :: PlaceholderTy ( placeholder) => {
294
+ CanonicalVarKind :: PlaceholderTy ( placeholder)
295
+ }
296
+ CanonicalVarKind :: PlaceholderRegion ( placeholder) => {
297
+ CanonicalVarKind :: PlaceholderRegion ( placeholder)
298
+ }
299
+ CanonicalVarKind :: PlaceholderConst ( placeholder, ty) => {
300
+ CanonicalVarKind :: PlaceholderConst ( placeholder, ty. try_fold_with ( folder) ?)
301
+ }
302
+ CanonicalVarKind :: Effect => CanonicalVarKind :: Effect ,
303
+ } )
304
+ }
305
+ }
306
+
307
+ impl < I : Interner > CanonicalVarKind < I > {
308
+ pub fn universe ( & self ) -> UniverseIndex {
309
+ match self {
310
+ CanonicalVarKind :: Ty ( CanonicalTyVarKind :: General ( ui) ) => * ui,
311
+ CanonicalVarKind :: Region ( ui) => * ui,
312
+ CanonicalVarKind :: Const ( ui, _) => * ui,
313
+ CanonicalVarKind :: PlaceholderTy ( placeholder) => placeholder. universe ( ) ,
314
+ CanonicalVarKind :: PlaceholderRegion ( placeholder) => placeholder. universe ( ) ,
315
+ CanonicalVarKind :: PlaceholderConst ( placeholder, _) => placeholder. universe ( ) ,
316
+ CanonicalVarKind :: Ty ( CanonicalTyVarKind :: Float | CanonicalTyVarKind :: Int ) => {
317
+ UniverseIndex :: ROOT
318
+ }
319
+ CanonicalVarKind :: Effect => UniverseIndex :: ROOT ,
320
+ }
321
+ }
322
+
323
+ /// Replaces the universe of this canonical variable with `ui`.
324
+ ///
325
+ /// In case this is a float or int variable, this causes an ICE if
326
+ /// the updated universe is not the root.
327
+ pub fn with_updated_universe ( self , ui : UniverseIndex ) -> CanonicalVarKind < I > {
328
+ match self {
329
+ CanonicalVarKind :: Ty ( CanonicalTyVarKind :: General ( _) ) => {
330
+ CanonicalVarKind :: Ty ( CanonicalTyVarKind :: General ( ui) )
331
+ }
332
+ CanonicalVarKind :: Region ( _) => CanonicalVarKind :: Region ( ui) ,
333
+ CanonicalVarKind :: Const ( _, ty) => CanonicalVarKind :: Const ( ui, ty) ,
334
+
335
+ CanonicalVarKind :: PlaceholderTy ( placeholder) => {
336
+ CanonicalVarKind :: PlaceholderTy ( placeholder. with_updated_universe ( ui) )
337
+ }
338
+ CanonicalVarKind :: PlaceholderRegion ( placeholder) => {
339
+ CanonicalVarKind :: PlaceholderRegion ( placeholder. with_updated_universe ( ui) )
340
+ }
341
+ CanonicalVarKind :: PlaceholderConst ( placeholder, ty) => {
342
+ CanonicalVarKind :: PlaceholderConst ( placeholder. with_updated_universe ( ui) , ty)
343
+ }
344
+ CanonicalVarKind :: Ty ( CanonicalTyVarKind :: Int | CanonicalTyVarKind :: Float )
345
+ | CanonicalVarKind :: Effect => {
346
+ assert_eq ! ( ui, UniverseIndex :: ROOT ) ;
347
+ self
348
+ }
349
+ }
350
+ }
351
+ }
352
+
353
+ /// Rust actually has more than one category of type variables;
354
+ /// notably, the type variables we create for literals (e.g., 22 or
355
+ /// 22.) can only be instantiated with integral/float types (e.g.,
356
+ /// usize or f32). In order to faithfully reproduce a type, we need to
357
+ /// know what set of types a given type variable can be unified with.
358
+ #[ derive( Copy , Clone , Debug , PartialEq , Eq , Hash ) ]
359
+ #[ derive( Decodable , Encodable , HashStable_NoContext ) ]
360
+ pub enum CanonicalTyVarKind {
361
+ /// General type variable `?T` that can be unified with arbitrary types.
362
+ General ( UniverseIndex ) ,
363
+
364
+ /// Integral type variable `?I` (that can only be unified with integral types).
365
+ Int ,
366
+
367
+ /// Floating-point type variable `?F` (that can only be unified with float types).
368
+ Float ,
369
+ }
0 commit comments