@@ -90,27 +90,29 @@ impl Chunk {
90
90
/// than objects without destructors. This reduces overhead when initializing
91
91
/// plain-old-data (`Copy` types) and means we don't need to waste time running
92
92
/// their destructors.
93
- pub struct Arena {
93
+ pub struct Arena < ' longer_than_self > {
94
94
// The head is separated out from the list as a unbenchmarked
95
95
// microoptimization, to avoid needing to case on the list to access the
96
96
// head.
97
97
head : RefCell < Chunk > ,
98
98
copy_head : RefCell < Chunk > ,
99
99
chunks : RefCell < Vec < Chunk > > ,
100
+ _invariant : marker:: InvariantLifetime < ' longer_than_self > ,
100
101
}
101
102
102
- impl Arena {
103
+ impl < ' a > Arena < ' a > {
103
104
/// Allocates a new Arena with 32 bytes preallocated.
104
- pub fn new ( ) -> Arena {
105
+ pub fn new ( ) -> Arena < ' a > {
105
106
Arena :: new_with_size ( 32 )
106
107
}
107
108
108
109
/// Allocates a new Arena with `initial_size` bytes preallocated.
109
- pub fn new_with_size ( initial_size : uint ) -> Arena {
110
+ pub fn new_with_size ( initial_size : uint ) -> Arena < ' a > {
110
111
Arena {
111
112
head : RefCell :: new ( chunk ( initial_size, false ) ) ,
112
113
copy_head : RefCell :: new ( chunk ( initial_size, true ) ) ,
113
114
chunks : RefCell :: new ( Vec :: new ( ) ) ,
115
+ _invariant : marker:: InvariantLifetime ,
114
116
}
115
117
}
116
118
}
@@ -124,7 +126,7 @@ fn chunk(size: uint, is_copy: bool) -> Chunk {
124
126
}
125
127
126
128
#[ unsafe_destructor]
127
- impl Drop for Arena {
129
+ impl < ' longer_than_self > Drop for Arena < ' longer_than_self > {
128
130
fn drop ( & mut self ) {
129
131
unsafe {
130
132
destroy_chunk ( & * self . head . borrow ( ) ) ;
@@ -182,7 +184,7 @@ fn un_bitpack_tydesc_ptr(p: uint) -> (*const TyDesc, bool) {
182
184
( ( p & !1 ) as * const TyDesc , p & 1 == 1 )
183
185
}
184
186
185
- impl Arena {
187
+ impl < ' longer_than_self > Arena < ' longer_than_self > {
186
188
fn chunk_size ( & self ) -> uint {
187
189
self . copy_head . borrow ( ) . capacity ( )
188
190
}
@@ -295,7 +297,7 @@ impl Arena {
295
297
/// Allocates a new item in the arena, using `op` to initialize the value,
296
298
/// and returns a reference to it.
297
299
#[ inline]
298
- pub fn alloc < T , F > ( & self , op : F ) -> & mut T where F : FnOnce ( ) -> T {
300
+ pub fn alloc < T : ' longer_than_self , F > ( & self , op : F ) -> & mut T where F : FnOnce ( ) -> T {
299
301
unsafe {
300
302
if intrinsics:: needs_drop :: < T > ( ) {
301
303
self . alloc_noncopy ( op)
@@ -319,20 +321,6 @@ fn test_arena_destructors() {
319
321
}
320
322
}
321
323
322
- #[ test]
323
- fn test_arena_alloc_nested ( ) {
324
- struct Inner { value : uint }
325
- struct Outer < ' a > { inner : & ' a Inner }
326
-
327
- let arena = Arena :: new ( ) ;
328
-
329
- let result = arena. alloc ( || Outer {
330
- inner : arena. alloc ( || Inner { value : 10 } )
331
- } ) ;
332
-
333
- assert_eq ! ( result. inner. value, 10 ) ;
334
- }
335
-
336
324
#[ test]
337
325
#[ should_fail]
338
326
fn test_arena_destructors_fail ( ) {
@@ -530,6 +518,41 @@ mod tests {
530
518
z : int ,
531
519
}
532
520
521
+ #[ test]
522
+ fn test_arena_alloc_nested ( ) {
523
+ struct Inner { value : u8 }
524
+ struct Outer < ' a > { inner : & ' a Inner }
525
+ enum EI < ' e > { I ( Inner ) , O ( Outer < ' e > ) }
526
+
527
+ struct Wrap < ' a > ( TypedArena < EI < ' a > > ) ;
528
+
529
+ impl < ' a > Wrap < ' a > {
530
+ fn alloc_inner < F : Fn ( ) -> Inner > ( & self , f : F ) -> & Inner {
531
+ let r: & EI = self . 0 . alloc ( EI :: I ( f ( ) ) ) ;
532
+ if let & EI :: I ( ref i) = r {
533
+ i
534
+ } else {
535
+ panic ! ( "mismatch" ) ;
536
+ }
537
+ }
538
+ fn alloc_outer < F : Fn ( ) -> Outer < ' a > > ( & self , f : F ) -> & Outer {
539
+ let r: & EI = self . 0 . alloc ( EI :: O ( f ( ) ) ) ;
540
+ if let & EI :: O ( ref o) = r {
541
+ o
542
+ } else {
543
+ panic ! ( "mismatch" ) ;
544
+ }
545
+ }
546
+ }
547
+
548
+ let arena = Wrap ( TypedArena :: new ( ) ) ;
549
+
550
+ let result = arena. alloc_outer ( || Outer {
551
+ inner : arena. alloc_inner ( || Inner { value : 10 } ) } ) ;
552
+
553
+ assert_eq ! ( result. inner. value, 10 ) ;
554
+ }
555
+
533
556
#[ test]
534
557
pub fn test_copy ( ) {
535
558
let arena = TypedArena :: new ( ) ;
0 commit comments