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