@@ -4,6 +4,7 @@ use crate::ids::Vector;
4
4
use derive_generic_visitor:: * ;
5
5
use std:: collections:: HashSet ;
6
6
use std:: convert:: Infallible ;
7
+ use std:: fmt:: Debug ;
7
8
use std:: iter:: Iterator ;
8
9
use std:: mem;
9
10
use std:: ops:: Index ;
@@ -130,6 +131,27 @@ impl<T> RegionBinder<T> {
130
131
skip_binder : x. move_under_binder ( ) ,
131
132
}
132
133
}
134
+
135
+ pub fn map_ref < U > ( & self , f : impl FnOnce ( & T ) -> U ) -> RegionBinder < U > {
136
+ RegionBinder {
137
+ regions : self . regions . clone ( ) ,
138
+ skip_binder : f ( & self . skip_binder ) ,
139
+ }
140
+ }
141
+
142
+ /// Substitute the bound variables with erased lifetimes.
143
+ pub fn erase ( self ) -> T
144
+ where
145
+ T : AstVisitable ,
146
+ {
147
+ let mut val = self . skip_binder ;
148
+ let args = GenericArgs {
149
+ regions : self . regions . map_ref_indexed ( |_, _| Region :: Erased ) ,
150
+ ..GenericArgs :: empty ( GenericsSource :: Builtin )
151
+ } ;
152
+ val. drive_mut ( & mut SubstVisitor :: new ( & args) ) ;
153
+ val
154
+ }
133
155
}
134
156
135
157
impl GenericArgs {
@@ -270,6 +292,90 @@ impl IntegerTy {
270
292
}
271
293
}
272
294
295
+ /// A value of type `T` bound by the generic parameters of item
296
+ /// `item`. Used when dealing with multiple items at a time, to
297
+ /// ensure we don't mix up generics.
298
+ ///
299
+ /// To get the value, use `under_binder_of` or `subst_for`.
300
+ #[ derive( Debug , Clone , Copy ) ]
301
+ pub struct ItemBinder < ItemId , T > {
302
+ pub item_id : ItemId ,
303
+ val : T ,
304
+ }
305
+
306
+ impl < ItemId , T > ItemBinder < ItemId , T >
307
+ where
308
+ ItemId : Debug + Copy + PartialEq ,
309
+ {
310
+ pub fn new ( item_id : ItemId , val : T ) -> Self {
311
+ Self { item_id, val }
312
+ }
313
+
314
+ pub fn as_ref ( & self ) -> ItemBinder < ItemId , & T > {
315
+ ItemBinder {
316
+ item_id : self . item_id ,
317
+ val : & self . val ,
318
+ }
319
+ }
320
+
321
+ pub fn map_bound < U > ( self , f : impl FnOnce ( T ) -> U ) -> ItemBinder < ItemId , U > {
322
+ ItemBinder {
323
+ item_id : self . item_id ,
324
+ val : f ( self . val ) ,
325
+ }
326
+ }
327
+
328
+ fn assert_item_id ( & self , item_id : ItemId ) {
329
+ assert_eq ! (
330
+ self . item_id, item_id,
331
+ "Trying to use item bound for {:?} as if it belonged to {:?}" ,
332
+ self . item_id, item_id
333
+ ) ;
334
+ }
335
+
336
+ /// Assert that the value is bound for item `item_id`, and returns it. This is used when we
337
+ /// plan to store the returned value inside that item.
338
+ pub fn under_binder_of ( self , item_id : ItemId ) -> T {
339
+ self . assert_item_id ( item_id) ;
340
+ self . val
341
+ }
342
+
343
+ /// Given generic args for `item_id`, assert that the value is bound for `item_id` and
344
+ /// substitute it with the provided generic arguments. Because the arguments are bound in the
345
+ /// context of another item, so it the resulting substituted value.
346
+ pub fn substitute < OtherItem : Debug + Copy + PartialEq > (
347
+ self ,
348
+ args : ItemBinder < OtherItem , & GenericArgs > ,
349
+ ) -> ItemBinder < OtherItem , T >
350
+ where
351
+ ItemId : Into < AnyTransId > ,
352
+ T : TyVisitable ,
353
+ {
354
+ args. map_bound ( |args| {
355
+ assert_eq ! (
356
+ args. target,
357
+ GenericsSource :: item( self . item_id) ,
358
+ "These `GenericArgs` are meant for {:?} but were used on {:?}" ,
359
+ args. target,
360
+ self . item_id
361
+ ) ;
362
+ let mut val = self . val ;
363
+ val. substitute ( args) ;
364
+ val
365
+ } )
366
+ }
367
+ }
368
+
369
+ /// Dummy item identifier that represents the current item when not ambiguous.
370
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
371
+ pub struct CurrentItem ;
372
+
373
+ impl < T > ItemBinder < CurrentItem , T > {
374
+ pub fn under_current_binder ( self ) -> T {
375
+ self . val
376
+ }
377
+ }
378
+
273
379
impl Ty {
274
380
/// Return true if it is actually unit (i.e.: 0-tuple)
275
381
pub fn is_unit ( & self ) -> bool {
0 commit comments