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

質問編集履歴

1

矛盾としていたものが矛盾ではなかったので、そのように修正。

2018/07/14 10:58

投稿

Eki
Eki

スコア429

title CHANGED
File without changes
body CHANGED
@@ -11,46 +11,43 @@
11
11
  これを次のように使うと、コメントしてある通りのエラーになります。
12
12
  なお、コメントの通りライフタイムに名前を付けます。
13
13
 
14
+ **修正** 少し勘違いして間違ったことを書いていたので、編集させていただきました。これ以下は修正したものです。質問の趣旨は変わりません。また、その後の具体例があまり意味をなしていなかったので削除しました。
15
+
16
+ ---
17
+
18
+ `x` の型を表すのに `decltype(x)` という表記を借りてくることにします。型同士の不等号はその型の生存期間の長さを表すものとします (サブタイピング的な意味ではありません) 。
19
+
20
+
14
21
  ```rust
15
22
  // ブロック (3つ下の行から始まるもの) の外側のライフタイムを 'outer とします。
16
23
  let mut x: i32 = 3;
17
24
  let rx = &mut x;
18
25
  { // ブロック開始、この内部のライフタイムを 'inner とします。
19
26
  let mut y = 4;
20
- let ry = &'inner mut y;
27
+ let ry = &mut y;
28
+ { // さらにこの内部のライフタイムを適当に 'center とでもします。
29
+ let rry = foo(rx, ry);
21
30
 
31
+ // error: use of moved value: `rx`
22
- let rry = foo(rx, ry);
32
+ // println!("{}", rx);
23
33
 
24
- // error: use of moved value: `rx`
25
- // println!("{}", rx);
26
-
27
- // error: cannot borrow `ry` as immutable because `*ry` is also borrowed as mutable
34
+ // error: cannot borrow `ry` as immutable because `*ry` is also borrowed as mutable
28
- // (と言って foo() の呼び出し箇所を指す)
35
+ // (と言って foo() の呼び出し箇所を指す)
29
- // println!("{}", ry);
36
+ // println!("{}", ry);
37
+ }
30
38
  }
31
39
  ```
32
40
 
33
- `x` の型を表すのに `decltype(x)` という表記を借りてくることにします。型同士の不等号はその型の生存期間の長さを表すものとします (サブタイピング的な意味ではありません) 。
34
-
35
41
  1. エラーは `rx` がムーブされ、 `ry` が再借用されていることを表すので、 `T == decltype(rx)` かつ `T != decltype(ry)` となります。
36
- 2. `ry` の再借用がなされるからには、`T` の生存期間は `y` の生存期間 `'inner` と同じかそれより短い必要、つまり、`T <= 'inner` となる必要があるはずです。そうでないと、再借用によって元変数の生存期間より長い期間を生きる参照が生み出されてしまうからです。
42
+ 2. `ry` の再借用がなされるからには、`T` の生存期間は `y` の生存期間 `'inner` と同じかそれより短い必要、つまり、`T <= 'inner` となる必要があるはずです。
37
- 3. `ry` を表示する `println!` が件のエラーを出すからには、 `println!` 実行時点で参照 `rry` が有効である必要、つまり `T >= 'inner` となる必要があります。
43
+ 3. `ry` を表示する `println!` が件のエラーを出すからには、 `println!` 実行時点で参照 `rry` が有効である必要、つまり `T >= 'center` となる必要があります。
38
44
 
39
- これ矛盾す。`T` はここでは何者で、何が起こっているのでょうか。
45
+ 以上から `decltype(rx) == T == &'center mut i32` で、 `decltype(ry) == &'inner mut i32` というとになります。これはしかし不自然です。普通は `rx` の方が外宣言されているので長く生き延びるすし必要最低限の期間に絞られているたら `ry` もやはり絞られているべきと考えるらです
40
46
 
41
- 具体的に考えてみても変す。
47
+ **修正ここま**
42
48
 
43
- 一つには次のように考えられますが疑問が残ります。 `rx` `'outer` 定義されてることを考えると `decltype(rx) == &'outer mut i32` となるので `T == &'outer mut i32` となます、 `foo(_x: &'outer mut i32, _y: &'outer mut i32)` の `_y` に対して `ry` を再借用して渡すこになり、この再借用は生存期間が `'inner` -> `'outer` と拡大される再借用です。これは本来できなことだと思います。
49
+ 長くなりました、読んでいただきありがとうございます。よろしくお願ます。
44
50
 
45
- あるいは、別の考え方として次も考えられますがやはり疑問が残ります。`let rx = ...` の段階では `rx` の型を指定していないので、生存期間が推論の自由度として残されており、以後の使用を見て生存期間が変わっているのではないか。ちょうど
51
+ ---
46
52
 
47
- ```rust
48
- let mut v = Vec::new();
49
- v.push(1);
50
- ```
51
-
52
- のとき、`v` の型が `let` の段階では完全には決まらないのと同様に、です。だとすると `foo()` の呼び出しの時点で `rx` の型が推論されるしかありません。しかしそれなら、そのときどのような推論が行われるにせよ、 `ry` についても同様の推論がされて `T == decltype(rx) == decltype(ry)` となるはずです。それなら `rx` も `ry` も両方ともムーブされるはずなので、妙です。
53
-
54
- 長くなりましたが、読んでいただきありがとうございます。よろしくお願いします。
55
-
56
53
  ところで `foo()` に渡す順序を変えて `foo(ry, rx)` とすると、今度は `use of moved value: 'ry'` となりました。あまり考えず、第一引数に合わせて推論しているような気もします。