1+ <!--
12# Exotically Sized Types
3+ -->
24
5+ # 奇妙なサイズの型
6+
7+ <!--
38Most of the time, we think in terms of types with a fixed, positive size. This
49is 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+ <!--
1222Rust in fact supports Dynamically Sized Types (DSTs): types without a statically
1323known size or alignment. On the surface, this is a bit nonsensical: Rust *must*
1424know 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
1828information that "completes" them (more on this below).
1929
2030There 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+ <!--
2245A trait object represents some type that implements the traits it specifies.
2346The exact original type is *erased* in favor of runtime reflection
2447with a vtable containing all the information necessary to use the type.
2548This 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+ <!--
2756A 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
2958it points to.
59+ -->
3060
61+ スライスとは、単純にある連続したスペース(通常はアレイか ` Vec ` )のビューです。
62+ スライスを補完する情報とは、単にポインタが指すエレメントの数です。
63+
64+ <!--
3165Structs can actually store a single DST directly as their last field, but this
3266makes them a DST as well:
67+ -->
68+
69+ 構造体は、最後のフィールドとして DST を直接含むことができますが、その構造体自体も DST になります。
3370
71+ <!--
3472```rust
3573// Can't be stored on the stack directly
3674struct 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
4391a 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
51105Rust actually allows types to be specified that occupy no space:
106+ -->
107+
108+ Rust ではなんと、スペースを有しない型を使うことができます。
52109
110+ <!--
53111```rust
54112struct 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+ <!--
64135On their own, Zero Sized Types (ZSTs) are, for obvious reasons, pretty useless.
65136However as with many curious layout choices in Rust, their potential is realized
66137in a generic context: Rust largely understands that any operation that produces
67138or stores a ZST can be reduced to a no-op. First off, storing it doesn't even
68139make sense -- it doesn't occupy any space. Also there's only one value of that
69140type, so anything that loads it can just produce it from the aether -- which is
70141also 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+ <!--
72153One 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
74155around `Map<Key, UselessJunk>`. In many languages, this would necessitate
75156allocating space for UselessJunk and doing work to store and load UselessJunk
76157only to discard it. Proving this unnecessary would be a difficult analysis for
77158the compiler.
159+ -->
160+
161+ 究極の ZST の利用法として、Set と Map を考えてみましょう。
162+ ` Map<Key, Value> ` があるときに、` Set<Key> ` を ` Map<Key, UselessJunk> ` の
163+ 簡単なラッパーとして実装することはよくあります。
164+ 多くの言語では、UselessJunk のスペースを割り当てる必要があるでしょうし、
165+ 結果的に使わない UselessJunk を保存したり読み込んだりする必要もあるでしょう。
166+ こういったことが不要であると示すのはコンパイラにとっては難しい仕事でしょう。
78167
168+ <!--
79169However in Rust, we can just say that `Set<Key> = Map<Key, ()>`. Now Rust
80170statically knows that every load and store is useless, and no allocation has any
81171size. The result is that the monomorphized code is basically a custom
82172implementation of a HashSet with none of the overhead that HashMap would have to
83173support values.
174+ -->
84175
176+ しかし Rust では、単に ` Set<Key> = Map<Key, ()> ` と言えばいいだけなのです。
177+ Rust は静的な解析で、読み込みや保存が無意味であること、メモリ割当が必要ないことを理解します。
178+ 結果として単態化したコードは、HashSet のためにカスタマイズされ、
179+ HashMap を使う場合のオーバーヘッドはなくなります。
180+
181+ <!--
85182Safe code need not worry about ZSTs, but *unsafe* code must be careful about the
86183consequence of types with no size. In particular, pointer offsets are no-ops,
87184and standard allocators (including jemalloc, the one used by default in Rust)
88185may return `nullptr` when a zero-sized allocation is requested, which is
89186indistinguishable 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+ <!--
97203Rust also enables types to be declared that *cannot even be instantiated*. These
98204types can only be talked about at the type level, and never at the value level.
99205Empty types can be declared by specifying an enum with no variants:
206+ -->
207+
208+ Rust では、* インスタンスを生成できない* 型を宣言することもできます。
209+ こういう型は、型レベルの話にのみ出てきて、値レベルには出てきません。
210+ 空の型は、識別子を持たない enum として宣言できます。
100211
212+ <!--
101213```rust
102214enum Void {} // No variants = EMPTY
103215```
216+ -->
217+
218+ ``` rust
219+ enum Void {} // 識別子なし = 空
220+ ```
104221
222+ <!--
105223Empty types are even more marginal than ZSTs. The primary motivating example for
106224Void types is type-level unreachability. For instance, suppose an API needs to
107225return a Result in general, but a specific case actually is infallible. It's
108226actually 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
110228knowing that it's *statically impossible* for this value to be an `Err`, as
111229this 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+ <!--
113241In principle, Rust can do some interesting analyses and optimizations based
114242on this fact. For instance, `Result<T, Void>` could be represented as just `T`,
115243because the `Err` case doesn't actually exist. The following *could* also
116244compile:
245+ -->
246+
247+ 原理的に、Rust ではこの事実をもとに、興味深い解析と最適化が可能です。
248+ たとえば、` Result<T, Void> ` は ` Err ` にはなり得ないので、
249+ ` T ` と表現することができます。以下のコードがコンパイルに通るようにも* できる* でしょう。
117250
251+ <!--
118252```rust,ignore
119253enum Void {}
120254
@@ -123,15 +257,37 @@ let res: Result<u32, Void> = Ok(0);
123257// Err doesn't exist anymore, so Ok is actually irrefutable.
124258let 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+ <!--
127272But neither of these tricks work today, so all Void types get you is
128273the ability to be confident that certain situations are statically impossible.
274+ -->
275+
276+ ただし、どちらの例も現時点では動きません。
277+ つまり、Void 型による利点は、静的な解析によて、特定の状況が起こらないと確実に言えることだけです。
129278
279+ <!--
130280One final subtle detail about empty types is that raw pointers to them are
131281actually valid to construct, but dereferencing them is Undefined Behavior
132282because that doesn't actually make sense. That is, you could model C's `void *`
133283type with `*const Void`, but this doesn't necessarily gain anything over using
134284e.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