質問編集履歴

1

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

2018/07/14 10:58

投稿

Eki
Eki

スコア429

test CHANGED
File without changes
test CHANGED
@@ -24,6 +24,20 @@
24
24
 
25
25
 
26
26
 
27
+ **修正** 少し勘違いして間違ったことを書いていたので、編集させていただきました。これ以下は修正したものです。質問の趣旨は変わりません。また、その後の具体例があまり意味をなしていなかったので削除しました。
28
+
29
+
30
+
31
+ ---
32
+
33
+
34
+
35
+ `x` の型を表すのに `decltype(x)` という表記を借りてくることにします。型同士の不等号はその型の生存期間の長さを表すものとします (サブタイピング的な意味ではありません) 。
36
+
37
+
38
+
39
+
40
+
27
41
  ```rust
28
42
 
29
43
  // ブロック (3つ下の行から始まるもの) の外側のライフタイムを 'outer とします。
@@ -36,25 +50,27 @@
36
50
 
37
51
  let mut y = 4;
38
52
 
39
- let ry = &'inner mut y;
53
+ let ry = &mut y;
54
+
55
+ { // さらにこの内部のライフタイムを適当に 'center とでもします。
56
+
57
+ let rry = foo(rx, ry);
40
58
 
41
59
 
42
60
 
61
+ // error: use of moved value: `rx`
62
+
43
- let rry = foo(rx, ry);
63
+ // println!("{}", rx);
44
64
 
45
65
 
46
66
 
47
- // error: use of moved value: `rx`
67
+ // error: cannot borrow `ry` as immutable because `*ry` is also borrowed as mutable
48
68
 
49
- // println!("{}", rx);
69
+ // (と言って foo() の呼び出し箇所を指す)
50
70
 
71
+ // println!("{}", ry);
51
72
 
52
-
53
- // error: cannot borrow `ry` as immutable because `*ry` is also borrowed as mutable
54
-
55
- // (と言って foo() の呼び出し箇所を指す)
56
-
57
- // println!("{}", ry);
73
+ }
58
74
 
59
75
  }
60
76
 
@@ -62,45 +78,19 @@
62
78
 
63
79
 
64
80
 
65
- `x` の型を表すの `decltype(x)` という表記を借りてくることにします。型同士の不等号はその型の生存期間の長さを表すものとします (サブタイピング的意味ではありません)
81
+ 1. エラーは `rx` がムーブされ、 `ry` が再借用されていることを表すので、 `T == decltype(rx)` かつ `T != decltype(ry)` となりま
82
+
83
+ 2. `ry` の再借用がなされるからには、`T` の生存期間は `y` の生存期間 `'inner` と同じかそれより短い必要、つまり、`T <= 'inner` となる必要があるはずです。
84
+
85
+ 3. `ry` を表示する `println!` が件のエラーを出すからには、 `println!` 実行時点で参照 `rry` が有効である必要、つまり `T >= 'center` となる必要があります。
66
86
 
67
87
 
68
88
 
69
- 1. エラーは `rx` がムーブされ、 `ry` が再借用されていることを表すので、 `T == decltype(rx)` かつ `T != decltype(ry)` となります。
70
-
71
- 2. `ry` の再借用がなされるからには、`T` の生存期間は `y` の生存期間 `'inner` と同じかそれより短い必要つまり、`T <= 'inner` となる必要るはずです。そうでないと再借用によって元変数生存期間期間を生きる参照が生み出されてしまうからです。
89
+ 以上から `decltype(rx) == T == &'center mut i32` `decltype(ry) == &'inner mut i32` ということにります。これはしかし不自然です。普通は `rx` の方外で宣言されていので長く生き延びるはずです必要最低限の期間に絞られているとしたら `ry` もやは絞られてるべと考えるからです。
72
-
73
- 3. `ry` を表示する `println!` が件のエラーを出すからには、 `println!` 実行時点で参照 `rry` が有効である必要、つまり `T >= 'inner` となる必要があります。
74
90
 
75
91
 
76
92
 
77
- れらは矛盾しす。`T` はここは何者で、何が起こっているのでしょうか。
78
-
79
-
80
-
81
- 具体的に考えてみても変です。
82
-
83
-
84
-
85
- 一つには次のように考えられますが疑問が残ります。 `rx` が `'outer` で定義されていることを考えると `decltype(rx) == &'outer mut i32` となるので `T == &'outer mut i32` となりますが、 `foo(_x: &'outer mut i32, _y: &'outer mut i32)` の `_y` に対して `ry` を再借用して渡すことになり、この再借用は生存期間が `'inner` -> `'outer` と拡大される再借用です。これは本来できないことだと思います。
86
-
87
-
88
-
89
- あるいは、別の考え方として次も考えられますがやはり疑問が残ります。`let rx = ...` の段階では `rx` の型を指定していないので、生存期間が推論の自由度として残されており、以後の使用を見て生存期間が変わっているのではないか。ちょうど
90
-
91
-
92
-
93
- ```rust
94
-
95
- let mut v = Vec::new();
96
-
97
- v.push(1);
98
-
99
- ```
100
-
101
-
102
-
103
- のとき、`v` の型が `let` の段階では完全には決まらないのと同様に、です。だとすると `foo()` の呼び出しの時点で `rx` の型が推論されるしかありません。しかしそれなら、そのときどのような推論が行われるにせよ、 `ry` についても同様の推論がされて `T == decltype(rx) == decltype(ry)` となるはずです。それなら `rx` も `ry` も両方ともムーブされるはずなので、妙です。
93
+ **修正まで**
104
94
 
105
95
 
106
96
 
@@ -108,4 +98,8 @@
108
98
 
109
99
 
110
100
 
101
+ ---
102
+
103
+
104
+
111
105
  ところで `foo()` に渡す順序を変えて `foo(ry, rx)` とすると、今度は `use of moved value: 'ry'` となりました。あまり考えず、第一引数に合わせて推論しているような気もします。