Skip to content

Commit 895be02

Browse files
committed
chapter 2
1 parent b0428fe commit 895be02

File tree

5 files changed

+383
-12
lines changed

5 files changed

+383
-12
lines changed

src/SUMMARY.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@
55
* [安全と危険のご紹介](meet-safe-and-unsafe.md)
66
* [安全と危険の相互作用](safe-unsafe-meaning.md)
77
* [Unsafe と連携する](working-with-unsafe.md)
8-
* [Data Layout](data.md)
8+
* [データレイアウト](data.md)
99
* [repr(Rust)](repr-rust.md)
10-
* [Exotically Sized Types](exotic-sizes.md)
11-
* [Other reprs](other-reprs.md)
10+
* [奇妙なサイズの型](exotic-sizes.md)
11+
* [代替メモリレイアウト](other-reprs.md)
1212
* [Ownership](ownership.md)
1313
* [References](references.md)
1414
* [Lifetimes](lifetimes.md)

src/data.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
<!--
12
# Data Representation in Rust
3+
-->
24

5+
# Rust のデータ表現
6+
<!--
37
Low-level programming cares a lot about data layout. It's a big deal. It also
48
pervasively influences the rest of the language, so we're going to start by
59
digging into how data is represented in Rust.
10+
-->
11+
12+
低レイヤのプログラミングでは、データのレイアウトがとても重要です。本当に重要な問題です。
13+
また言語の残りの部分の多くにわたって影響を及ぼします。
14+
ということで、Rust でどのようにデータが表現されるかを詳しく見るところから始めましょう。

src/exotic-sizes.md

Lines changed: 162 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,24 @@
1+
<!--
12
# Exotically Sized Types
3+
-->
24

5+
# 奇妙なサイズの型
6+
7+
<!--
38
Most of the time, we think in terms of types with a fixed, positive size. This
49
is not always the case, however.
10+
-->
511

12+
私たちは、型は 0 以上の固定サイズを持つと通常考えます。でも常にそうであるとは限りません。
613

714

8-
9-
15+
<!--
1016
# Dynamically Sized Types (DSTs)
17+
-->
18+
19+
# 動的サイズの型(DST: Dynamically Sized Type)
1120

21+
<!--
1222
Rust in fact supports Dynamically Sized Types (DSTs): types without a statically
1323
known size or alignment. On the surface, this is a bit nonsensical: Rust *must*
1424
know the size and alignment of something in order to correctly work with it! In
@@ -18,38 +28,86 @@ DST consequently becomes a *fat* pointer consisting of the pointer and the
1828
information that "completes" them (more on this below).
1929
2030
There are two major DSTs exposed by the language: trait objects, and slices.
31+
-->
2132

33+
実際に、Rust は動的にサイズが決まる型(DST)、静的にはサイズやアラインメントがわからない型、
34+
をサポートしています。
35+
一見すると、これは少し馬鹿げているようです。型をうまく扱うためには、
36+
サイズや型を知らなければ*いけない*ですから。
37+
こう考えると DST は通常の型ではありません。サイズが静的にわからないので、
38+
ある種のポインタの裏にしか存在できないのです。
39+
DST を指すポインタは結果的に、普通のポインタと DST を補完する情報(以下で詳しく説明します)から構成される、
40+
*太った* ポインタになります。
41+
42+
言語が提供する DST のうち重要なものが 2 つあります。trait オブジェクトとスライスです。
43+
44+
<!--
2245
A trait object represents some type that implements the traits it specifies.
2346
The exact original type is *erased* in favor of runtime reflection
2447
with a vtable containing all the information necessary to use the type.
2548
This is the information that completes a trait object: a pointer to its vtable.
49+
-->
50+
51+
Trait オブジェクトは、それが指す Trait を実装するある型を表現します。
52+
元となった型は消去されますが、vtable とリフレクションとによって実行時にはその型を利用することができます。
53+
つまり、Trait オブジェクトを補完する情報とは vtable へのポインタとなります。
2654

55+
<!--
2756
A slice is simply a view into some contiguous storage -- typically an array or
2857
`Vec`. The information that completes a slice is just the number of elements
2958
it points to.
59+
-->
3060

61+
スライスとは、単純にある連続したスペース(通常はアレイか `Vec`)のビューです。
62+
スライスを補完する情報とは、単にポインタが指すエレメントの数です。
63+
64+
<!--
3165
Structs can actually store a single DST directly as their last field, but this
3266
makes them a DST as well:
67+
-->
68+
69+
構造体は、最後のフィールドとして DST を直接含むことができますが、その構造体自体も DST になります。
3370

