@@ -89,27 +89,29 @@ impl Chunk {
8989/// than objects without destructors. This reduces overhead when initializing
9090/// plain-old-data (`Copy` types) and means we don't need to waste time running
9191/// their destructors.
92- pub struct Arena {
92+ pub struct Arena < ' longer_than_self > {
9393 // The head is separated out from the list as a unbenchmarked
9494 // microoptimization, to avoid needing to case on the list to access the
9595 // head.
9696 head : RefCell < Chunk > ,
9797 copy_head : RefCell < Chunk > ,
9898 chunks : RefCell < Vec < Chunk > > ,
99+ _invariant : marker:: InvariantLifetime < ' longer_than_self > ,
99100}
100101
101- impl Arena {
102+ impl < ' a > Arena < ' a > {
102103 /// Allocates a new Arena with 32 bytes preallocated.
103- pub fn new ( ) -> Arena {
104+ pub fn new ( ) -> Arena < ' a > {
104105 Arena :: new_with_size ( 32 )
105106 }
106107
107108 /// 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 > {
109110 Arena {
110111 head : RefCell :: new ( chunk ( initial_size, false ) ) ,
111112 copy_head : RefCell :: new ( chunk ( initial_size, true ) ) ,
112113 chunks : RefCell :: new ( Vec :: new ( ) ) ,
114+ _invariant : marker:: InvariantLifetime ,
113115 }
114116 }
115117}
@@ -123,7 +125,7 @@ fn chunk(size: usize, is_copy: bool) -> Chunk {
123125}
124126
125127#[ unsafe_destructor]
126- impl Drop for Arena {
128+ impl < ' longer_than_self > Drop for Arena < ' longer_than_self > {
127129 fn drop ( & mut self ) {
128130 unsafe {
129131 destroy_chunk ( & * self . head . borrow ( ) ) ;
@@ -181,7 +183,7 @@ fn un_bitpack_tydesc_ptr(p: usize) -> (*const TyDesc, bool) {
181183 ( ( p & !1 ) as * const TyDesc , p & 1 == 1 )
182184}
183185
184- impl Arena {
186+ impl < ' longer_than_self > Arena < ' longer_than_self > {
185187 fn chunk_size ( & self ) -> usize {
186188 self . copy_head . borrow ( ) . capacity ( )
187189 }
@@ -294,7 +296,7 @@ impl Arena {
294296 /// Allocates a new item in the arena, using `op` to initialize the value,
295297 /// and returns a reference to it.
296298 #[ 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 {
298300 unsafe {
299301 if intrinsics:: needs_drop :: < T > ( ) {
300302 self . alloc_noncopy ( op)
@@ -318,20 +320,6 @@ fn test_arena_destructors() {
318320 }
319321}
320322
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-
335323#[ test]
336324#[ should_fail]
337325fn test_arena_destructors_fail ( ) {
@@ -529,6 +517,41 @@ mod tests {
529517 z : i32 ,
530518 }
531519
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+
532555 #[ test]
533556 pub fn test_copy ( ) {
534557 let arena = TypedArena :: new ( ) ;
0 commit comments