Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update translation of transmute.md with the latest version #70

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 68 additions & 32 deletions src/transmutes.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,72 +7,108 @@
<!--
Get out of our way type system! We're going to reinterpret these bits or die
trying! Even though this book is all about doing things that are unsafe, I
really can't emphasize that you should deeply think about finding Another Way
really can't emphasize enough that you should deeply think about finding Another Way
than the operations covered in this section. This is really, truly, the most
horribly unsafe thing you can do in Rust. The railguards here are dental floss.
horribly unsafe thing you can do in Rust. The guardrails here are dental floss.
-->

型システムから抜け出しましょう! 何がなんでもビットを再解釈します! この本は
アンセーフなもの全てについて書かれていますが、この章でカバーされている操作を
やるよりも、他の方法を見つけるよう深刻に考えるべきだということは、
いくら強調しようとも、強調しきれません。これは本当に、マジで、 Rust で出来る
いくら強調しようとも、十分には強調しきれません。これは本当に、マジで、 Rust で出来る
最も恐ろしいアンセーフなことです。ここではガードレールは爪楊枝のように脆いです。

<!--
`mem::transmute<T, U>` takes a value of type `T` and reinterprets it to have
type `U`. The only restriction is that the `T` and `U` are verified to have the
same size. The ways to cause Undefined Behavior with this are mind boggling.
[`mem::transmute<T, U>`][transmute] takes a value of type `T` and reinterprets
it to have type `U`. The only restriction is that the `T` and `U` are verified
to have the same size. The ways to cause Undefined Behavior with this are mind
boggling.
-->

`mem::transmute<T, U>` は型 `T` の値を受け取り、その値が型 `U` であると再解釈します。
[`mem::transmute<T, U>`][transmute] は型 `T` の値を受け取り、その値が型 `U` であると再解釈します。
唯一の制約は、 `T` と `U` が同じサイズを持つとされていることです。
この操作によって未定義動作が起こる方法を考えると、気が遠くなります。

<!--
* First and foremost, creating an instance of *any* type with an invalid state
is going to cause arbitrary chaos that can't really be predicted.
is going to cause arbitrary chaos that can't really be predicted. Do not
transmute `3` to `bool`. Even if you never *do* anything with the `bool`. Just
don't.

* Transmute has an overloaded return type. If you do not specify the return type
it may produce a surprising type to satisfy inference.
* Making a primitive with an invalid value is UB
* Transmuting between non-repr(C) types is UB
* Transmuting an & to &mut is UB
* Transmuting an & to &mut is *always* UB
* No you can't do it
* No you're not special

* Transmuting an `&` to `&mut` is Undefined Behavior. While certain usages may
*appear* safe, note that the Rust optimizer is free to assume that a shared
reference won't change through its lifetime and thus such transmutation will
run afoul of those assumptions. So:
* Transmuting an `&` to `&mut` is *always* Undefined Behavior.
* No you can't do it.
* No you're not special.

* Transmuting to a reference without an explicitly provided lifetime
produces an [unbounded lifetime]
produces an [unbounded lifetime].

* When transmuting between different compound types, you have to make sure they
are laid out the same way! If layouts differ, the wrong fields are going to
get filled with the wrong data, which will make you unhappy and can also be
Undefined Behavior (see above).

So how do you know if the layouts are the same? For `repr(C)` types and
`repr(transparent)` types, layout is precisely defined. But for your
run-of-the-mill `repr(Rust)`, it is not. Even different instances of the same
generic type can have wildly different layout. `Vec<i32>` and `Vec<u32>`
*might* have their fields in the same order, or they might not. The details of
what exactly is and is not guaranteed for data layout are still being worked
out over [at the UCG WG][ucg-layout].
-->

