@@ -15,7 +15,6 @@ use middle::ty_fold;
15
15
use middle:: ty_fold:: { TypeFoldable , TypeFolder } ;
16
16
use util:: ppaux:: Repr ;
17
17
18
- use std:: iter:: Chain ;
19
18
use std:: mem;
20
19
use std:: raw;
21
20
use std:: slice:: { Items , MutItems } ;
@@ -191,8 +190,8 @@ impl Substs {
191
190
}
192
191
193
192
pub fn with_method_from ( self , substs : & Substs ) -> Substs {
194
- self . with_method ( ( * substs. types . get_vec ( FnSpace ) ) . clone ( ) ,
195
- ( * substs. regions ( ) . get_vec ( FnSpace ) ) . clone ( ) )
193
+ self . with_method ( Vec :: from_slice ( substs. types . get_slice ( FnSpace ) ) ,
194
+ Vec :: from_slice ( substs. regions ( ) . get_slice ( FnSpace ) ) )
196
195
}
197
196
198
197
pub fn with_method ( self ,
@@ -261,13 +260,44 @@ impl ParamSpace {
261
260
*/
262
261
#[ deriving( PartialEq , Eq , Clone , Hash , Encodable , Decodable ) ]
263
262
pub struct VecPerParamSpace < T > {
264
- vecs : ( Vec < T > , Vec < T > , Vec < T > )
263
+ // This was originally represented as a tuple with one Vec<T> for
264
+ // each variant of ParamSpace, and that remains the abstraction
265
+ // that it provides to its clients.
266
+ //
267
+ // Here is how the representation corresponds to the abstraction
268
+ // i.e. the "abstraction function" AF:
269
+ //
270
+ // AF(self) = (self.content.slice_to(self.type_limit),
271
+ // self.content.slice(self.type_limit, self.self_limit),
272
+ // self.content.slice_from(self.self_limit))
273
+ type_limit : uint ,
274
+ self_limit : uint ,
275
+ content : Vec < T > ,
276
+ }
277
+
278
+ impl < T : Clone > VecPerParamSpace < T > {
279
+ pub fn push_all ( & mut self , space : ParamSpace , values : & [ T ] ) {
280
+ // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
281
+ for t in values. iter ( ) {
282
+ self . push ( space, t. clone ( ) ) ;
283
+ }
284
+ }
265
285
}
266
286
267
287
impl < T > VecPerParamSpace < T > {
288
+ fn limits ( & self , space : ParamSpace ) -> ( uint , uint ) {
289
+ match space {
290
+ TypeSpace => ( 0 , self . type_limit ) ,
291
+ SelfSpace => ( self . type_limit , self . self_limit ) ,
292
+ FnSpace => ( self . self_limit , self . content . len ( ) ) ,
293
+ }
294
+ }
295
+
268
296
pub fn empty ( ) -> VecPerParamSpace < T > {
269
297
VecPerParamSpace {
270
- vecs : ( Vec :: new ( ) , Vec :: new ( ) , Vec :: new ( ) )
298
+ type_limit : 0 ,
299
+ self_limit : 0 ,
300
+ content : Vec :: new ( )
271
301
}
272
302
}
273
303
@@ -276,8 +306,15 @@ impl<T> VecPerParamSpace<T> {
276
306
}
277
307
278
308
pub fn new ( t : Vec < T > , s : Vec < T > , f : Vec < T > ) -> VecPerParamSpace < T > {
309
+ let type_limit = t. len ( ) ;
310
+ let self_limit = t. len ( ) + s. len ( ) ;
311
+ let mut content = t;
312
+ content. push_all_move ( s) ;
313
+ content. push_all_move ( f) ;
279
314
VecPerParamSpace {
280
- vecs : ( t, s, f)
315
+ type_limit : type_limit,
316
+ self_limit : self_limit,
317
+ content : content,
281
318
}
282
319
}
283
320
@@ -289,55 +326,98 @@ impl<T> VecPerParamSpace<T> {
289
326
result
290
327
}
291
328
329
+ /// Appends `value` to the vector associated with `space`.
330
+ ///
331
+ /// Unlike the `push` method in `Vec`, this should not be assumed
332
+ /// to be a cheap operation (even when amortized over many calls).
292
333
pub fn push ( & mut self , space : ParamSpace , value : T ) {
293
- self . get_mut_vec ( space) . push ( value) ;
334
+ let ( _, limit) = self . limits ( space) ;
335
+ match space {
336
+ TypeSpace => { self . type_limit += 1 ; self . self_limit += 1 ; }
337
+ SelfSpace => { self . self_limit += 1 ; }
338
+ FnSpace => { }
339
+ }
340
+ self . content . insert ( limit, value) ;
341
+ }
342
+
343
+ pub fn pop ( & mut self , space : ParamSpace ) -> Option < T > {
344
+ let ( start, limit) = self . limits ( space) ;
345
+ if start == limit {
346
+ None
347
+ } else {
348
+ match space {
349
+ TypeSpace => { self . type_limit -= 1 ; self . self_limit -= 1 ; }
350
+ SelfSpace => { self . self_limit -= 1 ; }
351
+ FnSpace => { }
352
+ }
353
+ self . content . remove ( limit - 1 )
354
+ }
355
+ }
356
+
357
+ pub fn truncate ( & mut self , space : ParamSpace , len : uint ) {
358
+ // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
359
+ while self . len ( space) > len {
360
+ self . pop ( space) ;
361
+ }
362
+ }
363
+
364
+ pub fn replace ( & mut self , space : ParamSpace , elems : Vec < T > ) {
365
+ // FIXME (#15435): slow; O(n^2); could enhance vec to make it O(n).
366
+ self . truncate ( space, 0 ) ;
367
+ for t in elems. move_iter ( ) {
368
+ self . push ( space, t) ;
369
+ }
294
370
}
295
371
296
372
pub fn get_self < ' a > ( & ' a self ) -> Option < & ' a T > {
297
- let v = self . get_vec ( SelfSpace ) ;
373
+ let v = self . get_slice ( SelfSpace ) ;
298
374
assert ! ( v. len( ) <= 1 ) ;
299
- if v. len ( ) == 0 { None } else { Some ( v . get ( 0 ) ) }
375
+ if v. len ( ) == 0 { None } else { Some ( & v [ 0 ] ) }
300
376
}
301
377
302
378
pub fn len ( & self , space : ParamSpace ) -> uint {
303
- self . get_vec ( space) . len ( )
379
+ self . get_slice ( space) . len ( )
380
+ }
381
+
382
+ pub fn is_empty_in ( & self , space : ParamSpace ) -> bool {
383
+ self . len ( space) == 0
304
384
}
305
385
306
- pub fn get_vec < ' a > ( & ' a self , space : ParamSpace ) -> & ' a Vec < T > {
307
- self . vecs . get ( space as uint ) . unwrap ( )
386
+ pub fn get_slice < ' a > ( & ' a self , space : ParamSpace ) -> & ' a [ T ] {
387
+ let ( start, limit) = self . limits ( space) ;
388
+ self . content . slice ( start, limit)
308
389
}
309
390
310
- pub fn get_mut_vec < ' a > ( & ' a mut self , space : ParamSpace ) -> & ' a mut Vec < T > {
311
- self . vecs . get_mut ( space as uint ) . unwrap ( )
391
+ fn get_mut_slice < ' a > ( & ' a mut self , space : ParamSpace ) -> & ' a mut [ T ] {
392
+ let ( start, limit) = self . limits ( space) ;
393
+ self . content . mut_slice ( start, limit)
312
394
}
313
395
314
396
pub fn opt_get < ' a > ( & ' a self ,
315
397
space : ParamSpace ,
316
398
index : uint )
317
399
-> Option < & ' a T > {
318
- let v = self . get_vec ( space) ;
319
- if index < v. len ( ) { Some ( v . get ( index) ) } else { None }
400
+ let v = self . get_slice ( space) ;
401
+ if index < v. len ( ) { Some ( & v [ index] ) } else { None }
320
402
}
321
403
322
404
pub fn get < ' a > ( & ' a self , space : ParamSpace , index : uint ) -> & ' a T {
323
- self . get_vec ( space) . get ( index)
405
+ & self . get_slice ( space) [ index]
324
406
}
325
407
326
408
pub fn get_mut < ' a > ( & ' a mut self ,
327
409
space : ParamSpace ,
328
410
index : uint ) -> & ' a mut T {
329
- self . get_mut_vec ( space) . get_mut ( index)
411
+ & mut self . get_mut_slice ( space) [ index]
330
412
}
331
413
332
- pub fn iter < ' a > ( & ' a self ) -> Chain < Items < ' a , T > ,
333
- Chain < Items < ' a , T > ,
334
- Items < ' a , T > > > {
335
- let ( ref r, ref s, ref f) = self . vecs ;
336
- r. iter ( ) . chain ( s. iter ( ) . chain ( f. iter ( ) ) )
414
+ pub fn iter < ' a > ( & ' a self ) -> Items < ' a , T > {
415
+ self . content . iter ( )
337
416
}
338
417
339
- pub fn all_vecs ( & self , pred: |& Vec < T > | -> bool ) -> bool {
340
- self . vecs . iter ( ) . all ( pred)
418
+ pub fn all_vecs ( & self , pred: |& [ T ] | -> bool) -> bool {
419
+ let spaces = [ TypeSpace , SelfSpace , FnSpace ] ;
420
+ spaces. iter ( ) . all ( |& space| { pred ( self . get_slice ( space) ) } )
341
421
}
342
422
343
423
pub fn all ( & self , pred: |& T | -> bool) -> bool {
@@ -353,9 +433,13 @@ impl<T> VecPerParamSpace<T> {
353
433
}
354
434
355
435
pub fn map < U > ( & self , pred: |& T | -> U ) -> VecPerParamSpace < U > {
356
- VecPerParamSpace :: new ( self . vecs . ref0 ( ) . iter ( ) . map ( |p| pred ( p) ) . collect ( ) ,
357
- self . vecs . ref1 ( ) . iter ( ) . map ( |p| pred ( p) ) . collect ( ) ,
358
- self . vecs . ref2 ( ) . iter ( ) . map ( |p| pred ( p) ) . collect ( ) )
436
+ // FIXME (#15418): this could avoid allocating the intermediate
437
+ // Vec's, but note that the values of type_limit and self_limit
438
+ // also need to be kept in sync during construction.
439
+ VecPerParamSpace :: new (
440
+ self . get_slice ( TypeSpace ) . iter ( ) . map ( |p| pred ( p) ) . collect ( ) ,
441
+ self . get_slice ( SelfSpace ) . iter ( ) . map ( |p| pred ( p) ) . collect ( ) ,
442
+ self . get_slice ( FnSpace ) . iter ( ) . map ( |p| pred ( p) ) . collect ( ) )
359
443
}
360
444
361
445
pub fn map_rev < U > ( & self , pred: |& T | -> U ) -> VecPerParamSpace < U > {
@@ -368,29 +452,46 @@ impl<T> VecPerParamSpace<T> {
368
452
* can be run to a fixed point
369
453
*/
370
454
371
- let mut fns: Vec < U > = self . vecs . ref2 ( ) . iter ( ) . rev ( ) . map ( |p| pred ( p) ) . collect ( ) ;
455
+ let mut fns: Vec < U > = self . get_slice ( FnSpace ) . iter ( ) . rev ( ) . map ( |p| pred ( p) ) . collect ( ) ;
372
456
373
457
// NB: Calling foo.rev().map().rev() causes the calls to map
374
458
// to occur in the wrong order. This was somewhat surprising
375
459
// to me, though it makes total sense.
376
460
fns. reverse ( ) ;
377
461
378
- let mut selfs: Vec < U > = self . vecs . ref1 ( ) . iter ( ) . rev ( ) . map ( |p| pred ( p) ) . collect ( ) ;
462
+ let mut selfs: Vec < U > = self . get_slice ( SelfSpace ) . iter ( ) . rev ( ) . map ( |p| pred ( p) ) . collect ( ) ;
379
463
selfs. reverse ( ) ;
380
- let mut tys: Vec < U > = self . vecs . ref0 ( ) . iter ( ) . rev ( ) . map ( |p| pred ( p) ) . collect ( ) ;
464
+ let mut tys: Vec < U > = self . get_slice ( TypeSpace ) . iter ( ) . rev ( ) . map ( |p| pred ( p) ) . collect ( ) ;
381
465
tys. reverse ( ) ;
382
466
VecPerParamSpace :: new ( tys, selfs, fns)
383
467
}
384
468
385
469
pub fn split ( self ) -> ( Vec < T > , Vec < T > , Vec < T > ) {
386
- self . vecs
470
+ // FIXME (#15418): this does two traversals when in principle
471
+ // one would suffice. i.e. change to use `move_iter`.
472
+ let VecPerParamSpace { type_limit, self_limit, content } = self ;
473
+ let mut i = 0 ;
474
+ let ( prefix, fn_vec) = content. partition ( |_| {
475
+ let on_left = i < self_limit;
476
+ i += 1 ;
477
+ on_left
478
+ } ) ;
479
+
480
+ let mut i = 0 ;
481
+ let ( type_vec, self_vec) = prefix. partition ( |_| {
482
+ let on_left = i < type_limit;
483
+ i += 1 ;
484
+ on_left
485
+ } ) ;
486
+
487
+ ( type_vec, self_vec, fn_vec)
387
488
}
388
489
389
490
pub fn with_vec ( mut self , space : ParamSpace , vec : Vec < T > )
390
491
-> VecPerParamSpace < T >
391
492
{
392
- assert ! ( self . get_vec ( space) . is_empty ( ) ) ;
393
- * self . get_mut_vec ( space) = vec;
493
+ assert ! ( self . is_empty_in ( space) ) ;
494
+ self . replace ( space, vec) ;
394
495
self
395
496
}
396
497
}
0 commit comments