1
+ <!--
1
2
# Layout
3
+ -->
2
4
5
+ # レイアウト
6
+
7
+ <!--
3
8
First off, we need to come up with the struct layout. A Vec has three parts:
4
9
a pointer to the allocation, the size of the allocation, and the number of
5
10
elements that have been initialized.
11
+ -->
12
+
13
+ まず、構造体のレイアウトを考える必要があります。 Vec は 3 つの部品を
14
+ 持っています。アロケーションへのポインタと、アロケーションの大きさ、
15
+ そして初期化された要素の数です。
6
16
17
+ <!--
7
18
Naively, this means we just want this design:
19
+ -->
20
+
21
+ 愚直に考えると、これは以下の設計で良いということになります。
8
22
9
23
``` rust
10
24
pub struct Vec <T > {
@@ -15,41 +29,74 @@ pub struct Vec<T> {
15
29
# fn main () {}
16
30
```
17
31
32
+ <!--
18
33
And indeed this would compile. Unfortunately, it would be incorrect. First, the
19
34
compiler will give us too strict variance. So a `&Vec<&'static str>`
20
35
couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it
21
36
will give incorrect ownership information to the drop checker, as it will
22
37
conservatively assume we don't own any values of type `T`. See [the chapter
23
38
on ownership and lifetimes][ownership] for all the details on variance and
24
39
drop check.
40
+ -->
25
41
42
+ そして実際に、このコードはコンパイルできます。残念ながら、この設計は正しくありません。
43
+ まず、コンパイラはあまりに厳密すぎる変性を与えることになります。ですから
44
+ ` &Vec<&'a str> ` が予期されているところで ` &Vec<&'static str> ` を使う事が
45
+ 出来ません。もっと重要なことに、この設計によって正しくない所有権の情報が
46
+ ドロップチェッカに渡されてしまいます。型 ` T ` のいかなる値も所有していないと、
47
+ ドロップチェッカが保守的に判断してしまうからです。変性やドロップチェックに
48
+ 関する全ての詳細は、[ 所有権とライフタイムの章] [ ownership ] を参照してください。
49
+
50
+ <!--
26
51
As we saw in the ownership chapter, we should use `Unique<T>` in place of
27
52
`*mut T` when we have a raw pointer to an allocation we own. Unique is unstable,
28
53
so we'd like to not use it if possible, though.
54
+ -->
55
+
56
+ 所有権の章で見てきたように、所有しているアロケーションに対する生ポインタを持つ場合、
57
+ ` *mut T ` の代わりに ` Unique<T> ` を使用するべきです。 Unique はアンステーブルなため、
58
+ 可能なら使いませんが。
29
59
60
+ <!--
30
61
As a recap, Unique is a wrapper around a raw pointer that declares that:
62
+ -->
31
63
64
+ 繰り返しになりますが、 Unique は生ポインタのラッパで、以下のことを宣言
65
+ します。
66
+
67
+ <!--
32
68
* We are variant over `T`
33
69
* We may own a value of type `T` (for drop check)
34
70
* We are Send/Sync if `T` is Send/Sync
35
71
* We deref to `*mut T` (so it largely acts like a `*mut` in our code)
36
72
* Our pointer is never null (so `Option<Vec<T>>` is null-pointer-optimized)
73
+ -->
74
+
75
+ * ` T ` に対して変性
76
+ * 型 ` T ` の値を所有する可能性がある (ドロップチェックのため)
77
+ * ` T ` が Send/Sync を実装している場合、継承される
78
+ * ` *mut T ` に参照外しをする (つまりコード内では専ら ` *mut ` のように振る舞う)
79
+ * ポインタはヌルにはならない (つまり ` Option<Vec<T>> ` はヌルポインタ最適化される)
37
80
81
+ <!--
38
82
We can implement all of the above requirements except for the last
39
83
one in stable Rust:
84
+ -->
85
+
86
+ 上記の最後以外の項は、安定版の Rust で実装可能です。
40
87
41
88
``` rust
42
89
use std :: marker :: PhantomData ;
43
90
use std :: ops :: Deref ;
44
91
use std :: mem;
45
92
46
93
struct Unique <T > {
47
- ptr : * const T , // *const for variance
48
- _marker : PhantomData <T >, // For the drop checker
94
+ ptr : * const T , // 変性のために *const です
95
+ _marker : PhantomData <T >, // ドロップチェッカ対策
49
96
}
50
97
51
- // Deriving Send and Sync is safe because we are the Unique owners
52
- // of this data. It's like Unique<T> is "just " T.
98
+ // Send と Sync を継承することは安全です。なぜならこのデータの
99
+ // Unique を所有しているからです。 Unique<T> は "単なる " T のようなものです。
53
100
unsafe impl <T : Send > Send for Unique <T > {}
54
101
unsafe impl <T : Sync > Sync for Unique <T > {}
55
102
@@ -62,18 +109,23 @@ impl<T> Unique<T> {
62
109
impl <T > Deref for Unique <T > {
63
110
type Target = * mut T ;
64
111
fn deref (& self ) -> & * mut T {
65
- // There's no way to cast the *const to a *mut
66
- // while also taking a reference. So we just
67
- // transmute it since it's all "just pointers".
112
+ // 参照も受け取っている時に、 *const を *mut に
113
+ // キャストする方法はありません。
114
+ // これらは全て "ただのポインタ" ですのでトランスミュートします。
68
115
unsafe { mem :: transmute (& self . ptr) }
69
116
}
70
117
}
71
118
# fn main () {}
72
119
```
73
120
121
+ <!--
74
122
Unfortunately the mechanism for stating that your value is non-zero is
75
123
unstable and unlikely to be stabilized soon. As such we're just going to
76
124
take the hit and use std's Unique:
125
+ -->
126
+
127
+ 残念ながら、値が非 0 であると述べるメカニズムはアンステーブルで、すぐには
128
+ 安定版はならないでしょう。ですから単に std の Unique を使うことにします。
77
129
78
130
79
131
``` rust
@@ -90,11 +142,19 @@ pub struct Vec<T> {
90
142
# fn main () {}
91
143
```
92
144
145
+ <!--
93
146
If you don't care about the null-pointer optimization, then you can use the
94
147
stable code. However we will be designing the rest of the code around enabling
95
148
the optimization. In particular, `Unique::new` is unsafe to call, because
96
149
putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't
97
150
need `new` to be unsafe because it doesn't make any interesting guarantees about
98
151
its contents.
152
+ -->
153
+
154
+ もしヌルポインタ最適化を気にしないなら、安定版のコードを使用することもできます。
155
+ しかしながら、残りのコードでは、最適化を有効にするような設計していきます。
156
+ 特に、 ` Unique::new ` を呼ぶことはアンセーフです。なぜなら ` null ` を中に突っ込む
157
+ ことは、未定義動作を引き起こしてしまうからです。安定版のコードの ` new ` はアンセーフに
158
+ する必要はありません。中身についての興味深い保証をしないからです。
99
159
100
160
[ ownership ] : ownership.html
0 commit comments