実現したいこと
スタックを模倣したプログラムを作ります。
nest
メソッドで新しいStackを返し、そのStackがドロップされるまでnest元のStack経由でメモリ確保はできません。これをmut借用の特性を使って表現したのが次のコードです。
解決にあたって変えてはいけないのは次のことです。
- main関数内の処理を変えてはいけない。
できれば回避したいことは次です。
- RefCellやRcは使いたくない
発生している問題・分からないこと
ライフタイム関連のエラーが出ます。
エラーメッセージ
error
1error: lifetime may not live long enough 2 --> src/main.rs:84:36 3 | 465 | impl<'a, 'b, T> Stack<'a, 'b, T> { 5 | -- -- lifetime `'b` defined here 6 | | 7 | lifetime `'a` defined here 8... 984 | parent: Parent::Parent(self), 10 | ^^^^ this usage requires that `'b` must outlive `'a` 11 | 12 = help: consider adding the following bound: `'b: 'a` 13 = note: requirement occurs because of a mutable reference to `Stack<'_, '_, T>` 14 = note: mutable references are invariant over their type parameter 15 = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
該当のソースコード
rust
1use std::collections::HashMap; 2 3fn main() { 4 let mut mem = Memory::new(); 5 let mut stack = Stack::new(&mut mem); 6 stack.alloc(0, "v1"); 7 { 8 let mut nest = stack.nest(); 9 nest.push(1, "v2"); 10 assert_eq!(nest.len(), 2); 11 } 12 assert_eq!(stack.len(), 1); 13 stack.alloc(2, "v3"); 14 assert_eq!(stack.len(), 2); 15} 16struct Memory<T> { 17 data: HashMap<u32, T>, 18} 19impl<T> Memory<T> { 20 fn new() -> Self { 21 Self { 22 data: HashMap::new(), 23 } 24 } 25 fn alloc(&mut self, id: u32, value: T) { 26 self.data.insert(id, value).unwrap(); 27 } 28 fn free(&mut self, id: u32) { 29 if self.data.remove(&id).is_some() { 30 panic!() 31 } 32 } 33} 34struct Stack<'a, 'b, T> { 35 ids: Vec<u32>, 36 parent: Parent<'a, 'b, T>, 37} 38enum Parent<'a, 'b, T> 39where 40 'a: 'b, 41{ 42 Root(&'a mut Memory<T>), 43 Parent(&'b mut Stack<'a, 'a, T>), 44} 45impl<'a, 'b, T> Parent<'a, 'b, T> { 46 fn alloc(&mut self, id: u32, value: T) { 47 match self { 48 Parent::Root(memory) => memory.alloc(id, value), 49 Parent::Parent(stack) => stack.alloc(id, value), 50 } 51 } 52 fn free(&mut self, id: u32) { 53 match self { 54 Parent::Root(memory) => memory.free(id), 55 Parent::Parent(stack) => stack.free(id), 56 } 57 } 58 fn len(&self) -> usize { 59 match self { 60 Parent::Root(memory) => memory.data.len(), 61 Parent::Parent(stack) => stack.len(), 62 } 63 } 64} 65impl<'a, 'b, T> Stack<'a, 'b, T> { 66 fn new(mem: &'a mut Memory<T>) -> Self { 67 Self { 68 ids: vec![], 69 parent: Parent::Root(mem), 70 } 71 } 72 fn push(&mut self, id: u32, value: T){ 73 self.ids.push(id); 74 self.alloc(id, value); 75 } 76 fn alloc(&mut self, id: u32, value: T) { 77 self.parent.alloc(id, value); 78 } 79 fn free(&mut self, id: u32) { 80 self.parent.free(id); 81 } 82 fn nest<'c>(&'c mut self) -> Stack<'a, 'c, T> 83 where 84 'b: 'c, 85 { 86 Stack { 87 ids: vec![], 88 parent: Parent::Parent(self), 89 } 90 } 91 fn len(&self) -> usize { 92 self.parent.len() 93 } 94} 95impl<'a, 'b, T> Drop for Stack<'a, 'b, T> { 96 fn drop(&mut self) { 97 for id in &self.ids { 98 self.parent.free(*id); 99 } 100 } 101} 102
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
なお張り付けたコードのnest関数を現在の
rust
1fn nest<'c>(&'c mut self) -> Stack<'a, 'c, T> 2 where 3 'b: 'c,
ではなく、
rust
1fn nest(&'b mut self)->Stack<'a, 'b, T>
とすると、nestのエラーは消えますが、以下の(2)のエラーが代わりに出ます。
error[E0597]: stack
does not live long enough
--> src/main.rs:8:24
|
5 | let mut stack = Stack::new(&mut mem);
| --------- binding stack
declared here
...
8 | let mut nest = stack.nest();
| ^^^^^ borrowed value does not live long enough
...
15 | }
| -
| |
| stack
dropped here while still borrowed
| borrow might be used here, when stack
is dropped and runs the Drop
code for type Stack
error[E0502]: cannot borrow stack
as immutable because it is also borrowed as mutable
--> src/main.rs:12:16
|
8 | let mut nest = stack.nest();
| ----- mutable borrow occurs here
...
12 | assert_eq!(stack.len(), 1);
| ^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
error[E0499]: cannot borrow stack
as mutable more than once at a time
--> src/main.rs:13:5
|
8 | let mut nest = stack.nest();
| ----- first mutable borrow occurs here
...
13 | stack.alloc(2, "v3");
| ^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
error[E0502]: cannot borrow stack
as immutable because it is also borrowed as mutable
--> src/main.rs:14:16
|
8 | let mut nest = stack.nest();
| ----- mutable borrow occurs here
...
14 | assert_eq!(stack.len(), 1);
| ^^^^^
| |
| immutable borrow occurs here
| mutable borrow later used here
error: lifetime may not live long enough
--> src/main.rs:82:36
|
65 | impl<'a, 'b, T> Stack<'a, 'b, T> {
| -- -- lifetime 'b
defined here
| |
| lifetime 'a
defined here
...
82 | parent: Parent::Parent(self),
| ^^^^ this usage requires that 'b
must outlive 'a
|
= help: consider adding the following bound: 'b: 'a
= note: requirement occurs because of a mutable reference to Stack<'_, '_, T>
= note: mutable references are invariant over their type parameter
= help: see https://doc.rust-lang.org/nomicon/subtyping.html for more information about variance
Some errors have detailed explanations: E0499, E0502, E0597.
For more information about an error, try rustc --explain E0499
.
error: could not compile workspace
(bin "workspace") due to 5 previous errors
補足
特になし

回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/01/26 17:33