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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy