teratail header banner
teratail header banner
質問するログイン新規登録

回答編集履歴

3

`if self.cache.get(hash).is_none()` を `if !self.contains_key(hash)` に変更しました

2020/05/10 16:04

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -7,7 +7,7 @@
7
7
  ```rust
8
8
  fn get_ref(&mut self, hash: &U256, tasks: &Tasks) -> Result<&Meta, String> {
9
9
  // Metaの存在チェックをして、存在しないならcacheに追加する
10
- if self.cache.get(hash).is_none() {
10
+ if !self.cache.contains_key(hash) {
11
11
  match tasks.get_data(hash)? {
12
12
  Some(data) => {
13
13
  let meta = Meta::from(data);

2

ソースコードコメントを追加しました

2020/05/10 16:04

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -1,6 +1,6 @@
1
1
  エラーメッセージによると、最初のmatchアーム`Some(meta) => Ok(meta)`で`self.cache`が所有する値への参照`&Meta`をmatch式の外に返しているのが原因のようです。`&Meta`が有効な間、つまり、`get_ref()`メソッドの外まで`self.cache`の不変借用が続くことになるので、たとえ`None`のアーム内であっても、その不変借用が有効になっています。
2
2
 
3
- なぜこうなるのかというと、`get_ref()`から戻った後、`&Meta`が有効な間は`cache`マップの内容を変更できないようにするためです。もし変更を許すと、`&Meta`が指している`Meta`が`cache`マップから削除できてしまい、&Metaはダングリングポインタになってしまいます。
3
+ なぜこうなるのかというと、`get_ref()`から戻った後、`&Meta`が有効な間は`cache`マップの内容を変更できないようにするためです。もし変更を許すと、`&Meta`が指している`Meta`が`cache`マップから削除できてしまい、`&Meta`はダングリングポインタになってしまいます。
4
4
 
5
5
  問題となっているのは`Ok(meta)`を返すところです。その部分が`self.cache.remove()`などと競合しないようにメソッドの最後に移せばエラーが解消します。
6
6
 
@@ -23,7 +23,8 @@
23
23
  }
24
24
  }
25
25
 
26
+ // cacheしておいたMetaを返す。これ以降は`&Mata`が有効な間は`self.cache`は
26
- // cacheしておいたMetaを返す
27
+ // 変更できなくなる
27
28
  self.cache.get(hash).ok_or_else(|| "failed".to_owned())
28
29
  }
29
30
  ```

1

説明を追加しました

2020/05/10 14:23

投稿

tatsuya6502
tatsuya6502

スコア2055

answer CHANGED
@@ -1,5 +1,7 @@
1
1
  エラーメッセージによると、最初のmatchアーム`Some(meta) => Ok(meta)`で`self.cache`が所有する値への参照`&Meta`をmatch式の外に返しているのが原因のようです。`&Meta`が有効な間、つまり、`get_ref()`メソッドの外まで`self.cache`の不変借用が続くことになるので、たとえ`None`のアーム内であっても、その不変借用が有効になっています。
2
2
 
3
+ なぜこうなるのかというと、`get_ref()`から戻った後、`&Meta`が有効な間は`cache`マップの内容を変更できないようにするためです。もし変更を許すと、`&Meta`が指している`Meta`が`cache`マップから削除できてしまい、&Metaはダングリングポインタになってしまいます。
4
+
3
5
  問題となっているのは`Ok(meta)`を返すところです。その部分が`self.cache.remove()`などと競合しないようにメソッドの最後に移せばエラーが解消します。
4
6
 
5
7
  ```rust