71+
<!--
3472
```rust
3573
// Can't be stored on the stack directly
3674
struct Foo {
3775
info: u32,
3876
data: [u8],
3977
}
4078
```
79+
-->
80+
81+
```rust
82+
// 直接スタックには置けません。
83+
struct Foo {
84+
info: u32,
85+
data: [u8],
86+
}
87+
```
4188

89+
<!--
4290
**NOTE: [As of Rust 1.0 struct DSTs are broken if the last field has
4391
a variable position based on its alignment][dst-issue].**
92+
-->
4493

94+
**[Rust 1.0 時点では、最後のフィールドが正しくアラインメントされていない DST 構造体は正しく動きません][dst-issue]**
4595

4696

97+
<!--
98+
# Zero Sized Types (ZSTs)
99+
-->
47100

101+
# サイズが 0 の型(ZST: Zero Sized Type)
48102

49-
# Zero Sized Types (ZSTs)
103+
<!--
50104
51105
Rust actually allows types to be specified that occupy no space:
106+
-->
107+
108+
Rust ではなんと、スペースを有しない型を使うことができます。
52109

110+
<!--
53111
```rust
54112
struct Foo; // No fields = no size
55113
@@ -60,61 +118,137 @@ struct Baz {
60118
baz: [u8; 0], // empty array has no size
61119
}
62120
```
121+
-->
63122

123+
```rust
124+
struct Foo; // フィールドがない = サイズ 0
125+
126+
// すべてのフィールドのサイズがない = サイズ 0
127+
struct Baz {
128+
foo: Foo,
129+
qux: (), // empty tuple has no size
130+
baz: [u8; 0], // empty array has no size
131+
}
132+
```
133+
134+
<!--
64135
On their own, Zero Sized Types (ZSTs) are, for obvious reasons, pretty useless.
65136
However as with many curious layout choices in Rust, their potential is realized
66137
in a generic context: Rust largely understands that any operation that produces
67138
or stores a ZST can be reduced to a no-op. First off, storing it doesn't even
68139
make sense -- it doesn't occupy any space. Also there's only one value of that
69140
type, so anything that loads it can just produce it from the aether -- which is
70141
also a no-op since it doesn't occupy any space.
142+
-->
71143

144+
サイズ 0 の型(ZST)は、当然ながら、それ自体ではほとんど価値があありません。
145+
しかし、多くの興味深いレイアウトの選択肢と組み合わせると、ZST が潜在的に役に立つことがいろいろな
146+
ケースで明らかになります。Rust は、ZST を生成したり保存したりするオペレーションが no-op に
147+
還元できることを理解しています。
148+
そもそも、ZST はスペースを要求しないので、保存することには意味がありません。
149+
また ZST は 1 つの値しかとらないので、ZST を読み込む操作は、
150+
代わりに無から ZST を作り出すことができ、この操作もスペースを必要としないので no-op と同じです。
151+
152+
<!--
72153
One of the most extreme example's of this is Sets and Maps. Given a
73154
`Map<Key, Value>`, it is common to implement a `Set<Key>` as just a thin wrapper
74155
around `Map<Key, UselessJunk>`. In many languages, this would necessitate
75156
allocating space for UselessJunk and doing work to store and load UselessJunk
76157
only to discard it. Proving this unnecessary would be a difficult analysis for
77158
the compiler.
159+
-->
160+
161+
究極の ZST の利用法として、Set と Map を考えてみましょう。
162+
`Map<Key, Value>` があるときに、`Set<Key>``Map<Key, UselessJunk>`
163+
簡単なラッパーとして実装することはよくあります。
164+
多くの言語では、UselessJunk のスペースを割り当てる必要があるでしょうし、
165+
結果的に使わない UselessJunk を保存したり読み込んだりする必要もあるでしょう。
166+
こういったことが不要であると示すのはコンパイラにとっては難しい仕事でしょう。
78167

168+
<!--
79169
However in Rust, we can just say that `Set<Key> = Map<Key, ()>`. Now Rust
80170
statically knows that every load and store is useless, and no allocation has any
81171
size. The result is that the monomorphized code is basically a custom
82172
implementation of a HashSet with none of the overhead that HashMap would have to
83173
support values.
174+
-->
84175

176+
しかし Rust では、単に `Set<Key> = Map<Key, ()>` と言えばいいだけなのです。
177+
Rust は静的な解析で、読み込みや保存が無意味であること、メモリ割当が必要ないことを理解します。
178+
結果として単態化したコードは、HashSet のためにカスタマイズされ、
179+
HashMap を使う場合のオーバーヘッドはなくなります。
180+
181+
<!--
85182
Safe code need not worry about ZSTs, but *unsafe* code must be careful about the
86183
consequence of types with no size. In particular, pointer offsets are no-ops,
87184
and standard allocators (including jemalloc, the one used by default in Rust)
88185
may return `nullptr` when a zero-sized allocation is requested, which is
89186
indistinguishable from out of memory.
187+
-->
90188