* まず真っ先に、*いかなる*型においても、無効状態のインスタンスを作ることは、本当に予測不可能な混沌状態を引き起こすでしょう。
`3` を `bool` にトランスミュートしないでください。
たとえその `bool` に対してまったく何も*しない*としてもです。
とにかくやめてください。
* transmute はオーバーロードされたリターン型を持ちます。もしリターン型を指定しなかった場合、
推論を満たす、びっくりするような型を生成するかもしれません。
* 無効なプリミティブを生成することは未定義動作を引き起こします
* repr(C) でない型の間でのトランスミュートは未定義動作を引き起こします
* & から &mut へのトランスミュートは未定義動作を引き起こします。
* & から &mut へのトランスミュートは*いつも*未定義動作を引き起こします。
* いいえ、これは出来ません。
* いいか、君は特別じゃないんだ。
* `&` から `&mut` へのトランスミュートは未定義動作を引き起こします
特定の使い方は安全であるように*見える*かもしれませんが、Rust のオプティマイザは共有参照がそのライフタイムを通して変更されないことを自由に仮定することができることから、このようなトランスミュートはその仮定に抵触することに注意する必要があります
よって、
* `&` から `&mut` へのトランスミュートは*いつも*未定義動作を引き起こします。
* いいえ、これは出来ません。
* いいか、君は特別じゃないんだ。
* 明確にライフタイムが指定されていない参照へのトランスミュートは[無制限のライフタイム]を生成します。
* 異なる複合型の間でトランスミュートを行う場合、それらが同じように配置されていることを確かめる必要があります!
もしレイアウトが異なっているなら、間違ったフィールドが間違ったデータによって埋められることとなり、あなたを不幸にさせ、未定義動作を引き起こす可能性もあります(上記を見てください)。

それでは、レイアウトが同じかどうかはどのように分かるのでしょうか?
`repr(C)` 型と `repr(transparent)` 型については、レイアウトは正確に定義されています。
しかし、ありふれた `repr(Rust)` についてはそうではありません。
同じジェネリック型の異なるインスタンスさえもまったく異なるレイアウトを持ちえます。
`Vec<i32>` と `Vec<u32>` はフィールドを同じ順序で持つ*かもしれません*し、そうならないかもしれません。
データレイアウトに関して、何が正確に保証されていて、何が保証されていないかについての詳細な説明は、まだ[UCG WG][ucg-layout]で作業が進められています。

<!--
`mem::transmute_copy<T, U>` somehow manages to be *even more* wildly unsafe than
this. It copies `size_of<U>` bytes out of an `&T` and interprets them as a `U`.
The size check that `mem::transmute` has is gone (as it may be valid to copy
out a prefix), though it is Undefined Behavior for `U` to be larger than `T`.
[`mem::transmute_copy<T, U>`][transmute_copy] somehow manages to be *even more*
wildly unsafe than this. It copies `size_of<U>` bytes out of an `&T` and
interprets them as a `U`. The size check that `mem::transmute` has is gone (as
it may be valid to copy out a prefix), though it is Undefined Behavior for `U`
to be larger than `T`.
-->

`mem::transmute_copy<T, U>` は、どうにかして transmute よりも*本当に更に*アンセーフな事をしようとします。
[`mem::transmute_copy<T, U>`][transmute_copy] は、どうにかして transmute よりも*本当に更に*アンセーフな事をしようとします。
この関数は `&T` から `size_of<U>` バイトコピーし、これらを `U` として解釈します。
もし `U` が `T` よりも大きい場合、未定義動作を引き起こしますが、 `mem::transmute` の
サイズチェックはなくなっています ( `T` の先頭部分をコピーすることが有効である場合があるためです) 。

<!--
Also of course you can get most of the functionality of these functions using
pointer casts.
Also of course you can get all of the functionality of these functions using raw
pointer casts or `union`s, but without any of the lints or other basic sanity
checks. Raw pointer casts and `union`s do not magically avoid the above rules.
-->

そしてもちろん、これらの関数の機能のほとんどを、ポインタのキャストを利用することで
得ることができます。

そしてもちろん、これらの関数の機能のすべてを、生ポインタのキャストまたは `union` を利用することで得ることができますが、そこには lint やその他の基本的な健全性チェックは一切ありません。
生ポインタのキャストや `union` は、上で述べたルールを魔法のように回避してくれるわけではありません。

[無制限のライフタイム]: unbounded-lifetimes.html
[無制限のライフタイム]: ./unbounded-lifetimes.md
[transmute]: ../std/mem/fn.transmute.html
[transmute_copy]: ../std/mem/fn.transmute_copy.html
[ucg-layout]: https://rust-lang.github.io/unsafe-code-guidelines/layout.html