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