Skip to content

Commit bb7aa28

Browse files
authored
Translate vec-layout.md (#53)
1 parent 1d8efff commit bb7aa28

File tree

2 files changed

+68
-8
lines changed

2 files changed

+68
-8
lines changed

src/SUMMARY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
* [Send and Sync](send-and-sync.md)
4242
* [Atomics](atomics.md)
4343
* [Vec の実装](vec.md)
44-
* [Layout](vec-layout.md)
44+
* [レイアウト](vec-layout.md)
4545
* [Allocating](vec-alloc.md)
4646
* [Push and Pop](vec-push-pop.md)
4747
* [Deallocating](vec-dealloc.md)

src/vec-layout.md

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,24 @@
1+
<!--
12
# Layout
3+
-->
24

5+
# レイアウト
6+
7+
<!--
38
First off, we need to come up with the struct layout. A Vec has three parts:
49
a pointer to the allocation, the size of the allocation, and the number of
510
elements that have been initialized.
11+
-->
12+
13+
まず、構造体のレイアウトを考える必要があります。 Vec は 3 つの部品を
14+
持っています。アロケーションへのポインタと、アロケーションの大きさ、
15+
そして初期化された要素の数です。
616

17+
<!--
718
Naively, this means we just want this design:
19+
-->
20+
21+
愚直に考えると、これは以下の設計で良いということになります。
822

923
```rust
1024
pub struct Vec<T> {
@@ -15,41 +29,74 @@ pub struct Vec<T> {
1529
# fn main() {}
1630
```
1731

32+
<!--
1833
And indeed this would compile. Unfortunately, it would be incorrect. First, the
1934
compiler will give us too strict variance. So a `&Vec<&'static str>`
2035
couldn't be used where an `&Vec<&'a str>` was expected. More importantly, it
2136
will give incorrect ownership information to the drop checker, as it will
2237
conservatively assume we don't own any values of type `T`. See [the chapter
2338
on ownership and lifetimes][ownership] for all the details on variance and
2439
drop check.
40+
-->
2541

42+
そして実際に、このコードはコンパイルできます。残念ながら、この設計は正しくありません。
43+
まず、コンパイラはあまりに厳密すぎる変性を与えることになります。ですから
44+
`&Vec<&'a str>` が予期されているところで `&Vec<&'static str>` を使う事が
45+
出来ません。もっと重要なことに、この設計によって正しくない所有権の情報が
46+
ドロップチェッカに渡されてしまいます。型 `T` のいかなる値も所有していないと、
47+
ドロップチェッカが保守的に判断してしまうからです。変性やドロップチェックに
48+
関する全ての詳細は、[所有権とライフタイムの章][ownership]を参照してください。
49+
50+
<!--
2651
As we saw in the ownership chapter, we should use `Unique<T>` in place of
2752
`*mut T` when we have a raw pointer to an allocation we own. Unique is unstable,
2853
so we'd like to not use it if possible, though.
54+
-->
55+
56+
所有権の章で見てきたように、所有しているアロケーションに対する生ポインタを持つ場合、
57+
`*mut T` の代わりに `Unique<T>` を使用するべきです。 Unique はアンステーブルなため、
58+
可能なら使いませんが。
2959

60+
<!--
3061
As a recap, Unique is a wrapper around a raw pointer that declares that:
62+
-->
3163

64+
繰り返しになりますが、 Unique は生ポインタのラッパで、以下のことを宣言
65+
します。
66+
67+
<!--
3268
* We are variant over `T`
3369
* We may own a value of type `T` (for drop check)
3470
* We are Send/Sync if `T` is Send/Sync
3571
* We deref to `*mut T` (so it largely acts like a `*mut` in our code)
3672
* 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>>` はヌルポインタ最適化される)
3780

81+
<!--
3882
We can implement all of the above requirements except for the last
3983
one in stable Rust:
84+
-->
85+
86+
上記の最後以外の項は、安定版の Rust で実装可能です。
4087

4188
```rust
4289
use std::marker::PhantomData;
4390
use std::ops::Deref;
4491
use std::mem;
4592

4693
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>, // ドロップチェッカ対策
4996
}
5097

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 のようなものです。
53100
unsafe impl<T: Send> Send for Unique<T> {}
54101
unsafe impl<T: Sync> Sync for Unique<T> {}
55102

@@ -62,18 +109,23 @@ impl<T> Unique<T> {
62109
impl<T> Deref for Unique<T> {
63110
type Target = *mut T;
64111
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+
// これらは全て "ただのポインタ" ですのでトランスミュートします。
68115
unsafe { mem::transmute(&self.ptr) }
69116
}
70117
}
71118
# fn main() {}
72119
```
73120

121+
<!--
74122
Unfortunately the mechanism for stating that your value is non-zero is
75123
unstable and unlikely to be stabilized soon. As such we're just going to
76124
take the hit and use std's Unique:
125+
-->
126+
127+
残念ながら、値が非 0 であると述べるメカニズムはアンステーブルで、すぐには
128+
安定版はならないでしょう。ですから単に std の Unique を使うことにします。
77129

78130

79131
```rust
@@ -90,11 +142,19 @@ pub struct Vec<T> {
90142
# fn main() {}
91143
```
92144

145+
<!--
93146
If you don't care about the null-pointer optimization, then you can use the
94147
stable code. However we will be designing the rest of the code around enabling
95148
the optimization. In particular, `Unique::new` is unsafe to call, because
96149
putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't
97150
need `new` to be unsafe because it doesn't make any interesting guarantees about
98151
its contents.
152+
-->
153+
154+
もしヌルポインタ最適化を気にしないなら、安定版のコードを使用することもできます。
155+
しかしながら、残りのコードでは、最適化を有効にするような設計していきます。
156+
特に、 `Unique::new` を呼ぶことはアンセーフです。なぜなら `null` を中に突っ込む
157+
ことは、未定義動作を引き起こしてしまうからです。安定版のコードの `new` はアンセーフに
158+
する必要はありません。中身についての興味深い保証をしないからです。
99159

100160
[ownership]: ownership.html

0 commit comments

Comments
 (0)