189+
安全なコードは ZST について心配する必要はありませんが、*危険な* コードは
190+
サイズ 0 の型を使った時の結果について注意しなくてはなりません。
191+
特に、ポインタのオフセットは no-op になることや、
192+
(Rust のデフォルトである jemalloc を含む)標準的なメモリアロケータは、
193+
サイズ 0 の割り当て要求には `nullptr` を返すこと
194+
(これはメモリ不足と区別がつきません)に注意してください。
91195

92-
93-
94-
196+
<!--
95197
# Empty Types
198+
-->
199+
200+
# 空の型
96201

202+
<!--
97203
Rust also enables types to be declared that *cannot even be instantiated*. These
98204
types can only be talked about at the type level, and never at the value level.
99205
Empty types can be declared by specifying an enum with no variants:
206+
-->
207+
208+
Rust では、*インスタンスを生成できない*型を宣言することもできます。
209+
こういう型は、型レベルの話にのみ出てきて、値レベルには出てきません。
210+
空の型は、識別子を持たない enum として宣言できます。
100211

212+
<!--
101213
```rust
102214
enum Void {} // No variants = EMPTY
103215
```
216+
-->
217+
218+
```rust
219+
enum Void {} // 識別子なし = 空
220+
```
104221

222+
<!--
105223
Empty types are even more marginal than ZSTs. The primary motivating example for
106224
Void types is type-level unreachability. For instance, suppose an API needs to
107225
return a Result in general, but a specific case actually is infallible. It's
108226
actually possible to communicate this at the type level by returning a
109227
`Result<T, Void>`. Consumers of the API can confidently unwrap such a Result
110228
knowing that it's *statically impossible* for this value to be an `Err`, as
111229
this would require providing a value of type `Void`.
230+
-->
112231

232+
空の型は、ZST よりもまれにしか使いません。
233+
空の型がもっとも必要になる例としては、型レベルの到達不可能性を示す時です。
234+
例えば、ある API は、一般に Result を返す必要がありますが、
235+
特定のケースでは絶対に失敗しないことがわかっているとします。
236+
`Result<T, Void>` を返すことで、この事実を型レベルで伝えることが可能です。
237+
Void 型の値を提供することはできないので、この Result は Err に*なり得ないと静的にわかります*
238+
そのため、この API の利用者は、自信を持って Result を unwrap することができます。
239+
240+
<!--
113241
In principle, Rust can do some interesting analyses and optimizations based
114242
on this fact. For instance, `Result<T, Void>` could be represented as just `T`,
115243
because the `Err` case doesn't actually exist. The following *could* also
116244
compile:
245+
-->
246+
247+
原理的に、Rust ではこの事実をもとに、興味深い解析と最適化が可能です。
248+
たとえば、`Result<T, Void>``Err` にはなり得ないので、
249+
`T` と表現することができます。以下のコードがコンパイルに通るようにも*できる*でしょう。
117250

251+
<!--
118252
```rust,ignore
119253
enum Void {}
120254
@@ -123,15 +257,37 @@ let res: Result<u32, Void> = Ok(0);
123257
// Err doesn't exist anymore, so Ok is actually irrefutable.
124258
let Ok(num) = res;
125259
```
260+
-->
261+
262+
```rust,ignore
263+
enum Void {}
264+
265+
let res: Result<u32, Void> = Ok(0);
266+
267+
// Err は存在しないので、Ok になることに疑問の余地はありません。
268+
let Ok(num) = res;
269+
```
126270

271+
<!--
127272
But neither of these tricks work today, so all Void types get you is
128273
the ability to be confident that certain situations are statically impossible.
274+
-->
275+
276+
ただし、どちらの例も現時点では動きません。
277+
つまり、Void 型による利点は、静的な解析によて、特定の状況が起こらないと確実に言えることだけです。
129278

279+
<!--
130280
One final subtle detail about empty types is that raw pointers to them are
131281
actually valid to construct, but dereferencing them is Undefined Behavior
132282
because that doesn't actually make sense. That is, you could model C's `void *`
133283
type with `*const Void`, but this doesn't necessarily gain anything over using
134284
e.g. `*const ()`, which *is* safe to randomly dereference.
285+
-->
286+
287+
最後に細かいことを一つ。空の型を指す生のポインタを構成することは有効ですが、
288+
それをデリファレンスすることは、意味がないので、未定義の挙動となります。
289+
つまり、C における `void *` と同じような意味で `*const Void` を使うこと出来ますが、
290+
これは、*安全に*デリファレンスできる型(例えば `*const ()`)と比べて何も利点はありません。
135291

136292

137293
[dst-issue]: https://github.com/rust-lang/rust/issues/26403

0 commit comments

Comments
 (0)