質問編集履歴
1
矛盾としていたものが矛盾ではなかったので、そのように修正。
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 = &
|
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
|
-
|
63
|
+
// println!("{}", rx);
|
44
64
|
|
45
65
|
|
46
66
|
|
47
|
-
// error: use o
|
67
|
+
// error: cannot borrow `ry` as immutable because `*ry` is also borrowed as mutable
|
48
68
|
|
49
|
-
//
|
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
|
-
|
73
|
+
}
|
58
74
|
|
59
75
|
}
|
60
76
|
|
@@ -62,45 +78,19 @@
|
|
62
78
|
|
63
79
|
|
64
80
|
|
65
|
-
`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
|
-
|
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
|
-
こ
|
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'` となりました。あまり考えず、第一引数に合わせて推論しているような気もします。
|