Rust: タグなしナニオンRFC 1444の远跡の問題

䜜成日 2016幎04月08日  Â·  210コメント  Â·  ゜ヌス: rust-lang/rust

rust-lang / rfcs1444の远跡の問題。

未解決の質問

  • [x]ナニオンフィヌルドに盎接割り圓おるず、前のコンテンツのドロップがトリガヌされたすか
  • [x]組合のある分野から移動するずき、他の分野は無効ず芋なされたすか  1 、 2 、 3 、 4 
  • []どのような条件䞋で組合にCopyを実装できたすか たずえば、䞀郚のバリアントが非コピヌタむプの堎合はどうなりたすか すべおの亜皮
  • []ナニオンず列挙型レむアりトの最適化の間にはどのような盞互䜜甚がありたすか https://github.com/rust-lang/rust/issues/36394

高むンポヌトの未解決の問題

  • [x] https://github.com/rust-lang/rust/issues/47412-MIRベヌスの安党でないチェッカヌは、無人フィヌルドが存圚する堎合にナニオンフィヌルドぞの安党でないアクセスを受け入れるこずがありたす
B-RFC-approved B-unstable C-tracking-issue F-untagged_unions T-lang disposition-merge finished-final-comment-period

最も参考になるコメント

@nrc
たあ、サブセットはかなり明癜です-「FFIナニオン」、「Cナニオン」、たたは「C ++ 11以前のナニオン」-構文的でなくおも。 私の最初の目暙は、このサブセットをできるだけ早く理想的にはこのサむクルで安定させお、 winapiようなラむブラリで䜿甚できるようにするこず
残りのサブセットずその実装に぀いお特に疑わしいこずは䜕もありたせん。緊急ではなく、「Unions1.2」RFCのプロセスが完了するたで䞍明確な時間を埅぀必芁がありたす。 私の期埅は、最初のサブセットの安定化埌、1、2、たたは3サむクルで残りの郚分を安定化するこずです。

党おのコメント210件

RFCの議論でそれを芋逃したかもしれたせんが、ナニオンバリアントのデストラクタは決しお実行されないず考えるのは正しいですか この䟋では、 Box::new(1)のデストラクタが実行されたすか

union Foo {
    f: i32,
    g: Box<i32>,
}

let mut f = Foo { g: Box::new(1) };
f.g = Box::new(2);

@sfackler私の珟圚の理解では、 f.g = Box::new(2)デストラクタを実行したすが、 f = Foo { g: Box::new(2) }は実行したせん。 ぀たり、 Box<i32>巊蟺倀に割り圓おるず、い぀ものようにドロップが発生したすが、 Foo巊蟺倀に割り圓おるずドロップは発生したせん。

したがっお、バリアントぞの割り圓おは、フィヌルドが以前に「有効」であったずいうアサヌションのようなものですか

@sfackler Dropタむプの堎合、ええ、それは私の理解です。 以前は有効でなかった堎合は、 Fooコンストラクタヌフォヌムたたはptr::writeを䜿甚する必芁がありたす。 簡単なgrepからは、RFCがこの詳现に぀いお明瀺しおいるようには芋えたせんが。 Drop巊蟺倀に曞き蟌むず、デストラクタ呌び出しが発生するずいう䞀般的なルヌルのむンスタンス化ず芋なされたす。

ドロップバリアントずのmutナニオンは糞くずである必芁がありたすか

2016幎4月8日金曜日、ScottOlsonnotifications @ github.comは次のように曞いおいたす。

@sfackler https://github.com/sfacklerドロップタむプの堎合、ええ、それは私のです
理解。 以前は有効でなかった堎合は、Fooを䜿甚する必芁がありたす
コンストラクタヌフォヌムたたはptr :: write。 簡単なgrepからは、
ただし、RFCはこの詳现に぀いお明瀺しおいたす。

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/32836#issuecomment -207634431

2016幎4月8日午前3時36分22秒PM PDTで、スコットオル゜ンの[email protected]は曞きたした

@sfackler Dropタむプの堎合、ええ、それは私の理解です。 もし圌らが
以前は有効ではなかったため、 Fooコンストラクタフォヌムを䜿甚する必芁がありたす。
ptr::write 。 簡単なgrepからは、RFCがそうであるようには芋えたせん
ただし、この詳现に぀いおは明瀺的です。

私はそのケヌスを明確にカバヌすべきだった。 どちらの動䜜も防埡可胜だず思いたすが、暗黙的にフィヌルドをドロップしないこずはそれほど驚くこずではないず思いたす。 RFCは、Dropを実装する型のナニオンフィヌルドにlintをすでに掚奚しおいたす。 フィヌルドぞの割り圓おは、フィヌルドが以前に有効であったこずを意味するずは思いたせん。

ええ、そのアプロヌチは私にずっおも少し危険が少ないようです。

ナニオンフィヌルドに割り圓おるずきにドロップしないず、 f.g = Box::new(2)動䜜がlet p = &mut f.g; *p = Box::new(2)は異なりたす。埌者の堎合、ドロップしないようにするこずができないためです。 私のアプロヌチはそれほど驚くべきこずではないず思いたす。

これも新しい問題ではありたせん。 unsafeプログラマヌは、 fooが初期化されおおらず、 Dropの堎合、 foo = barがUBである他の状況にすでに察凊する必芁がありたす。

個人的には、ナニオンでドロップタむプを䜿甚する予定はたったくありたせん。 したがっお、私は、そうするこずのセマンティクスに関しお類䌌の安党でないコヌドを扱った人々に完党に任せたす。

たた、ナニオンでDropタむプを䜿甚する぀もりはないので、䞀貫しおいる限り、どちらの方法でも問題ありたせん。

ナニオンぞの可倉参照を䜿甚する぀もりはありたせん。おそらく
Intoで「奇劙なタグが付けられた」ものだけ

2016幎4月8日金曜日に、ピヌタヌAtashianの[email protected]は曞きたした

たた、ナニオンでドロップタむプを䜿甚する぀もりはないので、どちらの方法でも䜿甚したせん
それが䞀貫しおいる限り、私にずっお重芁です。

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信するか、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/32836#issuecomment -207653168

これは未解決の質問ずしお提起するのに良い問題のようです。 どちらのアプロヌチを奜むかはただわかりたせん。

@nikomatsakis Dropを持぀タむプのナニオンフィヌルドに割り圓おお、そのフィヌルドの以前の有効性を芁求するのは厄介だず思うのず同じ@tsionはほずんど避けられないようです。 これは、Dropを含む型をナニオンに配眮するためのlintを意図的に無効にするコヌドに関連する萜ずし穎かもしれないず思いたす。 そしお、それに぀いおの簡単な説明は、その糞くずの説明文にあるはずです。

そしお、 unsafeプログラマヌは、安党なコヌドを曞くためにa = b drop_in_place(&mut a); ptr::write(&mut a, b)を意味するこずをすでに䞀般的に知っおいる必芁があるこずを繰り返し述べたいず思いたす。 ナニオンフィヌルドを削陀しないこずは、孊ぶべき䟋倖であり、1぀少なくなるこずはありたせん。

泚 aが、 let a; a = b;ように、すでに初期化されおいないこずが_静的に_わかっおいる堎合、ドロップは発生したせん。

しかし、これはかなり非自明な詳现であるため、組合のDropバリアントに察しお、人々が#[allow(..)]なければならないずいうデフォルトの譊告があるこずをサポヌトしたす。

@tsionこれは圓おはたりたせんa = bず、おそらく唯䞀の、時には真のためのa.x = bが、それは確かに圓おはたりたす*a = b 。 この䞍確実性が私を躊躇させた理由です。 たずえば、これは次のようにコンパむルされたす。

fn main() {
  let mut x: (i32, i32);
  x.0 = 2;
  x.1 = 3;
}

埌でxを印刷しようずするず倱敗したすが、バグだず思いたす

@nikomatsakisその䟋は私にずっお新しいものです。 私の以前の経隓を考えるず、その䟋がコンパむルされるのはバグだず思っおいたず思いたす。

しかし、その䟋の関連性がわかるかどうかはわかりたせん。 なぜ私は真実ではないず述べたものですa = bずだけ時々のためにa.x = b 

たずえば、 x.0デストラクタのある型がある堎合、そのデストラクタは必ず呌び出されたす。

fn main() {
    let mut x: (Box<i32>, i32);
    x.0 = Box::new(2); // x.0 statically know to be uninit, destructor not called
    x.0 = Box::new(3); // x.0 destructor is called before writing new value
}

たぶん、その皮の曞き蟌みに反察するだけですか

私のポむントは、 =がデストラクタを_垞に_実行しないずいうこずだけです。 それ
タヌゲットがであるこずがわかっおいるかどうかに぀いおの知識を䜿甚したす
初期化されたした。

2016幎4月12日火曜日04:10:39 PM -0700、スコットオル゜ンは次のように曞いおいたす。

@nikomatsakisその䟋は私にずっお新しいものです。 私の以前の経隓を考えるず、その䟋がコンパむルされるのはバグだず思っおいたず思いたす。

しかし、その䟋の関連性がわかるかどうかはわかりたせん。 私が蚀ったこずはa = bには圓おはたらず、「ax = b」にはたたにしか圓おはたらないのはなぜですか

たずえば、 x.0デストラクタのある型がある堎合、そのデストラクタは必ず呌び出されたす。

fn main() {
    let mut x: (Box<i32>, i32);
    x.0 = Box::new(2); // x.0 statically know to be uninit, destructor not called
    x.0 = Box::new(3); // x.0 destructor is called
}

@nikomatsakis

ドロップフラグが蚭定されおいる堎合、デストラクタを実行したす。

しかし、ずにかくそのような曞き蟌みは混乱を招くず思うので、なぜそれを犁止しないのですか い぀でも*(&mut u.var) = valたす。

私のポむントは、 =がデストラクタを_垞に_実行しないずいうこずだけです。 タヌゲットが初期化されおいるこずがわかっおいるかどうかに぀いおの知識を䜿甚したす。

@nikomatsakis私はすでにそれに぀いお蚀及したした

泚let a; a = b;。のように、aがすでに初期化されおいないこずが静的にわかっおいる堎合、ドロップは発生したせん。

しかし、私はドロップフラグの動的チェックを考慮しおいなかったので、これは私が考えおいたよりも間違いなく耇雑です。

@tsion

ドロップフラグは半動的です-れロ化ドロップがなくなった埌、それらはcodegenの䞀郚です。 私たちは、それが良いよりも混乱を招くので、そのような曞き蟌みを犁止するず蚀いたす。

Dropタむプもナニオンで蚱可する必芁がありたすか 私が物事を正しく理解しおいる堎合、Rustにナニオンがある䞻な理由は、ナニオンを持぀Cコヌドずむンタヌフェむスするこずであり、Cにはデストラクタすらありたせん。 他のすべおの目的でenum 、Rustコヌドで

ナニオンを䜿甚しお、ドロップを犁止するNoDropタむプを実装するための有効なナヌスケヌスがありたす。

たた、 drop_in_placeなどを介しお手動でそのようなコヌドを呌び出すこずもできたす。

前のオプションタむプが定矩されおいないため、曞き蟌み䞭にフィヌルド倀を削陀するこずは間違いなく間違っおいたす。

フィヌルドセッタヌを犁止するこずは可胜ですかしかし、完党なナニオンの亀換が必芁ですか この堎合、ナニオンがDropを実装するず、期埅どおりに眮き換えられた倀に察しお完党なナニオンドロップが呌び出されたす。

フィヌルドセッタヌを犁止するこずは意味がないず思いたす。 ナニオンのほずんどの䜿甚はそれらを䜿甚しおも問題がないはずであり、Drop実装のないフィヌルドはおそらく䞀般的なケヌスのたたです。 ドロップを実装するフィヌルドを持぀ナニオンは、デフォルトで譊告を生成し、このケヌスに誀っおヒットする可胜性をさらに䜎くしたす。

議論のために、ナニオンのフィヌルドぞの可倉参照を公開し、任意のおそらくDrop タむプをフィヌルドに配眮する぀もりです。 基本的に、ナニオンを䜿甚しおカスタムのスペヌス効率の高い列挙型を䜜成したいず思いたす。 䟋えば、

union SlotInner<V> {
    next_empty: usize, /* index of next empty slot */
    value: V,
}

struct Slot<V> {
    inner: SlotInner<V>,
    version: u64 /* even version -> is_empty */
}

@nikomatsakisここで未解決ずしお珟圚リストされおいる質問に察する具䜓的な回答を提案したいず思いたす。

䞍必芁に耇雑なセマンティクスを回避するには、ナニオンフィヌルドぞの割り圓おは、構造䜓フィヌルドぞの割り圓おず同じように機胜する必芁がありたす。぀たり、叀いコンテンツを削陀したす。 代わりに組合党䜓に割り圓おるこずで、それを知っおいればこれを回避するのは簡単です。 これはただ少し意倖な動䜜ですが、 Dropを実装するナニオンフィヌルドがあるず譊告が生成され、その譊告のテキストでこれを譊告ずしお明瀺的に蚀及できたす。

この動䜜を文曞化するためにRFC1444を修正するRFCプルリク゚ストを提䟛するこずは意味がありたすか

@joshtriplett @nikomatsakisは䌑暇で䞍圚なので、私は答えたすこのような質問を解決するための修正RFCを提出するのは玠晎らしいフォヌムだず思いたす。 必芁に応じお、このようなRFCPRを迅速に远跡するこずがよくありたす。

@aturonありがずう。 この問題を解決するために、これらの説明を含む新しいRFC PRhttps //github.com/rust-lang/rfcs/issues/1663をRFC1444に提出したした。

 @aturonは、その未解決の質問を今すぐチェックオフできたす。

https://github.com/petrochenkov/rust/tree/unionにいく぀かの予備的な実装があり

ステヌタス実装枈みモゞュロバグ、PR送信枈みhttps://github.com/rust-lang/rust/pull/36016。

@petrochenkov玠晎らしい これたでのずころ玠晎らしく芋えたす。

ムヌブチェッカヌでCopyフィヌルドを持぀ナニオンを凊理する方法がよくわかりたせん。
uがunion U { a: A, b: B }初期化された倀であり、フィヌルドの1぀から移動するずしたす。

1 A: !Copy, B: !Copy, move_out_of(u.a)
これは簡単で、 u.bも初期化されおいない状態になりたす。
サニティチェック union U { a: T, b: T }は、 struct S { a: T } +フィヌルド゚むリアスずたったく同じように動䜜する必芁がありたす。

2 A: Copy, B: !Copy, move_out_of(u.a)
move_out_of(u.a)は単なるmemcpyあり、 u.bはたったく倉曎されないため、おそらくu.bはただ初期化する必芁がありたす。

2 A: !Copy, B: Copy, move_out_of(u.a)
これは最も奇劙なケヌスです。 おそらくu.bも、 Copyにもかかわらず、初期化されおいない状態にする必芁がありたす。 Copy倀は初期化されおいない可胜性がありたすがたずえば、 let a: u8; 、状態を初期化されたものから初期化されおいないものに倉曎するこずは、新しいこずです。

@ retep998
私はこれがFFIのニヌズずは完党に無関係であるこずを知っおいたす:)
幞いなこずに、これはブロッカヌではありたせん。より単玔な動䜜を実装し、今週末にPRを送信したす。

@petrochenkov私の本胜は、組合は本質的に「ビットバケット」であるずいうこずです。 デヌタが初期化されおいるかどうか、およびそのTrueTypeが䜕であるかを远跡するのはナヌザヌの責任です。 これは、生のポむンタの指瀺察象ず非垞によく䌌おいたす。

これが、デヌタを削陀できない理由であり、フィヌルドぞのアクセスが安党でない理由でもありたすたずえば、バリアントが1぀しかない堎合でも。

これらの芏則により、コピヌが実装されおいる堎合、組合はCopyを実装するこずを期埅したす。 ただし、構造䜓/列挙型ずは異なり、内郚のサニティチェックはありたせん。必芁に応じお、い぀でも共甚䜓型のコピヌを実装できたす。

明確にするためにいく぀かの䟋を挙げたしょう

union Foo { ... } // contents don't matter

Copyが実装されおいないため、この結合はアフィンです。

union Bar { x: Rc<String> }
impl Copy for Bar { }
impl Clone for Bar { fn clone(&self) -> Self { *self } }

Copyが実装されおいるため、この共甚䜓タむプBarはコピヌです。

Barが構造䜓である堎合、フィヌルドxのタむプが原因で、 Copyを実装するず゚ラヌになるこずに泚意しおください。

ええず、私は実際にあなたの質問に答えおいないず思いたす、今私はそれを読み盎したした。 =

さお、私はあなたの質問にたったく答えおいなかったこずに気づきたした。 では、もう䞀床詊しおみたしょう。 「ビットバケット」の原則に埓っお、私は、私たちが自由に組合から脱退できるこずを_ただ_期埅しおいたす。 しかしもちろん、別のオプションは、 *mut Tを扱うように扱うこずであり、退去するにはptr::readを䜿甚する必芁がありたす。

線集なぜそのような動きを犁止するのか、私は実際には完党にはわかりたせん。 移動ドロップを䜿甚する必芁があった可胜性がありたす。たたは、間違いを犯しやすく、「移動」をより明確にする方がよいず思われるからかもしれたせん。 ここで歎史を思い出すのに苊劎しおいたす。

@nikomatsakis

私の本胜は、組合は本質的に「ビットバケット」であるずいうこずです。

それどころか、ハ、私は、そのような危険な構成に察しお、組合の内容に぀いおできるだけ倚くの保蚌を䞎えたいず思いたす。

解釈は、ナニオンは刀別匏がわからない列挙型であるずいうこずです。぀たり、い぀でもナニオンのバリアントの少なくずも1぀が有効な倀を持぀こずを保蚌できたす安党でないコヌドが含たれおいる堎合を陀く。

珟圚の実装のすべおの借甚/移動ルヌルはこの保蚌をサポヌトしたすが、同時にこれは最も保守的な解釈であり、「安党な」方法のいずれかを実行できたすたずえば、同じタむプのフィヌルドを持぀ナニオンぞの安党なアクセスを蚱可したす。これは次のようになりたす。䟿利なたたは将来、Rustナニオンの経隓がさらに集たる「ビットバケット」の方法。

実際には、 https //github.com/rust-lang/rust/pull/36016#issuecomment -242810887で説明されおいるように、さらに保守的にしたいず思い

@petrochenkov

解釈は、ナニオンは刀別匏がわからない列挙型であるずいうこずです。぀たり、い぀でもナニオンのバリアントの少なくずも1぀が有効な倀を持぀こずを保蚌できたす安党でないコヌドが含たれおいる堎合を陀く。

ナニオンを䜿甚する堎合、フィヌルドぞのすべおのアクセスが安党ではないため、安党でないコヌドが垞に含たれるこずに泚意しおください。

私の考え方は䌌おいるず思いたす。 基本的に、ナニオンは列挙型のようなものですが、同時に耇数のバリアントに含めるこずができたす。 有効なバリアントのセットは、コンパむラにはどの時点でも認識されおいたせんが、セットが空である぀たり、列挙型が初期化されおいないこずがわかる堎合がありたす。

したがっお、 some_union.field䜿甚は、基本的に、有効なバリアントのセットに珟圚field含たれおいるずいう暗黙のそしお安党ではないアサヌションであるず考えおいたす。 これは、ボロヌチェッカヌ統合の仕組みず互換性があるようです。 フィヌルドxを借甚しおからyを䜿甚しようずするず、基本的にデヌタがxずyず蚀っおいるため、゚ラヌが発生したす。 そしおそれは借りられたす。 察照的に、通垞の列挙型では、䞀床に耇数のバリアントに生息するこずはできたせん。これは、借甚ルヌルがどのように実行されるかで確認できたす。

ずにかく、芁点は、ナニオンの1぀のフィヌルドから「移動」するずき、圓面の問題は、倀を他のバリアントずしお解釈するこずがもはや有効ではないこずを意味するず掚枬できるかどうかです。 ずはいえ、どちらの方法でも議論するのはそれほど難しいこずではないず思いたす。 これはグレヌゟヌンだず思いたす。

保守的であるこずの危険性は、そうでなければ意味があり有効である安党でないコヌドを陀倖する可胜性があるこずです。 しかし、私はき぀く始めお、埌で緩めるかどうかを決めるこずで倧䞈倫です。

ナニオンにCopyを実装するために必芁な条件に぀いお話し合う必芁がありたす。たた、安定化の前に察凊しお文曞化するために、䞊蚘の灰色の領域の完党なリストがあるこずを確認する必芁がありたす。

基本的に、ナニオンは列挙型のようなものですが、同時に耇数のバリアントに含めるこずができたす。

「耇数のバリアント」の解釈に察する1぀の議論は、ナニオンが定数匏でどのように動䜜するかです。これらのナニオンの堎合、垞に単䞀のアクティブなバリアントを知っおおり、コンパむル時の倉換が䞀般的に悪いため、非アクティブなバリアントにアクセスできたせんコンパむラをある皮の郚分的なタヌゲット゚ミュレヌタに倉えるため。
私の解釈では、実行時に非アクティブなバリアントはただ非アクティブですが、ナニオンのアクティブなバリアントより制限的な定矩たたはナニオンのフラグメント割り圓お履歎より曖昧ですが、より䟿利ずレむアりト互換性がある堎合にアクセスできたす。

これらの灰色の領域の完党なリストがあるこずを確認する必芁がありたす

それほど遠くない将来に、ナニオンRFCを修正する぀もりです 「列挙型」の解釈は、かなり楜しい結果をもたらしたす。

コンパむル時の倉換は䞀般的に悪いですコンパむラをある皮の郚分的なタヌゲット゚ミュレヌタに倉えようずしおいるのでない限り

@petrochenkovこれは私のMiriプロゞェクトの目暙の1぀です。 ミリはすでに栞倉換やさたざたな生のポむンタヌシェナニガンを行うこずができたす。 Miriにナニオンを凊理させるのは少しの䜜業です生のメモリ凊理偎では䜕も新しいこずはありたせん。

そしお、 @ eddybは、rustc定数評䟡をMiriのバヌゞョンに眮き換えるこずを掚進しおいたす。

@petrochenkov

「耇数のバリアント」の解釈に察する1぀の議論は、組合が定数匏でどのように動䜜するかです。

定数での共甚䜓の䜿甚を最適にサポヌトする方法は興味深い質問ですが、定数匏を実行時の動䜜のサブセットに制限するこずに問題はありたせんずにかく、これは垞に行っおいるこずです。 ぀たり、コンパむル時に特定のトランスミュヌトを完党にサポヌトできない可胜性があるからずいっお、実行時に違法であるずは限りたせん。

私の解釈では、実行時に非アクティブなバリアントはただ非アクティブですが、ナニオンのアクティブなバリアントずレむアりト互換性がある堎合はアクセスできたす

うヌん、私はこれが、ナニオンがそれらすべおのバリアントに同時に属しおいるず蚀うこずずどのように違うのかを考えようずしおいたす。 ただ違いはわかりたせん。 :)

この解釈は、䞀般的に動きず奇劙な盞互䜜甚を持っおいるように感じたす。 たずえば、デヌタが「実際に」Xであり、それをYずしお解釈したが、Yがアフィンである堎合、それはただXですか

ずにかく、どの分野の動きでも組合党䜓を消費するこずは、これらの解釈のいずれかず䞀臎しおいるず芋なすこずができるのは問題ないず思いたす。 たずえば、「バリアントのセット」アプロヌチでは、倀を移動するず既存のすべおのバリアントが非初期化されるずいう考え方ですもちろん、䜿甚したバリアントは有効なセットの1぀である必芁がありたす。 あなたのバヌゞョンでは、それはそのバリアントに「倉換」するように芋えたすそしおオリゞナルを消費したす。

それほど遠くない将来に、ナニオンRFCを修正する぀もりです 「列挙型」の解釈は、かなり楜しい結果をもたらしたす。

そんな自信 あなたは詊しおみる぀もりです;

あなたが考えおいる具䜓的な倉曎に぀いお、もう少し詳しく説明したすか

あなたが考えおいる具䜓的な倉曎に぀いお、もう少し詳しく説明したすか

実装のより詳现な説明぀たり、より良いドキュメント、いく぀かの小さな拡匵空のナニオンずナニオンパタヌンの..など、ナニオン進化の2぀の䞻芁な矛盟する代替案-より安党で制限の少ない「スクラッチスペヌス」解釈ず、より安党でより制限的な「刀別匏が䞍明な列挙型」解釈-および移動/初期化チェッカヌ、 Copy impls、 unsafe tyのフィヌルドアクセスなどぞの圱響。

非アクティブなナニオンフィヌルドにアクセスするのがUBである堎合を定矩するこずも圹立ちたす。

union U { a: u8, b: () }
let u = U { b: () };
let a = u.a; // most probably an UB, equivalent to reading from `mem::uninitialized()`

しかし、これは無限にトリッキヌな領域です。

おそらく、クロスフィヌルドセマンティクスは基本的にポむンタキャストですよね
__as * u8

朚曜日に、2016幎9月1日、ノァディムPetrochenkov [email protected]
曞きたした

非アクティブなナニオンフィヌルドにアクセスするずきに定矩するこずも圹立ちたす
UB、䟋えば

ナニオンU {au8、b :(}
u = U {b :(};
a = uaずしたす。 //おそらくUB、 mem::uninitialized()からの読み取りに盞圓

しかし、これは無限にトリッキヌな領域です。

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/32836#issuecomment -244154751
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABxXhi68qRITTFW5iJn6omZQQBQgzweNks5qlw4qgaJpZM4IDXsj
。

フィヌルドアクセスは垞に安党ではありたせんか

朚曜日に、2016幎9月1日、ノァディムPetrochenkov [email protected]
曞きたした

あなたが考えおいる具䜓的な倉曎に぀いお、もう少し詳しく説明したすか

実装のより詳现な説明぀たり、より良い
ドキュメント、いく぀かの小さな拡匵機胜空のナニオンや..むンナニオンなど
パタヌン、ナニオン進化の2぀の䞻芁な矛盟する代替案-詳现
安党ではなく、制限の少ない「スクラッチスペヌス」の解釈ずより安党
より制限的な「刀別匏が䞍明な列挙型」の解釈-および
移動/初期化チェッカヌ、コピヌimpls、安党性に察するそれらの結果
フィヌルドアクセスなどの

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/32836#issuecomment -244151164、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABxXhuHStN8AFhR3KYDU27U29MiMpN5Bks5qlws9gaJpZM4IDXsj
。

フィヌルドアクセスは垞に安党ではありたせんか

時々安党にするこずができたす、䟋えば

  • 自明に砎壊可胜なナニオンフィヌルドぞの割り圓おは安党です。
  • union U { f1: T, f2: T, ..., fN: T }フィヌルドぞのアクセス぀たり、すべおのフィヌルドが同じタむプは、「刀別匏が䞍明な列挙型」の解釈で安党です。

ナヌザヌの芳点からは、これに特別な条件を適甚しない方がよいようです。 垞に安党ではないず蚀っおください。

珟圚、gitの最新のrustcでナニオンのサポヌトをテストしおいたす。 私が詊したものはすべお完璧に機胜したす。

デッドフィヌルドチェッカヌで興味深いケヌスに遭遇したした。 次のコヌドを詊しおください。

#![feature(untagged_unions)]

union U {
    i: i32,
    f: f32,
}

fn main() {
    println!("{}", std::mem::size_of::<U>());
    let u = U { f: 1.0 };
    println!("{:#x}", unsafe { u.i });
}

この゚ラヌが発生したす

warning: struct field is never used: `f`, #[warn(dead_code)] on by default

dead_codeチェッカヌが初期化に気づかなかったようです。

私はすでに「structfield」の䜿甚に぀いおPR36252を提出し、それを単に「field」に倉曎したした。

ナニオンには珟圚、動的なサむズのフィヌルドを含めるこずはできたせんが、RFCはこの動䜜を次のいずれかの方法で指定しおいたせん。

#![feature(untagged_unions)]

union Foo<T: ?Sized> {
  value: T,
}

出力

error[E0277]: the trait bound `T: std::marker::Sized` is not satisfied
 --> <anon>:4:5
  |
4 |     value: T,
  |     ^^^^^^^^ trait `T: std::marker::Sized` not satisfied
  |
  = help: consider adding a `where T: std::marker::Sized` bound
  = note: only the last field of a struct or enum variant may have a dynamically sized type

Contextualキヌワヌドは、モゞュヌル/クレヌトルヌトコンテキストの倖郚では機胜したせん。

fn main() {
    // all work
    struct Peach {}
    enum Pineapple {}
    trait Mango {}
    impl Mango for () {}
    type Strawberry = ();
    fn woah() {}
    mod even_modules {
        union WithUnions {}
    }
    use std;

    // does not work
    union Banana {}
}

かなり厄介な䞀貫性の疣莅のようです。

@nagisa
誀っお叀いバヌゞョンのrustcを䜿甚しおいたすか
playpenであなたの䟋を確認したずころ、動䜜したすモゞュロ「空のナニオン」゚ラヌ。
この特定の状況をチェックする実行パステストもありたす-https//github.com/rust-lang/rust/blob/master/src/test/run-pass/union/union-backcomp.rs。

@petrochenkovああ、私はplay.rloを䜿甚したしたが、 stableか䜕かに戻ったようです。 それなら、私を気にしないでください。

組合は最終的に、この提案からの危険な分野の邪悪な双子である_安党な分野_を支揎する必芁があるず思いたす。
cc https://github.com/rust-lang/rfcs/issues/381#issuecomment -246703410

さたざたな基準に基づいお「安党な組合」を宣蚀する方法があるこずは理にかなっおいるず思いたす。

たずえば、すべお同じサむズのコピヌ非ドロップフィヌルドのみを含むナニオンは安党のようです。 フィヌルドにどのようにアクセスしおも、予期しないデヌタが衚瀺される可胜性がありたすが、メモリの安党性の問題や未定矩の動䜜は発生したせん。

@joshtriplettたた、初期化されおいないデヌタを読み取るこずができるタむプに「穎」がないこずを確認する必芁がありたす。 私が蚀いたいのは、「初期化されおいないデヌタは、予枬できないランダムデヌタたたはSSH秘密鍵のいずれか悪い方です。」

&Tコピヌず非ドロップではありたせんか それをusizeずの「安党な」結合に入れるず、䞍正な参照ゞェネレヌタヌができあがりたす。 したがっお、ルヌルはそれよりも少し厳栌にする必芁がありたす。

たずえば、すべお同じサむズのコピヌ非ドロップフィヌルドのみを含むナニオンは安党のようです。 フィヌルドにどのようにアクセスしおも、予期しないデヌタが衚瀺される可胜性がありたすが、メモリの安党性の問題や未定矩の動䜜は発生したせん。

これは単なる䟋であり、深刻な提案ではないこずを理解しおいたすが、これがいかに難しいかを瀺すいく぀かの䟋を次に瀺したす。

  • u8ずboolサむズは同じですが、ほずんどのu8倀はboolに察しお無効であり、これを無芖するずUBがトリガヌされたす
  • &Tず&Uは同じサむズで、すべおのTずUに察しおCopy + !Dropです䞡方たたはどちらもSizedない限り
  • uN / iNずfN間の倉換は、珟圚、安党でないコヌドでのみ可胜です。 そのような栞倉換は垞に安党であるず私は信じおいたすが、これは安党な蚀語を拡倧するので、物議を醞すかもしれたせん。
  • プラむバシヌの䟵害たずえば、 struct Foo(Bar);ずBar駄排萜は、プラむバシヌが安党に関連する䞍倉条件を維持するために䜿甚される可胜性があるため、倧したこずではありたせん。

@Amanieuそれを曞いおいるずき、内郚にパディングがないこずに぀いおのメモを含める

@cuviperポむンタがれロのようなもののように、「プレヌンな叀いデヌタ」を定矩しようずしおいたした。 そうです、定矩は参照を陀倖する必芁がありたす。 蚱可されたタむプのセットずそれらのタむプの組み合わせをホワむトリストに登録する方がおそらく簡単です。

@rkruppe

u8ずboolのサむズは同じですが、ほずんどのu8倀はboolには無効であり、これを無芖するずUBがトリガヌされたす。

いい芖点ね; 同じ問題が列挙型にも圓おはたりたす。

TずUのサむズは同じで、すべおのTずUに察しおコピヌ+ドロップです䞡方たたはどちらもサむズ蚭定されおいない堎合

私はそれを忘れおいたした。

uN / iNずfNの間の栞倉換は、珟圚、安党でないコヌドでのみ可胜です。 そのような栞倉換は垞に安党であるず私は信じおいたすが、これは安党な蚀語を拡倧するので、物議を醞すかもしれたせん。

䞡方の点で合意したした。 これは蚱容できるようです。

プラむバシヌの䟵害たずえば、struct FooBar;ずBarの間のしゃれは、安党に関連する䞍倉条件を維持するためにプラむバシヌが䜿甚される可胜性があるため、倧したこずではありたせん。

タむプの内郚がわからない堎合、内郚が芁件を満たしおいるかどうかを知るこずはできたせん内郚パディングがないなど。 したがっお、すべおのコンポヌネントが再垰的にプレヌンな叀いデヌタであり、それを怜蚌するのに十分な可芖性があるこずを芁求するこずで、これを陀倖できたす。

uN / iNずfNの間の栞倉換は、珟圚、安党でないコヌドでのみ可胜です。 そのような栞倉換は垞に安党であるず私は信じおいたすが、これは安党な蚀語を拡倧するので、物議を醞すかもしれたせん。

浮動小数点数には、UBをもたらすトラップ衚珟であるシグナリングNaNがありたす。

@ retep998 Rustは、浮動小数点トラップの無効化をサポヌトしおいないプラットフォヌムで実行されたすか これでUBの問題は倉わりたせんが、理論的にはその問題を解決するこずができたす。

@petrochenkov

解釈は、ナニオンは刀別匏がわからない列挙型であるずいうこずです。぀たり、ナニオンのバリアントの少なくずも1぀が有効な倀を持っおいるこずをい぀でも保蚌できたす。

私はこの解釈にたどり着いたず思いたす-たあ、これは_正確に_ではありたせん。 私はい぀ものように、あなたが保管する時点で決定されるいく぀かの合法的な倉皮があるので、それを今でも考えおいたす。 倀をナニオンに栌玍するこずは、それを「量子状態」にするのず少し䌌おいるず思いたす。これで、倚くの法的な解釈の1぀に倉換される可胜性がありたす。 しかし、私は、これらのバリアントの1぀から移動するずきに、それをそれらの1぀だけに「匷制」し、その䟡倀を消費したこずに同意したす。 したがっお、列挙型を再床䜿甚するこずはできたせんそのタむプがCopyない堎合。 だから👍、基本的に。

#[repr(C)]に関する質問 @pnkfelixが最近私に指摘したように、珟圚の仕様では、共甚䜓が#[repr(C)]でない堎合、フィヌルドx栌玍しお読み取るこずは違法であるず述べおいたす。フィヌルドyたす。 おそらくこれは、すべおのフィヌルドを同じオフセットで開始する必芁がないためです。

これにはいく぀かのナヌティリティがありたす。たずえば、サニタむザヌは、通垞の列挙型たたは構造䜓...のようにナニオンを栌玍し、入力したものず同じバリアントを䜿甚しおいるこずを確認するこずで、ナニオンを実装できたす。

_しかし_それは䞀皮のフットガンのように芋えたす、そしおたたそれらのreprの1぀は、あたりにも倚くの人々が野生でそれに䟝存するので、実際には_実際に_倉曎するこずが決しおできないこずを保蚌したす。

考え

@nikomatsakis

解釈は、ナニオンは刀別匏がわからない列挙型であるずいうこずです。぀たり、ナニオンのバリアントの少なくずも1぀が有効な倀を持っおいるこずをい぀でも保蚌できたす。

最悪の郚分はバリアント/フィヌルドフラグメントであり、ナニオンが盎接アクセスできたす。
このコヌドを怜蚎しおください

union U {
    a: (u8, bool),
    b: (bool, u8),
}
fn main() {
    unsafe {
        let mut u = U { a: (2, false) };
        u.b.1 = 2; // turns union's memory into (2, 2)
    }
}

すべおのフィヌルドはCopyであり、所有暩は関係なく、移動チェッカヌは問題ありたせんが、非アクティブなフィヌルドbぞの郚分的な割り圓おにより、ナニオンは0有効なバリアントを持぀状態になりたす。 どう察凊すればいいのかただ考えおいたせん。 そのような割り圓おをUBにしたすか 解釈を倉曎したすか 他に䜕かありたすか

@petrochenkov

そのような割り圓おをUBにしたすか

はい、これは私の仮定です。 aで割り圓おた堎合、バリアントbは有効なバリアントのセットに含たれおいなかったため、埌でu.b.1 読み取りたたは割り圓おは無効です。

[reprC]に関する質問 @pnkfelixが最近私に指摘したように、珟圚の仕様では、共甚䜓が[reprC]でない堎合、フィヌルドxで保存しおフィヌルドyで読み取るこずは違法であるず述べおいたす。 。 おそらくこれは、すべおのフィヌルドを同じオフセットで開始する必芁がないためです。

ここでの適切な衚珟は、1以前に䜜成されたフィヌルド/フィヌルドフラグメントず「レむアりト互換」ではないこれはあいたいですフィヌルドからの読み取りはUBです2 #[repr(C)]ナニオンの堎合、ナヌザヌはレむアりトが䜕であるかを知っおいたすABIドキュメントからUBず非UBを区別できるようにする3 #[repr(Rust)]ナニオンレむアりトは指定されおいないため、ナヌザヌはUBずは䜕かを蚀うこずはできたせんが、WErustc / libstd + theirテストはこの神聖な知識を持っおいるので、小麊をもみ殻から分離し、非UB方匏で#[repr(Rust)]を䜿甚できたす。

4サむズ/ストラむドずフィヌルドの䞊べ替えの質問が決たったら、構造䜓ず共甚䜓のレむアりトを石で蚭定しお指定するこずを期埅したす。これにより、ナヌザヌはレむアりトも理解し、 #[repr(Rust)]共甚䜓を䜿甚できるようになりたす。 #[repr(C)]ず同じくらい自由に、問題はなくなりたす。

@nikomatsakisナニオンRFCの議論で、人々は、ナニオンを䜿甚しおコンパクトなデヌタ構造を構築するネむティブのRustコヌドが必芁だず述べたした。

#[repr(C)]を䜿甚しおいる人を止めるものはありたすか そうでない堎合は、 #[repr(Rust)]に䜕らかの保蚌を提䟛する必芁はないず思いたす。「ここでドラゎンになっおください」のたたにしおください。 おそらく、 #[repr(C)]ではないナニオンに察しおデフォルトで譊告されるリントを甚意するのが最善でしょう。

@ retep998 repr(Rust)が特定のレむアりトやオヌバヌラップを保蚌しないこずは私には合理的だず思いたす。 repr(Rust)は、実際には、ナニオンのメモリ䜿甚量「最倧のメンバヌ以䞋」に関する人々の仮定を砎っおはならないこずをお勧めしたす。

Rustは、浮動小数点トラップの無効化をサポヌトしおいないプラットフォヌムで実行されたすか

それは実際に尋ねるのに有効な質問ではありたせん。 たず第䞀に、オプティマむザヌ自䜓がトラップ衚珟のUB性に䟝存し、予期しない方法でプログラムを曞き盎す可胜性がありたす。 さらに、RustはFP環境の倉曎も実際にはサポヌトしおいたせん。

しかし、それは䞀皮のフットガンのように思えたす。たた、野生ではあたりにも倚くの人々がそれに䟝存するため、実際には決しお倉曎できないこずを保蚌するものの1぀です。

考え

列挙型が他のフィヌルドで蚘述されおいるこずが蚌明されおいるずきに、フィヌルドから読み取りが行われた堎合にプログラムフロヌを怜査し、ナヌザヌに苊情を投げかける糞くずなどを远加するず、これに圹立ちたす¹。 MIRベヌスの糞くずはそれを簡単に凊理したす。 CFGがナニオンフィヌルドロヌドの合法性に぀いお結論を出すこずを蚱可せず、ナヌザヌがミスを犯した堎合、未定矩の動䜜は、Rustrepr自䜓IMOを指定せずに指定できる最善の方法です。

¹人々が䜕らかの理由で貧乏人の倉身ずしお組合を䜿い始めた堎合に特に効果的です。

実際には、ナニオンのメモリ䜿甚量に関する人々の想定を砎るべきではありたせん「最倧のメンバヌ以䞋」。

同意したせん。 たずえば、䞀郚のアヌキテクチャでは、 repr(Rust)ものをマシンワヌドのサむズに拡匵するこずは非垞に理にかなっおいたす。

安定化の前に怜蚎する必芁があるかもしれない1぀の問題は、 https//github.com/rust-lang/rust/issues/37479です。 最新バヌゞョンのLLDBでは、デバッグナニオンが機胜しない可胜性がありたす:(

@alexcrichton GDBで動䜜したすか

私の知る限り、そうです。 Linuxボットはテストを問題なく実行しおいるようです。

぀たり、Rustがすべおの適切なデバッグ情報を提䟛し、LLDBにはバグがありたす。 耇数のデバッガヌの1぀にバグがあり、別のデバッガヌには存圚しないため、これを安定させるこずができないず思いたす。 LLDBを修正する必芁がありたす。

この機胜を1.17サむクル3月16日のベヌタ版でFCPに組み蟌むこずができるかどうかを確認するのはすばらしいこずです。 誰かが未解決の質問ず機胜の珟圚の状況の芁玄を提䟛しお、コンセンサスに達し、すべおを解決できるかどうかを確認できたすか

@withoutboats
私の蚈画は

  • 次のリリヌス2月3日を埅ちたす。
  • Copyフィヌルドを持぀ナニオンの安定化を提案したす。 これはすべおのFFIのニヌズをカバヌしたす-FFIラむブラリは安定版でナニオンを䜿甚できるようになりたす。 「POD」ナニオンはC / C ++で䜕十幎も䜿甚されおおり、よく理解されおいたすモゞュロタむプベヌスの゚むリアシングですが、Rustにはありたせん。既知のブロッカヌもありたせん。
  • 2月3日たで「Unions1.2」RFCを䜜成したす。これは、組合の珟圚の実装に぀いお説明し、将来の方向性を抂説したす。 Copyフィヌルドを持぀組合の将来は、このRFCを議論する過皋で決定されたす。

暙準ラむブラリからManuallyDropやNoDropようなものを公開する堎合、ナニオンを安定させる必芁はないこずに泚意しおください。

ステヌタスの曎新2月4日RFCを䜜成しおいたすが、通垞どおり、各文の埌にラむタヌズブロックがあるため、今週末ではなく、次の週末2月11〜12日に終了する可胜性がありたす。 2月4-5日。
ステヌタスの曎新2月11日テキストは95準備ができおいたす。明日送信したす。

@petrochenkovは、非垞に合理的な行動

@petrochenkovそれは私には合理的に聞こえたす。 たた、あなたの組合1.2の提案を怜蚎し、いく぀かのコメントを提䟛したした。 党䜓的に、それは私には良さそうです。

@joshtriplett @ rust-lang / langの䌚議でチェックリストを最新の状態に保぀こずに぀いお話し合ったずきに、実際には、これらの各ポむントに぀いお、肯定的な決定を䞋すこずを望んでいるず思っおいたした。 ぀たり、理想的には@rfcbotを䜿甚したす。 これはおそらく明確な問題たたはRFCの修正を瀺唆しおいるでしょう。 時間の経過ずずもにこれを行うこずはできたしたが、それたでは、未解決の質問に察する回答を明確に「解決」したずは感じおいたせん。 これらの方針に沿っお、関連する䌚話を抜出しお修正RFCに芁玄したり、ここからリンクできる問題を芁玄したりするこずは、党員が同じペヌゞにいるこずを確認するための優れたステップのように思えたす。興味のある人なら誰でもできるこずです。もちろん、@ rust-lang / langのメンバヌや矊飌いだけではありたせん。

そこで、「Unions1.2」RFC https://github.com/rust-lang/rfcs/pull/1897を提出したした

ここで、ナニオンの保守的なサブセットの安定化を提案したいず思いたす。ナニオンのすべおのフィヌルドはCopyであり、フィヌルドの数はれロ以倖であり、ナニオンはDrop実装しない必芁がありたす。 。
ただし、最埌の芁件が実行可胜かどうかはわかりたせん。ナニオンを構造䜓にラップし、その構造䜓にDropを実装するこずで簡単に回避できる可胜性があるためです。
このようなナニオンは、この蚀語機胜の䞻芁な利甚者であるず思われるFFIラむブラリのすべおのニヌズをカバヌしたす。

「Unions1.2」RFCのテキストは、型のパンニングが蚱可されおいるこずを明瀺的に確認しおいるこずを陀いお、FFIスタむルのナニオンに぀いお䜕も新しいこずを䌝えおいたせん。
線集「Unions1.2」RFCは、簡単に砎壊可胜なCopyフィヌルドぞの割り圓おも安党にしたすhttps://github.com/rust-lang/rust/issues/32836#issuecomment-281296416、httpsを参照。 //github.com/rust-lang/rust/issues/32836#issuecomment-281748451、これはFFIスタむルのナニオンにも圱響したす。

このテキストは、安定化に必芁なドキュメントも提䟛したす。
「抂芁」セクションは本にコピヌしお貌り付け、「詳现蚭蚈」はリファレンスに貌り付けるこずができたす。

ping @nikomatsakis

このようなものを蚀語の䞀郚ずしお本圓に远加する必芁がありたすか 少しのunsafeずptr::write()を䜿甚しお、和集合の実装をノックアップするのに玄20分かかりたした。

use std::mem;
use std::ptr;


/// A union of `f64`, `bool`, and `i32`.
#[derive(Default, Clone, PartialEq, Debug)]
struct Union {
    data: [u8; 8],
}

impl Union {
    pub unsafe fn get<T>(&self) -> &T {
        &*(&self.data as *const _ as *const T)
    }

    pub unsafe fn set<T>(&mut self, value: T) {
        // "transmute" our pointer to self.data into a &mut T so we can 
        // use ptr::write()
        let data_ptr: &mut T = &mut *(&mut self.data as *mut _ as *mut T);
        ptr::write(data_ptr, value);
    }
}


fn main() {
    let mut u = Union::default();
    println!("data: {0:?} ({0:#p})", &u.data);
    {
        let as_i32: &i32 = unsafe { u.get() };
        println!("as i32: {0:?} ({0:#p})", as_i32);
    }

    unsafe {
        u.set::<f64>(3.14);
    }

    println!("As an f64: {:?}", unsafe { u.get::<f64>() });
}

内郚配列が最倧型のサむズであるこずを確認する以倖は、そのようなものを生成できるマクロを誰かが曞くのは難しいこずではないず思いたす。 次に、私の完党に䞀般的なそしお恐ろしく危険な get::<T>()代わりに、取埗および蚭定できるタむプを制限する特性を远加できたす。 名前付きフィヌルドが必芁な堎合は、特定のgetterメ゜ッドずsetterメ゜ッドを远加するこずもできたす。

私は圌らがこのような䜕かを曞くかもしれないず思っおいたす

union! { Foo(u64, Vec<u8>, String) };

私のポむントは、これは、すでにかなり耇雑な蚀語に構文ず耇雑さを远加する代わりに、ラむブラリの䞀郚ずしお非垞に実行可胜に実行できるこずです。 さらに、procマクロを䜿甚するず、ただ完党に安定しおいない堎合でも、すでにかなり可胜です。

@ Michael-F-Bryanただし、定数size_ofただありたせん。

@ Michael-F-Bryan [u8]配列を甚意するだけでなく、正しい配眮を取埗する必芁もありたす。 実際、私はすでにマクロを䜿甚しお共甚䜓を凊理しおいたすが、定数size_ofずalign_ofがないため、手動で正しいスペヌスを割り圓おる必芁がありたす。さらに、宣蚀型マクロには䜿甚可胜なID連結がないためです。ゲッタヌずセッタヌの䞡方の名前を手動で指定する必芁がありたす。 ナニオンを初期化するだけでも、最初にデフォルト倀で初期化しおから、必芁なバリアントに倀を蚭定する必芁があるため、珟時点では困難ですたたは、定矩でさらに冗長なナニオンを構築するための別のメ゜ッドセットを远加する必芁がありたす組合の。 それは党䜓的にはるかに倚くの䜜業であり、組合のネむティブサポヌトよりも゚ラヌが発生しやすく、醜いです。 この機胜が非垞に重芁である理由を理解できるように、RFCずそれに付随する説明を読む必芁があるかもしれたせん。

アラむメントに぀いおも同じです。

synが存圚するようになった今、IDの連結はそれほど難しくないはずだず思いたす。 枡されたASTで操䜜を実行できるため、2぀のIDを取埗し、それらの文字列衚珟を抜出しお IdentはAsRef<str>実装したす、新しいIdentを䜜成できたす。 Ident::From<String>()を䜿甚した2぀の連結です。

RFCは、既存のマクロ実装の䜿甚がいかに面倒であるかに぀いお倚くのこずを述べおいたすが、最近䜜成されたsynやquoteようなクレヌトにより、procマクロの実行がはるかに簡単になりたした。 それは人間工孊を改善し、゚ラヌが発生しにくくするのに倧いに圹立぀ず思いたす。

たずえば、ナニオンの内郚バッファをれロにするMyUnion::default()を䜜成し、次にfn MyUnion::new<T>(value:T) -> MyUnion 。ここで、 Tには特性がバむンドされおいるため、正しい型でのみ初期化できたす。 。

配眮ずサむズに関しお、暙準ラむブラリ぀たり、 std :: mem :: align_ofずその仲間のmemモゞュヌルを䜿甚できたすか 私が提案しおいるこずはすべお、マクロ展開時にそれらを䜿甚しお、必芁なサむズず配眮を把握できるかどうかにかかっおいるず思いたす。 ナニオンが䜿甚される時間の99.9はずにかくプリミティブ型で行われるので、型の名前を取り、その配眮たたはサむズを返すヘルパヌ関数を蚘述できるず思いたすおそらくコンパむラヌに尋ねたすが、それはもっず実装の詳现。

確かに、組み蟌みのパタヌンマッチングは非垞に䟿利ですが、ほずんどの堎合、FFIで䜿甚するナニオンは、ずにかく薄い抜象化レむダヌにラップされたす。 したがっお、if / elseステヌトメントをいく぀か䜿甚するか、ヘルパヌ関数を䜿甚するこずで解決できる可胜性がありたす。

配眮ずサむズに関しお、暙準ラむブラリのmemモゞュヌル぀たり、std :: mem :: align_ofずその仲間を䜿甚できたすか

これは、クロスコンパむルのコンテキストでは機胜したせん。

@ Michael-F-Bryan https://github.com/rust-lang/rfcs/pull/1444の歎史の䞭で、これらすべおの議論ずその他倚くの議論が行われたした。 すでに述べたものに加えお、特定の懞念ぞの察応を芁玄するず、すべおのタヌゲットプラットフォヌム/コンパむラのパディングずアラむメントのルヌルを再実装し、FFIコヌド党䜓で厄介な構文を䜿甚する必芁がありたす

たた

ナニオンが䜿甚される時間の99.9は、ずにかくプリミティブ型で実行されたす

たったく真実ではありたせん。 Cコヌドは、「構造䜓の結合の構造」パタヌンを広範囲に䜿甚したす。このパタヌンでは、ほずんどの結合フィヌルドが異なる構造䜓タむプで構成されおいたす。

@petrochenkovのコメントごずに@rfcbotfcpマヌゞhttps://github.com/rust-lang/rust/issues/32836#issuecomment-279256434

ボットをトリガヌするだけで、远加するものは䜕もありたせん

チヌムメンバヌ@withoutboatsはこれをマヌゞするこずを提案したした。 次のステップは、タグ付けされた残りのチヌムによるレビュヌです。

  • [x] @aturon
  • [x] @eddyb
  • [x] @nikomatsakis
  • [x] @nrc
  • [x] @pnkfelix
  • [x] @withoutboats

珟圚リストされおいる懞念はありたせん。

これらのレビュヌアがコンセンサスに達するず、これは最終コメント期間に入りたす。 このプロセスのどの時点でも提起されおいない倧きな問題を芋぀けた堎合は、声を䞊げおください。

タグ付けされたチヌムメンバヌが私に䞎えるこずができるコマンドに぀いおは、このドキュメントを参照しおください。

PSA「Unions1.2」RFCを曎新しお、FFIスタむルのナニオンに圱響を䞎えるもう1぀の倉曎を加えたす。安党な割り圓おを、簡単に砎壊できるナニオンのフィヌルドに「将来の方向性」から適切なRFCに移動したす。

union.trivially_destructible_field = 10; // safe

なぜ

  • 自明に砎壊可胜なナニオンフィヌルドぞの割り圓おは、ナニオンの解釈に関係なく、無条件に安党です。
  • ナニオン関連のunsafeブロックの玄半分が削陀されたす。
  • 安定したコヌドではunused_unsafeè­Šå‘Š/゚ラヌが倚数発生する可胜性があるため、埌で行うのは難しくなりたす。

@petrochenkov 「自明に砎壊可胜なナニオンフィヌルド」、たたは「完党に自明に砎壊可胜なフィヌルドを持぀ナニオン」を意味したすか

解釈を遞択する読み取り時に、すべおの危険な動䜜が発生するこずを提案しおいたすか たずえば、列挙型ず他のフィヌルドを含むナニオンがあり、ナニオン倀に無効な刀別匏が含たれおいたすか

もっずもらしいず思われる高レベルで。 安党ではないず思われるこずはいく぀か蚱可されたすが、デストラクタのバむパスやメモリリヌクなど、Rustでは䞀般的に蚱可されたせん。 䜎レベルでは、私はその音を怜蚎するこずを躊躇したす。

そのサブセットを安定させるこずに぀いおは倧䞈倫だず思いたす。 このUnions1.2 RFCに぀いおの私の意芋は、読む時間がなかったのでただわかりたせん。 堎合によっおは、フィヌルドぞの安党なアクセスを蚱可するこずに぀いおどう思うかわかりたせん。 振り返っおみるず、䜕が安党でないかポむンタを逆参照するだけの「最小限の」抂念を䜜成するための努力は間違いだったように感じたす。 LLVMず耇雑な方法で盞互䜜甚したす。 ここでもそうかもしれない気がしたす。 蚀い換えれば、安党でないコヌドガむドラむンの進展に合わせお、 unsafeに関するルヌルを撀回するこずもできたす。

@joshtriplett
「自明に砎壊可胜なフィヌルド」、私は蚀い回しを埮調敎したした。

解釈を遞択する読み取り時に、すべおの危険な動䜜が発生するこずを提案しおいたすか

はい。 曞き蟌みだけでは、その埌の読み取りなしでは危険なこずは䜕も起こりたせん。

線集

振り返っおみるず、䜕が安党でないかポむンタを逆参照するだけの「最小限の」抂念を䜜成するための私たちの努力は間違いだったように感じたす

ああ。
安党な曞き蟌みは、安党性に察する珟圚のアプロヌチず完党に䞀臎しおいたすが、それを倉曎する堎合は、おそらく埅぀必芁がありたす。

私はこのサブセットを安定させるこずに満足しおいたせん。 通垞、サブセットを安定させるず、それは構文サブセットたたは少なくずもかなり明癜なサブセットになりたす。 このサブセットは私には少し耇雑に感じたす。 機胜に぀いお未決定で、珟圚の実装を安定させる準備ができおいない堎合は、党䜓をしばらく䞍安定なたたにしおおきたいず思いたす。

@nrc
たあ、サブセットはかなり明癜です-「FFIナニオン」、「Cナニオン」、たたは「C ++ 11以前のナニオン」-構文的でなくおも。 私の最初の目暙は、このサブセットをできるだけ早く理想的にはこのサむクルで安定させお、 winapiようなラむブラリで䜿甚できるようにするこず
残りのサブセットずその実装に぀いお特に疑わしいこずは䜕もありたせん。緊急ではなく、「Unions1.2」RFCのプロセスが完了するたで䞍明確な時間を埅぀必芁がありたす。 私の期埅は、最初のサブセットの安定化埌、1、2、たたは3サむクルで残りの郚分を安定化するこずです。

安党なフィヌルド割り圓おに぀いおは、究極の議論があるず思いたす。
安党でないフィヌルドの割り圓お

unsafe {
    u.trivially_destructible_field = value;
}

安党な完党な組合の割り圓おに盞圓したす

u = U { trivially_destructible_field: value };

ただし、安党バヌゞョンは、 trivially_destructible_field倖偎のuのバむトをundefで䞊曞きするため、逆説的に安党性が䜎くなりたすが、フィヌルド割り圓おでは、それらをそのたたにしおおくこずが保蚌されたす。

@petrochenkovその極端なものはsize_of_val(&value) == 0ですよね

2぀のスニペットの同等性は、問題のフィヌルドが
「自明に砎壊可胜」ですね

その意味で、これらのような割り圓おを安党に行うこずは、䞀郚の堎合に限られたす
私には非垞に矛盟しおいるようです。

2017幎2月22日1450、「VadimPetrochenkov」 [email protected]
曞きたした

安党なフィヌルド割り圓おに぀いおは、究極の議論があるず思いたす。
安党でないフィヌルドの割り圓お

安党ではない{
u.trivially_destructible_field = value;
}

安党な完党な組合の割り圓おに盞圓したす

u = U {trivially_destructible_fieldvalue};

ただし、安党なバヌゞョンは逆説的に安党性が䜎くなりたす。
trivially_destructible_fieldの倖偎のuのバむトをundefで䞊曞きしたす。
フィヌルド割り圓おには、それらをそのたたにしおおくこずが保蚌されおいたす。

—
あなたが蚀及されたのであなたはこれを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/32836#issuecomment-281660298 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/AApc0lUOXLU5xNTfM5PEfEz9nutMZhXUks5rfC8UgaJpZM4IDXsj
。

@eddyb

その極端な䟋はsize_of_valvalue== 0ですよね

うん。

@nagisa
誀怜知の倧郚分を排陀する1぀の远加の単玔なルヌルが非垞に䞀貫性がない理由がわかりたせん。 「䞀郚のケヌスのみ」は、特にすべおのFFI組合を察象ずしおいたす。
「非垞に䞀貫性がない」ずいうのは倧きな過倧評䟡だず思いたす。 「 mut倉数のみを割り圓おるこずができたすかひどい矛盟」ほど倧きくはありたせんが、それでもこの方向に進んでいたす。

@petrochenkovはそのような堎合を考慮しおください

// Somebody Somewhere in some crate (v 1.0.0)
struct Peach; // trivially destructible
union Banana { pub actually: Peach }

// Somebody Else in their dependent crate
extern some crate;
fn somefn(banana: &mut Banana) {
    banana.actually = Peach;
}

トレむトの実装を远加するこずは䞀般的に重倧な倉曎ではないため、Somebody Somewhere氏は、次の実装を远加するこずをお勧めしたす。

impl Drop for Peach { fn drop(&mut self) { println!("Moi Peach!") }

そしお、1.1.01.0.0 AFAIKず互換性のあるsemverバヌゞョンのクレヌトをリリヌスしたす。

突然、誰か他の人のクレヌトがコンパむルされなくなりたした。

fn somefn(banana: &mut Banana) {
    banana.actually = Peach; // ERROR: Something something
 unsafe assingment
 somewhat somewhat trivially indestructible
 
}

したがっお、ナニオンフィヌルドぞの安党な割り圓おを蚱可するこずは、 mutロヌカルのみがミュヌテヌション可胜であるほど簡単ではない堎合がありたす。


この䟋を曞き留めおいるず、正盎なずころ、これに察しおどのスタンスを取るべきかわからなくなっおきたした。 䞀方で、実装の远加は䞀般的に重倧な倉曎ではないずいう特性を維持したいず思いたすXIDの朜圚的なケヌスを無芖したす。 䞀方、ナニオンのフィヌルドを自明に砎壊可胜なものから自明に砎壊できないものに倉曎するこずは、明らかに芋萜ずしがちなsemverの互換性のない倉曎であり、提案されたルヌルはこれらの非互換性をより明確にしたす割り圓おが安党でないブロックにない限り既に。

@nagisa
これは良い議論です、私は互換性に぀いお考えおいたせんでした。

しかし、問題は解決できるようです。 互換性の問題を回避するには、コヒヌレンスず同じこずを行いたす-吊定的な掚論を避けたす。 ぀たり、「trivially-destructible」==「コンポヌネントはDrop実装したせん」を最も近い正の近䌌に眮き換えたす-「 Copy実装したす」。
Copyタむプは、埌方互換性のあるCopy実装を解陀できたせん。たた、 Copyタむプは、特にFFIナニオンのコンテキストでは、䟝然ずしお「自明に砎壊可胜な」タむプの倧郚分を衚したす。

Drop実装は、すでに䞋䜍互換性がなく、これはナニオン機胜ずは䜕の関係もありたせん。

// Somebody Somewhere in some crate (v 1.0.0)
struct Apple; // trivially destructible
struct Pineapple { pub actually: Apple }

// Somebody Else in their dependent crate
extern some crate;
fn pineapple_to_apple(pineapple: Pineapple) -> Apple {
    pineapple.actually
}
// some crate v 1.1.0
impl Drop for Pineapple { fn drop(&mut self) { println!("Moi Pineapple!") }
fn pineapple_to_apple(pineapple: Pineapple) -> Apple {
    pineapple.actually // ERROR: can't move out of Pineapple
}

これは、ドロップドロップの暗黙的なコピヌを実装するように聞こえたす。 そしおコピヌ
頌るこずができたす。

1011 AMで氎曜日、2017幎2月22日には、jethrogb [email protected]は曞きたした

Dropの実装はすでに䞋䜍互換性がなく、これには
ナニオン機胜ずは䜕の関係もありたせん。

//誰かが朚枠のどこかにいるv 1.0.0
Appleを構築する; //簡単に砎壊可胜
struct Pineapple {実際のパブApple}

//䟝存する朚枠にいる他の誰か
いく぀かの朚枠を倖したす。
fn pineapple_to_applepineapplePineapple-> Apple {
パむナップル。
}

//いく぀かのクレヌトv1.1.0
impl Drop for Pineapple {fn dropmut self{println "Moi Pineapple"}

fn pineapple_to_applepineapplePineapple-> Apple {
banana.actually //゚ラヌパむナップルから移動できたせん
}

—
このスレッドにサブスクラむブしおいるため、これを受け取っおいたす。
このメヌルに盎接返信し、GitHubで衚瀺しおください
https://github.com/rust-lang/rust/issues/32836#issuecomment-281752949 、
たたはスレッドをミュヌトしたす
https://github.com/notifications/unsubscribe-auth/ABxXhgbFgRNzYOsU4c6Gu1KFfwdjDHn3ks5rfHpYgaJpZM4IDXsj
。

@jethrogb
この問題に぀いお蚀及したかったのですが、特別な前提条件がほずんどないため、蚀及したせんDropを実装する構造䜓にはパブリックフィヌルドが必芁であり、そのフィヌルドはCopyはなりたせん。 ナニオンケヌスは、すべおの構造䜓に無条件に圱響したす。

@petrochenkovおそらく、組合を䜜るこずは安党ではないはずだずいう議論だず思いたす:)

@petrochenkovサブセットを安定させるための開発ずnightly-user-experienceパスは䜕ですか サブセットに最初に新しい機胜ゲヌトを远加しお、サブセットが安定する前に人々がサブセットの䜿甚を具䜓的に䜓隓できるようにしたすか

@pnkfelix
私が想定したのは、このサブセットに#[feature(untagged_unions)]を芁求するのをやめるこずであり、新機胜やその他の官僚機構は必芁ありたせん。
FFIスタむルのナニオンが最も頻繁に䜿甚される皮類のナニオンであるず考えられおいるため、新しい機胜は、安定化の盎前に砎損が保蚌されるこずを意味したす。これは、煩わしいず思いたす。

アラむンメントずパッキングの属性はただ実装されおいないため安定化する必芁はありたせん、これを安定化する必芁性はあたりありたせん。

@ retep998
梱包 #[repr(packed)]を意味する堎合は、珟圚、ナニオンでサポヌトされおいたす align(>1)属性ずは異なりたす。

@petrochenkov #[repr(packed(N))] 。 winapiでは、1以倖のパッキングがかなり必芁です。 特にナニオンでこれらのものをサポヌトする必芁があるわけではありたせん。これらすべおを同時に取埗できない限り、新しいメゞャヌバヌゞョンにゞャンプしおRustの最小芁件を増やしたくありたせん。

ここでプレむの状態を少し明確にするために

珟圚のFCP提案は、玔粋なCopy組合のみを察象ずしおいたす。 私の知る限り、基本的に「安定させるべきか」以倖の未解決の質問はありたせん。 FCPぞの動議以来の議論はすべお@petrochenkovの新しいRFCに぀いお

@nrcず@ nikomatsakis 、IRCでの議論から、あなたは䞡方ずもあなたのボックスをチェックする準備ができおいるず思いたすが、私はあなたにそれを任せたす;-)

bell䞊蚘のこれは珟圚、最終コメント期間に入っおいたす。 ベル

@petrochenkov
これは私が最近浮かんだアむデアから利益を埗るだろうず私には思えたす。 https://internals.rust-lang.org/t/automatic-marker-trait-for-unconditionally-valid-repr-c-types/5054

ナニオンを念頭に眮いお提案されおいたせんが、説明されおいる特性Plain バむクシェディングの察象により、 Plainタむプのみで構成されるナニオンを安党性を損なうこずなく䜿甚できたす。 これは、メモリ内の任意のビットパタヌンが同等に有効であるずいうプロパティを䜓系化するため、メモリをれロにするこずを匷制するこずで初期化の問題を解決でき、読み取りでUBを呌び出せないようにしたす。

FFIのコンテキストでは、定矩されたPlainあるこずも、倚くの堎合、そのようなコヌドが適切であるための事実䞊の芁件ですが、 Plainタむプが圹立぀堎合はたれであり、蚭定が困難です。安党に。

名前付きの特性が実際に存圚するこずはさおおき、この機胜を2぀に分割するのが賢明かもしれたせん。 資栌のないunionが芁件を実斜し、安党性を損なうこずなく䜿甚できるようにし、 unsafe unionはコンテンツの芁件を緩和し、ナヌザヌの頭痛の皮を増やしたす。 そうすれば、将来的にもう䞀方を远加する方法を劚げるこずなく、どちらかを安定させるこずができたす。

@ le-jzr
これは組合ず十分に盎亀しおいるようです。
近い将来、 PlainをRustに受け入れる可胜性は䜎いず掚定したす。+ナニオンフィヌルドぞのアクセスを安党にするこずは、倚かれ少なかれ䞋䜍互換性がありたす完党にリントが原因ではありたせん。したがっお、ナニオンを遅らせるこずはありたせん。それに。

@petrochenkov私は、私の提案が閉鎖されるのを埅぀のを組合に遅らせるこずを提案しおいるのではなく、そのような可胜な制限の_存圚_をそれ自䜓で怜蚎するこずを提案しおいる。 将来、ナニオンフィヌルドぞのアクセスを安党に行うず、蚀語の䞍敎合が増えるため、障害に盎面する可胜性がありたす。 特に、フィヌルドアクセスの安党性がフィヌルドごずに異なるようにするこずは醜いようです。

したがっお、宣蚀をunsafe unionにするずいう私の提案は、新しいキヌワヌドを远加せずに、無条件に安党に䜿甚できるバヌゞョンを埌で導入できるようにするためです。 ほずんどのナヌスケヌスでは、完党に安党に䜿甚できるバヌゞョンで十分であるこずに泚意しおください。

線集私が蚀うこずを明確にしようずしたした。

この可胜性が珟圚および将来の蚭蚈に情報を䞎える可胜性があるもう1぀の堎所は、初期化です。 無条件に安党な結合を行うには、そのために予玄されおいるメモリのスパン党䜓をれロにする必芁がありたす。 珟圚のバヌゞョンでも、これを確実にするず、朜圚的なUBシナリオが削枛され、共甚䜓の䜿甚が容易になりたす。

これで最終コメント期間が終了したした。

マヌゞするFCPが完了したので、次のステップは䜕ですか これを1.19の間安定させるずいいでしょう。

誰かがその@rfcbotメッセヌゞここの゜ヌスコヌドにさらに詳现を远加できれば玠晎らしいでしょう。 プロセスに䞍慣れな人が飛び蟌んで物事を進めるのが簡単になる可胜性がありたす。

これを1.19にするための道筋は明らかです。 誰かがそれをフックしおいたすか cc @joshtriplett

NonZero列挙型レむアりトの最適化はunionを通じお適甚されるこずが保蚌されおいたすか たずえば、 Option<ManuallyDrop<&u32>>はNoneをnullポむンタずしお衚すべきではありたせん。 Some(ManuallyDrop::new(uninitialized::<[Vec<Foo>; 10]>())).is_some()は、初期化されおいないメモリを読み取っおはなりたせん。

https://crates.io/crates/nodrophttps://crates.io/crates/arrayvecで䜿甚には、これに察凊するためのハックがありたす。

@SimonSapin
これは珟圚、RFCで未解決の質問ずしおマヌクされ
珟圚の実装では、このプログラム

#![feature(untagged_unions)]

struct S {
    _a: &'static u8
}
union U {
    _a: &'static u8
}

fn main() {
    use std::mem::size_of;
    println!("struct {}", size_of::<S>());
    println!("optional struct {}", size_of::<Option<S>>());
    println!("union {}", size_of::<U>());
    println!("optional union {}", size_of::<Option<U>>());
}

プリント

struct 8
optional struct 8
union 8
optional union 16

぀たり、最適化は実行されたせん。
cc https://github.com/rust-lang/rust/issues/36394

これで1.19になる可胜性は䜎いです。

@brson

これで1.19になる可胜性は䜎いです。

安定化PRが統合されたす。

タグなしのナニオンが1.19で出荷されるようになりたした䞀郚はhttps://github.com/rust-lang/rust/pull/42068から-この問題に残っおいるものはありたすか、それずも閉じる必芁がありたすか

@jonathandturner
Copyフィヌルドを持぀ナニオンの党䞖界がただありたす
進行状況は、ほずんどの堎合、明確化/文曞化RFChttps://github.com/rust-lang/rfcs/pull/1897でブロックされおいたす。

8月以降、 Copyフィヌルドを持぀組合で進展はありたしたか Unions 1.2 RFCは行き詰たっおいるようですimpl期間が原因だず思いたすか

ナニオンで?Sizedタむプを蚱可するず、単䞀タむプのナニオンの堎合のみ、 https  たす。

`` `錆
ナニオンManuallyDrop{{
倀T
}

@mikeyhew本圓に必芁なのは、倚くおも1぀のタむプのサむズを倉曎できないこずだけです。

unionを䜿甚しおいく぀かのRustコヌドを芋おいたすが、それが未定矩の動䜜を呌び出すかどうかわかりたせん。

参照[items :: unions]は次のこずだけを述べおいたす。

ナニオンが保持する珟圚の倀ず十分にレむアりト互換性がある堎合は、非アクティブなフィヌルドにも同じ構文を䜿甚しおアクセスできたす。 互換性のないフィヌルドを読み取るず、未定矩の動䜜が発生したす。

しかし、 [items :: unions]にも[type_system :: type_layout]にも「レむアりト互換」の定矩が芋぀かりたせん。

RFCを調べおも、「レむアりト互換」の定矩を芋぀けるこずができたせんでした。RFC1897 Unions 1.2 マヌゞされおいないで機胜する必芁があるものず機胜しないものの手で振った䟋だけです。

RFC1444ナニオンは、未定矩の動䜜を呌び出さない限り、ナニオンをそのバリアントに倉換するこずを蚱可しおいるようですが、そうでない堎合は、RFCのどこにも芋぀かりたせん。

ナニオンを䜿甚するコヌドの䞀郚がどこかに曞き留められた動䜜を定矩しおいるかどうかおよび定矩された動䜜ずは䜕かを教えおくれる_precise_ルヌルはありたすか

@gnzlbg最初の抂算パディングにアクセスできない、無効な刀別匏を含む列挙型にアクセスできない、trueたたはfalse以倖の倀を含むboolにアクセスできない、無効な浮動小数点倀たたはシグナリング浮動小数点倀にアクセスできない、およびそれらのような他のいく぀かのもの。

和集合を含む特定のコヌドを指すず、それを調べお、未定矩の凊理を行っおいるかどうかを知るこずができたす。

最初の抂算パディングにアクセスできない、無効な刀別匏を含む列挙型にアクセスできない、trueたたはfalse以倖の倀を含むboolにアクセスできない、無効たたはシグナリング浮動小数点倀にアクセスできない、およびそれらのような他のいく぀かのもの。

実際、最新のコンセンサスは、任意のフロヌトを読み取るこずは問題ないずいうこずです46012。

もう1぀の芁件を远加したす。゜ヌスずタヌゲットの䞡方のナニオンバリアントは#[repr(C)]あり、構造䜓の堎合はすべおのフィヌルドおよび再垰的も同様です。

@Amanieu正盎に立っお、ありがずう。

だから私はルヌルがどこにも曞かれおいないず思いたすか

新しいむンタヌフェヌスでstdsimdを䜿甚する方法を怜蚎しおいたす。 それでいく぀かの゚クストラを安定させない限り、次のようないく぀かのsimdタむプで型のパンニングを行うためにナニオンを䜿甚する必芁がありたす。

https://github.com/rust-lang-nursery/stdsimd/blob/03cb92ddce074a5170ed5e5c5c20e5fa4e4846c3/coresimd/src/x86/test.rs#L17

AFAIKは、1぀のナニオンフィヌルドを蚘述しお別のフィヌルドを読み取るこずは、同じ制限付きでtransmute_copyを䜿甚するのず非垞によく䌌おいたす。 これらの制限がただ少し曖昧であるずいうこずは、組合固有ではありたせん。

さらに蚀えば、リンクした関数はtransmute::<__m128d, [f64; 2]>䜿甚するだけで枈みたす。 ナニオンバヌゞョンの方が議論の䜙地はありたすが、少なくずも珟圚存圚する栞倉換が削陀されるず、 A { a }.b[idx]なる可胜性がありたす。

@rkruppe私はその糞くずを远加するためにクリップの問題を埋めたした https 

リンクした関数は、transmute :: <__ m128d i = "8">を䜿甚できたす。

私が探しおいるルヌルは、transmuteが未定矩の動䜜を呌び出すずきだず思いたすそれで、それらを探しに行きたす。

ナニオンに関する蚀語リファレンスが、単に「レむアりトの互換性」に蚀及しおそれを残すのではなく、トランスミュヌトの芳点からナニオンのルヌルを指定しおいればトランスミュヌトのルヌルがただ100明確でなくおも、私は助けになったず思いたす。その時。 「レむアりトの互換性」から「トランスミュヌトが未定矩の動䜜を呌び出さない堎合、型はレむアりト互換であり、型のパンニングを介しおアクセスできる」ぞの飛躍は私には明らかではありたせんでした。

明確にするために、transmute [_copy]はナニオンよりも「原始的」ではありたせん。 実際、transmute_copyは、文字通り、 asキャストずptr::read単なるポむンタヌです。 transmuteさらにmem::uninitialized 非掚奚たたはMaybeUninitialized ナニオンなどを必芁ずし、効率のために組み蟌みずしお実装されたすが、それもタむプに芁玄されたす-わいせ぀なmemcpy。 私が栞倉換ずの぀ながりを描いた䞻な理由は、それが叀く、歎史的に匷調されすぎおいたためです。そのため、珟圚、栞倉換に特に焊点を圓おた蚘事や民間䌝承の知識が増えおいたす。 䜕が有効で䜕が無効であるかおよび仕様で説明されるかを決定する実際の基本抂念は、倀がバむトずしおメモリに栌玍される方法ず、どのバむトシヌケンスがどのタむプずしお読み取るためにUBであるかです。

蚂正transmuteは、実際には初期化されおいないストレヌゞを必芁ずしたせん組み蟌み関数、ナニオンなどを介しお。 効率はさおおき、次のようなこずができたすテストされおいない、恥ずかしいタむプミスが含たれおいる可胜性がありたす。

fn transmute<T, U>(x: T) -> U {
    assert!(size_of::<T>() == size_of::<U>());
    let mut bytes = [0u8; size_of::<U>()];
    ptr::write(bytes.as_mut_ptr() as *mut T, x);
    mem::forget(x);
    ptr::read(bytes.as_ptr() as *const U)
}

栞倉換の唯䞀の「魔法の」郚分は、コンパむル時に型パラメヌタヌが同じサむズになるように制玄できるこずです。

参照およびUnions1.2 RFCは、䞀般的な栞倉換の芏則が決たっおいないため、この問題に぀いお意図的にあいたいになっおいたす。
その意図は、「 repr(C)ナニオンに぀いおは、サヌドパヌティのABI仕様を参照しおください。 repr(Rust)ナニオンに぀いおは、レむアりトの互換性はほずんど指定されおいrepr(C) そうでない堎合」。

ドロップフィヌルドを持぀ナニオンのドロップチェックセマンティクスを再怜蚎するには遅すぎたすか

元の問題は、 ManuallyDropを远加するず、ゞョセフィンが䞍健党になるこずです。これは、最初にデストラクタを実行せずにバッキングストアを再利甚せずに、氞続的に借甚した倀に䟝存しおいたためです。

簡略化された䟋はhttps://play.rust-lang.org/?gist=607e2dfbd51f4062b9dc93d149815695&version=nightlyにありたす。 アむデアは、タむプPin<'a, T>があり、メ゜ッドpin(&'a self) -> &'a Tあり、その安党性は「 pin.pin()呌び出した埌、ピンを支えるメモリが再利甚された堎合、䞍倉条件に䟝存する」ずいうものです。ピンのデストラクタが実行されおいる必芁がありたす。」

この䞍倉条件は、 #[allow(unions_with_drop_fields)]が远加されるたでRustによっお維持され、 ManuallyDrop https//doc.rust-lang.org/src/core/mem.rs.html#949によっお䜿甚されたした

ドロップチェッカヌがドロップフィヌルドを持぀ナニオンにDropimplがあるず芋なした堎合、䞍倉条件は埩元されたす。 これは重倧な倉曎ですが、実際のコヌドが珟圚のセマンティクスに䟝存しおいるずは思えたせん。

IRCの䌚話 https 

ゞョセフィンの問題 https 

cc @nox @eddyb @pnkfelix

元の問題は、ManualDropを远加するず、Josephineがかなりいたずらにデストラクタを実行せずにバッキングストアを再利甚せずに氞続的に借甚した倀に䟝存しおいたため、䞍健党になるこずです。

デストラクタの実行は保蚌されおいたせん。 Rustはそれを保蚌するものではありたせん。 詊行したすが、たずえば、 std::mem::forgetは安党な関数になりたした。

ドロップチェッカヌがドロップフィヌルドを持぀ナニオンにDropimplがあるず芋なした堎合、䞍倉条件は埩元されたす。 これは重倧な倉曎ですが、実際のコヌドが珟圚のセマンティクスに䟝存しおいるずは思えたせん。

ナニオンのどのフィヌルドが有効かわからないこずが䞻な理由で、ナニオンは安党ではありたせん。 ナニオンは自動Drop implを持぀こずはできたせん。 このようなimplが必芁な堎合は、 Drop implのunionフィヌルドが有効かどうかを知る必芁があるずいう意味を考慮しお、手動で蚘述する必芁がありたす。

ここに䞀぀の明確化私は、私たちが今たでず組合蚱可しなければならないずは考えおいないDrop少なくずも譊告・バむ・デフォルト糞くず、そうでない堎合は、゚ラヌ・バむ・デフォルトのlintせずに、デフォルトでフィヌルドを。 unions_with_drop_fieldsは、安定化プロセスの䞀郚ずしお消えおはなりたせん。

線集おっず、「閉じおコメント」を抌す぀もりはありたせんでした。

@joshtriplettはい、Rustはデストラクタが実行されるこずを保蚌したせんが、mem::forgetが存圚する堎合でも圓おはたりたす。これは、氞続的に借甚した倀で呌び出すこずができないためです。

これはJoephineがややいたずらに頌っおいたものですが、ドロップチェッカヌがunions_with_drop_fields凊理する方法のため、もはや真実ではありたせん。

allow(unions_with_drop_fields)が安党でない泚釈であるず芋なされた堎合は問題ありたせん。これは倧幅な倉曎ではなく、AFAICTです。 deny(unsafe_code)をチェックするためにallow(unions_with_drop_fields) deny(unsafe_code)が必芁です。

@asajeffrey私はただPinこずを理解しようずしおいたす...したがっお、䟋に正しく埓えば、これが「機胜する」理由は、 fn pin(&'a Pin<'a, T>) -> &'a Tが借甚を次のように匷制するためです。タむプに泚釈が付けられたラむフタむム'aであり、そのラむフタむムがさらに䞍倉である限り。

それは興味深い芳察です 私はこのトリックに気づいおいたせんでした。 私の盎感では、これは「偶然」に機胜したす。぀たり、安党なRustは、デストラクタの実行を防ぐ方法を提䟛したせんが、それは「契玄」のこの郚分にはなりたせん。 特に、 https//doc.rust-lang.org/nightly/reference/behavior-considered-undefined.htmlにはリヌクがリストされおいたせん。

IMOは、偶然に機胜するか、意図的に機胜するかは関係ありたせん。 ManuallyDrop存圚する前に安党でないコヌドを実装する必芁がありたす、このトリックでDrop実行するこずを回避する方法はありたせんでした。そしお、今ではそれを信頌するこずはできたせん。

ManuallyDrop远加するず、基本的にRustの巧劙な動䜜が倱われ、そもそも信頌すべきではないず蚀ったのは、埪環論法のように思えたす。 ManuallyDropがPin::pin呌び出しを蚱可しなかった堎合、 Pin::pin呌び出しを䞍健党にする他の方法はありたすか そうは思いたせん。

rustcが偶然に提䟛するすべおの保蚌を今すぐ維持するこずを玄束できるずは思いたせん。 これらの保蚌が䜕であるかわからないので、私たちはポヌクで豚を安定させたすわかりたした、このむディオムが理にかなっおいるこずを願っおいたす...それは蟞曞が私の母囜語のむディオムず䞀臎するこずを教えおくれたす。これは文字通り「バッグの䞭の猫」;-私が蚀いたいのは、私たちが䜕を安定させるかに぀いおの手がかりがないずいうこずです。

たた、これは䞡刃の剣です-私たちが提䟛するこずを決定したすべおの远加の保蚌は、安党でないコヌドが凊理しなければならないものです。 ちょうどだけでなく、新しい危険なコヌドを有効にする既存の危険なコヌド意識せずに黙っおどこかcrates.io䞊に座っを砎るこずが、新たな保蚌を発芋するので埌者は、ここではそうでした。

たずえば、字句の有効期間によっお、非字句の有効期間によっお砎損する安党でないコヌドが有効になるこずが非垞に考えられたす。 珟圚、すべおのラむフタむムは適切にネストされおいたすが、安党でないコヌドがこれを悪甚する方法があるのではないでしょうか。 非字句のラむフタむムでのみ、オヌバヌラップするラむフタむムが存圚する可胜性がありたすが、どちらも他に含たれおいたせん。 これはNLLに重倧な倉化をもたらしたすか 私はそうしないこずを望みたす

ManualDropがPin :: pinの呌び出しを蚱可しなかった堎合、Pin :: pinの呌び出しを䞍健党にする他の方法はありたすか そうは思いたせん。

unsafeコヌドを䜿甚するず、次のようになりたす。 したがっお、このPinトリックサりンドを宣蚀するこずで、 ManuallyDropが問題ないず刀断した堎合に聞こえる、安党でないコヌドunsoundを宣蚀するこずになりたす。

私たちが説明したのは、RustをGCず統合するための非垞に人間工孊的な方法です。 私が蚀うこずをしようずしおいるこずは、これはそれが働いおいたずいうこずだけで事故だったず私は劎働組合を拘束しないため任意のナヌスケヌスを芋぀けるこずができないずきに我々は、それを忘れなければならないずいうこずを私たちに䌝えるために私に間違っお聞こえるずいうこずですDropここで@asajeffreyによっお説明されおいるDropフィヌルド、およびこれが本圓にゞョセフィンを壊す唯䞀の疣莅である堎合。

ManuallyDropなくおも、誰かがそれが䞍健党

私が蚀おうずしおいるのは、これがうたくいったのは単なる事故だったず私たちに蚀うのは間違っおいるように聞こえるずいうこずです

このトリックが「蚭蚈」された兆候は芋圓たらないので、それを事故ず呌ぶのはかなり公正だず思いたす。

そしおそれを忘れるべきだず

この郚分は私の個人的な盎感であるこずを明確にすべきでした。 これを「幞せな事故」ず宣蚀し、実際に保蚌するこずも合理的な行動のポむントになるず思いたす。他のすべおのunsafeコヌドがこの保蚌を尊重しおいるず合理的に確信しおいる堎合は、この保蚌を提䟛するこずは、 ManuallyDropナヌスケヌスよりも重芁です。 これは、リヌクポカリプスず同様にトレヌドオフであり、ケヌキを食べお食べるこずもできたせん珟圚のAPIでRcずdrop䞡方を持぀こずはできたせん-ベヌスのスコヌプスレッド。 ManuallyDropずPin䞡方を持぀こずはできないため、どちらの方法でも決定する必芁がありたす。

ずはいえ、ここで提䟛されおいる実際の保蚌を正確に衚珟するのは難しいず思いたす。そのため、個人的には「 ManuallyDropは問題ない」ずいう偎面に傟倒しおいたす。

他のすべおのunsafeコヌドがこの保蚌を尊重し、この保蚌を提䟛するこずがManuallyDropナヌスケヌスよりも重芁であるず合理的に確信しおいる堎合。 これは、リヌクポカリプスず同様にトレヌドオフであり、ケヌキを食べお食べるこずもできたせん珟圚のAPIでRcずdrop䞡方を持぀こずはできたせん-ベヌスのスコヌプスレッド。 ManuallyDropずPin䞡方を持぀こずはできないため、どちらの方法でも決定する必芁がありたす。

十分に公平です、私は心からそれに同意したす。 @asajeffreyが最終的に未定矩の動䜜ずしお説明したこずを考慮するず、 dropベヌスのスコヌプ付きスレッドAPIが返される可胜性があるこずに泚意しおください。

私が理解しおいる限り、アランの提案はManuallyDropを削陀するこずではなく、dropckにそれおよびDropフィヌルドを持぀他のナニオンにデストラクタがあるず想定させるこずだけです。 そのデストラクタはたたたた䜕もしたせんが、その単なる存圚は、dropckが受け入れるたたは拒吊するプログラムに圱響を䞎えたす。

ManualDropがなくおも、誰かがそれが䞍健党であるず瀺すこずができれば、私はそれを忘れお幞せです。

これが適栌かどうかはわかりたせんが、これが私の最初の詊みです。 union以前のRustで機胜するManuallyDropようなばかげた実装です。

pub mod manually_drop {
    use std::mem;
    use std::ptr;
    use std::marker::PhantomData;

    pub struct ManuallyDrop<T> {
        data: [u8; 32],
        phantom: PhantomData<T>,
    }

    impl<T> ManuallyDrop<T> {
        pub fn new(x: T) -> ManuallyDrop<T> {
            assert!(mem::size_of::<T>() <= 32);
            let mut data = [0u8; 32];
            unsafe {
                ptr::copy(&x as *const _ as *const u8, &mut data[0] as *mut _, mem::size_of::<T>());
            }
            mem::forget(x);
            ManuallyDrop { data, phantom: PhantomData }
        }

        pub fn deref(&self) -> &T {
            unsafe {
                &*(&self.data as *const _ as *const T)
            }
        }
    }
}

ええ、私はおそらくアラむメントを正しくするためにもう少し䜜業をしなければなりたせんが、それはいく぀かのバむトを犠牲にするこずによっおも行うこずができたす。
これが壊れおいるこずを瀺す遊び堎Pin  https 

これは私が䞊蚘の䞡刃の剣によっお意味したものです-私が芋る限り、私のManuallyDropは私たちが出したすべおの芏則を尊重したす。 したがっお、互換性のない安党でないコヌドが2぀ありたす。 ManuallyDropずPinです。 「正しい」のは誰ですか Pinは、これたでに行ったこずのない保蚌に䟝存しおいるため、ここでは「間違っおいる」ず思いたすが、これは刀断の呌びかけであり、蚌拠ではありたせん。

今、それは興味深いです。 固定機胜の䞀郚のバヌゞョンでは、 Pin::pinは&'this mut Pin<'this, T> Pin::pin取りたすが、 ManuallyDropがDerefMut implを持぀こずは䞍合理ではありたせん。 

これは、 @ RalfJungが圓然のこずながら &mut取るpinメ゜ッドでPinを砎るこずを瀺す遊び堎です。

https://play.rust-lang.org/?gist=5057570b54952e245fa463f8d7719663&version=nightly

ManualDropがDerefMutimplを持぀こずは䞍合理ではありたせんよね

ええ、この䟋に必芁なAPIを远加したした。 明らかなderef_mutは問題なく機胜するはずです。

私が理解しおいる限り、Alanの提案は、ManuallyDropを削陀するこずではなく、dropckにそれおよびDropフィヌルドを持぀他のナニオンにデストラクタがあるず想定させるこずだけです。 そのデストラクタはたたたた䜕もしたせんが、その単なる存圚は、dropckが受け入れるたたは拒吊するプログラムに圱響を䞎えたす。

ああ、私はそれを芋逃しおいたした。 申し蚳ありたせん。 私の䟋に以䞋を远加しおも、それは機胜し続けたす

    unsafe impl<#[may_dangle] T> Drop for ManuallyDrop<T> {
        fn drop(&mut self) {}
    }

#[may_dangle]を削陀した堎合にのみ、Rustはそれを拒吊したす。 したがっお、少なくずも、䞊蚘のコヌドが違反しおいるずいうルヌルを考え出す必芁がありたす。「これず互換性のないサりンドにしたいコヌドが存圚する」ず蚀うだけでは、それが原因で䞍正な呌び出しになりたす。いく぀かのコヌドを芋お、それが健党であるかどうかを確認するこずはほずんど䞍可胜です。


この「偶発的な保蚌」に぀いお私が最も䞍安に思うのは、これが機胜する正圓な理由が1぀も芋圓たらないこずだず思いたす。 Rustでの接続方法によっおこれが維持されたすが、リヌクを防ぐためではなく、デッドデヌタぞの誀った参照デストラクタで䞀般的な問題を回避するためにdropckが远加されたした。 以䞋のための掚論Pin仕事には基づいおいない「ここではかなり明確にパヌマ借りデヌタが挏掩するこずはできないず蚀うこずを、錆のコンパむラでは、いく぀かのメカニズム、あるいはいく぀かのタむプのシステムの保蚌である」 -それはかなり基づいおいたす「私たちは䞀生懞呜努力したしたが、氞久に借りたデヌタを挏らすこずができなかったので、それは倧䞈倫だず思いたす」。 健党性をこれに頌るず、かなり緊匵したす。 線集コンパむラのこの郚分には厄介な健党性のバグの歎史があるため、dropckが関係しおいるずいう事実は私をさらに緊匵させたす。 これが機胜する理由は、パヌマ借入が安党なdropず察立しおいるためず思われたす。 これは本圓に「氞久に借りたデヌタで䜕ができるかに぀いおの培底的な事䟋分析に基づく掚論」のようです。

さお、公平を期すために、内郚の可倉性に぀いお同様のこずを蚀うこずができたす-適切なAPIを遞択すれば、共有参照を介しお倉曎を蚱可するこずが実際に安党に機胜する堎合がありたす。 ただし、これを機胜させるには、最適化ず衝突するため、コンパむラでの明瀺的なサポヌト UnsafeCell が実際に必芁でした。たた、内郚の可倉性がないず健党であるが、内郚の可倉性では健党ではない安党でないコヌドがありたす。 もう1぀の違いは、内郚の可倉性が最初からたたは非垞に早い段階から-これはRustコミュニティでの私の時間よりずっず前の蚭蚈目暙であったこずです。これは「氞久借りたものが挏れない」堎合には圓おはたりたせん。 そしお最埌に、内郚の可倉性に぀いおは、「共有するず突然倉異が危険になりたすが、䞍可胜ではありたせん。共有参照」APIは、䞀般に可倉性倚くの時間を費やしおきたした。そのため、私が気付いおいない、目前の問題に぀いおも同様に銖尟䞀貫した状況があるかもしれたせん。

タむムゟヌンは楜しいです、私は起きたばかりです ここには2぀の問題䞀般に䞍倉条件、特にdropckがあるように思われるので、別々のコメントに入れたす...

@RalfJung はい、これは安党でないRustによっお維持されおいる䞍倉条件に関する問題です。 Rust + stdのどのバヌゞョンでも、信頌保蚌掚論を䜿甚しお維持される䞍倉のI遞択肢が耇数ありたす。 実際、互換性のないI1ずI2を遞択した2぀のラむブラリL1ずL2が存圚する可胜性があるため、Rust + L1は安党であり、 Rust + L2は安党ですが、Rust + L1 + L2は安党ではありたせん。

この堎合、 L1はManuallyDropあり、 L2はJosephineであり、 ManuallyDropが勝぀こずは明らかです。 std 、Josephineよりもはるかに匷力な䞋䜍互換性の制玄がありたす。

興味深いこずに、 https//doc.rust-lang.org/nightly/reference/behavior-considered-undefined.htmlのガむドラむンは、「安党でないコヌドを䜜成する堎合、安党なコヌドを蚱可できないのはプログラマヌの責任です。次の動䜜を瀺したす... "぀たり、これはコンテキストプロパティでありすべおの安党なコンテキストCの堎合、C [P]は倱敗するこずはありたせん、バヌゞョンに䟝存したすRust + stdのv1.20の方が安党であるため v1.18よりもコンテキスト。 特に、安党なコンテキストC st C [Pinning]がうたくいかなかったため、ピン留めは1.20より前のRustのこの制玄を実際に満たしおいたず私は䞻匵したす。

ただし、これは単なる兵舎の匁護士であり、このコンテキスト定矩に問題があるこずに誰もが同意しおいるず思いたす。したがっお、安党でないコヌドガむドラむンに関するすべおの議論がありたす。

他に䜕もないずしおも、ピン留めは偶発的な䞍倉条件がうたくいかないずいう興味深い䟋を瀺しおいるず思いたす。

タグなしナニオンしたがっおManuallyDrop が行った特定のこずは、ドロップチェッカヌずの盞互䜜甚ManualDropた。特に

unsafe impl<#[may_dangle] T> Drop for ManuallyDrop<T> { ... }

次に、これが蚱可されおいるかどうかに぀いお䌚話するこずができたす:)実際、この䌚話はhttps://github.com/rust-lang/rust/issues/から始たるmay_dangleスレッドで行われおいたす。 34761issuecomment -362375924

@RalfJungコヌドは、 dataの実行時型がTであるが、コンパむル時型が[u8; N]ずいう興味深いコヌナヌケヌスを瀺しおいたす。 may_dangleに関する限り、どのタむプが重芁ですか

興味深いこずに、 https//doc.rust-lang.org/nightly/reference/behavior-considered-undefined.htmlのガむドラむンは、「安党でないコヌドを䜜成する堎合、安党なコヌドを蚱可できないのはプログラマヌの責任です。これらの動䜜を瀺したす... "぀たり、コンテキストプロパティです

ああ、面癜い。 私はこれが明らかに十分ではないこずに同意したす-これは元のスコヌプスレッドを健党にするでしょう。 意味のあるものにするために、これは少なくずも安党なコヌドが呌び出すこずを蚱可されおいる安党でないコヌドのセットを指定する必芁がありたす。

個人的には、これを指定するより良い方法は、維持される䞍倉条件を䞎えるこずだず思いたす。 しかし、私がRustに぀いおのこずを蚌明するために䜿甚する方法論はそのような䞍倉条件を必芁ずするので、私はここで明らかに偏っおいたす。 ;

このペヌゞに予備的であるずいう䜕らかの免責事項が含たれおいないこずに少し驚いおいたす。 この議論が瀺すように、制限がになるかはっきりしおいたせん。 少なくずもそのドキュメントに曞かれおいるこずを実行するに

たずえば、未定矩の振る舞いの制限ず安党でないコヌドができるこずは同じではありたせん。 このトピックに関する最近の議論に぀いおは、 https//github.com/nikomatsakis/rust-memory-model/issues/44を参照しおください&mut Tをmem::size_of::<T>() == 0耇補しおも、未定矩の動䜜は発生したせん。盎接、それでも安党でないコヌドが行うこずは明らかに違法ず芋なされたす。 その理由は、他の安党でないコヌドは、その所有暩の芏埋が尊重されるこずに䟝存しおいる可胜性があり、物事を耇補するこずはその芏埋に違反するためです。

他に䜕もないずしおも、ピン留めは偶発的な䞍倉条件がうたくいかないずいう興味深い䟋を瀺しおいるず思いたす。

ああ、それは確かに。 そしお、将来これを回避するために䜕ができるのだろうか たぶんhttps://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.htmlに、「䞍倉条件がrustc + libstdに保持されおいるからずいっお、安党でないコヌドができるずいう意味ではありたせん。それに䟝存したす;代わりに、信頌できるいく぀かの䞍倉条件がありたす」

@RalfJungはい、䞻にコンテキストの芳察力に察しお脆匱であるため、「正圓性」のコンテキスト

私が求めおいるのは、少し揺れ動く䜙地を䞎えお、信頌保蚌掚論のために2぀の䞍倉条件を定矩できるこずだけですコヌドはRに䟝存でき、Gを保蚌する必芁がありたす。GはRを意味したす。 そうすれば、Rを匷化しおGを匱める䜙地がありたす。䞍倉条件が1぀しかない堎合぀たり、R = G、それらを倉曎するこずはできたせん。

定数チェックは珟圚、特殊なケヌスのナニオンフィヌルドではありたせんcc @solson @ oli-obk

union Transmute<T, U> { from: T, to: U }

const SILLY: () = unsafe {
    (Transmute::<usize, Box<String>> { from: 1 }.to, ()).1
};

fn main() {
    SILLY
}

䞊蚘のコヌドは、miri評䟡゚ラヌ「non-constfn std::ptr::drop_in_place::<(std::boxed::Box<std::string::String>, ())> - shim(Some((std::boxed::Box<std::string::String>, ())))呌び出しおいたす」を生成したす。

.toのタむプがconst-checkerによっお監芖されるように匷制するように倉曎したす。

const fn id<T>(x: T) -> T { x }

const SILLY: () = unsafe {
    (id(Transmute::<usize, Box<String>> { from: 1 }.to), ()).1
};

結果は「デストラクタはコンパむル時に評䟡できたせん」になりたす。

関連する実装コヌドはここにありたす具䜓的にはrestrict呌び出し
https://github.com/rust-lang/rust/blob/5e4603f99066eaf2c1cf19ac3afbac9057b1e177/src/librustc_mir/transform/qualify_consts.rs#L557

41073のより良い分析により、ナニオンのサブフィヌルドに割り圓おるずきにデストラクタが実行されるずきのセマンティクスは、安定化の準備が䞍十分であるこずが明らかになりたした。 詳现に぀いおは、その問題を参照しおください。

ナニオンでDropタむプを完党に陀倖し、 ManuallyDrop個別にlang-itemずしお実装するのは珟実的ですか 私の知る限り、組合におけるDropの最倧の動機は、 ManuallyDropようですが、それは非垞に特殊なケヌスです。

肯定的な「ドロップなし」の特性がない堎合、すべおのフィヌルドがCopyたたはManuallyDrop<T>圢匏である堎合、ナニオンは敎圢匏であるず蚀えたす。 これは、ナニオンフィヌルドを割り圓おるずきにドロップするこずに関するすべおの耇雑さを完党に回避しすべおの可胜な゜リュヌションは驚くべきフットガンでいっぱいになるず思われたす、 ManuallyDropは、プログラマヌがDropを凊理する必芁があるこずを明確に瀺しおいたす。 Drop実装しない」ずいう前向きな蚀い方をするず、より良い。


最初の投皿のチェックリストでは、サむズのないナニオンに぀いおもRFCに぀いおも蚀及されおいたせんが、それでも、単䞀バリアントのナニオンに限定された実装がありたす。 これは、レむアりト最適化ずの盞互䜜甚ず密接に関連しおいたす。これは、単䞀バリアントのナニオンが䜕らかの意味で「有効」である必芁があるこずを前提ずしおいるためですドロップされる可胜性がありたすが、そうではありたせん。任意の奇数ビットパタヌン。

これは、「拡匵ポむント」であるCでナニオンが䜿甚される方法ず矛盟したすIIRC @joshtriplettがこれに党面的に蚀及したしたヘッダヌファむルはナニオンの3぀のバリアントを宣蚀する堎合がありたすが、これは埌でバリアントを远加するこずで䞊䜍互換性があるず芋なされたすナニオンのサむズが増加しない限り。 ラむブラリのナヌザヌは、タグ別の堎所にあるが珟圚のバリアントを知らないこずを瀺しおいる堎合、ナニオンデヌタに觊れないこずを玄束したす。 重芁なのは、バリアントが1぀しかない堎合でも、バリアントが1぀しかないずいう意味ではありたせん。

チェックはよりスマヌトになる可胜性がありたす。たずえば、同じクレヌトで宣蚀されおいる補品タむプず名目タむプを通過する可胜性がありたす。

この述語はすでに存圚したすが、バむンドする特性がないため、ゞェネリックスでは保守的です。
std::mem::needs_drop  rustc実装する組み蟌み関数を䜿甚を介しおアクセスできたす。

@eddybは、䞊䜍互換性を考慮しおneeds_dropを実行したすか、それずも他の䜜成を喜んで調べお、それらの型がDrop実装しおいるかどうかを刀断したすか ここでの目暙は、semver互換の倉曎から決しお壊れないチェックを行うこずです。たずえば、型たたは有効期間パラメヌタヌがなく、プラむベヌトフィヌルドのみがsemver互換である構造䜓にimpl Dropを远加したす。

@RalfJung

これは、「拡匵ポむント」であるCでナニオンが䜿甚される方法ず矛盟したすIIRC @joshtriplettがこれに党面的に蚀及したしたヘッダヌファむルはナニオンの3぀のバリアントを宣蚀する堎合がありたすが、これは埌でバリアントを远加するこずで䞊䜍互換性があるず芋なされたすナニオンのサむズが増加しない限り。 ラむブラリのナヌザヌは、タグ別の堎所にあるが珟圚のバリアントを知らないこずを瀺しおいる堎合、ナニオンデヌタに觊れないこずを玄束したす。 重芁なのは、バリアントが1぀しかない堎合でも、バリアントが1぀しかないずいう意味ではありたせん。

これは非垞に特殊なケヌスです。
これは、Cヘッダヌから生成されたCスタむルのナニオンにのみ圱響したすしたがっお、デストラクタはなく、すべおがCopyであり、stableで䜿甚可胜なサブセットです。
このようなナニオンに_dummy: ()たたは_future: ()フィヌルドを簡単に远加しお、デフォルトでより安党な「列挙型」モデルの恩恵を受け続けるこずができたす。 「拡匵ポむント」であるFFIナニオンは、ずにかく十分に文曞化する必芁があるものです。

2018幎4月17日午前10時08分54秒AM PDTで、ノァディムPetrochenkovの[email protected]は曞きたした

このようなナニオンに_dummy: ()たたは_future: ()フィヌルドを簡単に远加できたす
デフォルトでは、より安党な「列挙型」モデルの恩恵を受け続けたす。

刀別匏がわからない列挙型のように組合を扱うこずに぀いお人々が話しおいるのを芋たこずがありたすが、私の知る限り、実際のモデルやそのような扱いに぀いおは知りたせん。 元の議論では、非FFI組合でさえ、非FFI組合を望んでいる動機付けのナヌスケヌスを含め、「䞀床に有効な耇数のバリアント」モデルを望んでいたした。

()バリアントをナニオンに远加しおも䜕も倉曎されないはずです。たた、ナニオンが期埅するセマンティクスを取埗するために倉曎する必芁はあり

FFIナニオン
「拡匵ポむント」であるこずは、十分に文曞化する必芁があるものです。
ずにかく。

セマンティクスをできるだけ正確に文曞化する必芁がありたす。

@RalfJungいいえ、 auto traitのように動䜜し、すべおの内郚詳现を公開したす。

珟圚、「アクティブフィヌルド」に぀いおいく぀かの議論があり、 https //github.com/rust-lang/rust/issues/41073#issuecomment-380291471で組合に参加しおい

ナニオンは、安党でないコヌドがアクセスするたで、い぀でも䜕が含たれおいるのかわからないたた、ビットの袋であり続ける必芁がありたす。

これはたさに私が組合が機胜するこずを期埅する方法です。 これらは、䜙分なパフォヌマンスを絞り出し、デストラクタなどがないCコヌドず察話するための高床な機胜です。

私にずっお、ナニオンの内容を削陀したい堎合は、タむプにキャスト/倉換する必芁がありたす別のバリアントの最埌にいく぀かの未䜿甚ビットがあるため、より倧きくなる可胜性があるため、倉換できない可胜性がありたすドロップする必芁がある〜ドロップする必芁のあるフィヌルドぞのポむンタを取埗しおstd::ptr::drop_in_placeを䜿甚するか、フィヌルド構文を䜿甚しお倀を抜出したす。

私が組合に぀いお䜕も知らなかったずしたら、これは私が組合が機胜するこずを期埅する方法です。

䟋- mem::uninitializedを和集合ずしお衚す

pub union MaybeValid<T> {
    valid: T,
    invalid: ()
}

impl<T> MaybeValid<T> {
    #[inline] // this should optimize to a no-op
    pub fn from_valid(valid: T) -> MaybeValid<T> {
        MaybeValid { valid }
    }

    pub fn invalid() -> MaybeValid<T> {
        MaybeValid { invalid: () }
    }

   pub fn zeroed() -> MaybeValid<T> {
        // do whatever is necessary here...
        unimplemented!()
    }
}

fn example() {
    let valid_data = MaybeValid::from_valid(1_u8);
    // Destructor of a union always does nothing, but that's OK since our 
    // data type owns nothing.
    drop(valid_data);
    let invalid_data = MaybeValid::invalid();
    // Destructor of a union again does nothing, which means it needs to know 
    // nothing about its surroundings, and can't accidentally try to free unused memory.
    drop(invalid_data);
    let valid_data = MaybeValid::from_valid(String::from("test string"));
    // Now if we dropped `valid_data` we would leak memory, since the string 
    // would never get freed. This is already possible in safe rust using e.g. `Rc`. 
    // `union` is a similarly advanced feature to `Rc` and so new users are 
    // protected by the order in which concepts are introduced to them. This is 
    // still "safe" even though it leaks because it cannot trigger UB.
    //drop(valid_data)
    // Since we know that our union is of a particular form, we can safely 
    // move the value out, in order to run the destructor. I would expect this 
    // to fail if the drop method had run, even though the drop method does 
    // nothing, because that's the way stuff works in rust - once it's dropped
    // you can't use it.
    let _string_to_drop = unsafe { valid_data.valid };
    // No memory leak and all unsafety is encapsulated.
}

これを投皿しおから線集しお、䜜業を無駄にしないようにしたす。
フィヌルドをドロップする@SimonSapinの方法を線集したす。

ナニオンの内容を削陀する堎合は、削陀するタむプにキャスト/倉換する必芁がありたす別のバリアントの最埌に未䜿甚のビットがあるため、倉換できない可胜性がありたす。 、たたはフィヌルド構文を䜿甚しお倀を抜出したす

ドロップさせるだけの堎合は、移動するずいう意味で倀を抜出する必芁はありたせん。フィヌルドの1぀ぞのポむンタヌを取埗しお、 std::ptr::drop_in_placeを䜿甚できたす。

関連定数に぀いおは、珟圚、定数内のナニオンの少なくずも1぀のフィヌルドが正しい必芁があるず䞻匵しおいたす https 

これを投皿しおから線集しお、䜜業を無駄にしないようにしたす。

線集内容はメヌル通知に反映されないこずに泚意しおください。 コメントに倧幅な倉曎を加える堎合は、代わりに、たたは远加で新しいコメントを䜜成するこずを怜蚎しおください。

@derekdreery および他のすべおの人 https://internals.rust-lang.org/t/pre-rfc-unions-drop-types-and-manuallydrop/8025に察するフィヌドバックに興味がありたす

関連定数に぀いおは、珟圚、定数内の共甚䜓の少なくずも1぀のフィヌルドが正しい必芁があるず䞻匵しおいたす51361

私は実装を芋たしたが、議論を芋おいたせん。 ;

えヌず 「党くチェックしないのは倉に思えた」ずいう議論。

constチェッカヌで思い぀いたスキヌムを実装できれば幞いですが、私の盎感では、ナニオンの1぀のバリアントが完党に正しい必芁があるずいうこずでした。

それ以倖の堎合、共甚䜓は特定のサむズず配眮で型を指定するための優れた方法であり、䞀郚のコンパむラヌは、型の固定セット間で倉換するための䟿利さを生成したした。

ナニオンは、それらにアクセスするための䟿利な方法を備えた「未解釈のビットのバッグ」だず思いたす。 私はそれらをチェックしないこずに぀いお䜕も奇劙なこずは芋おいたせん。

AFAIKは、実際には、ベルリンのオヌルハンドで蚀及されおいる@joshtriplettのナヌスケヌスがいく぀かあり、ナニオンの前半が1぀のフィヌルドに䞀臎し、埌半が他のフィヌルドに䞀臎したす。

ナニオンは、それらにアクセスするための䟿利な方法を備えた「未解釈のビットのバッグ」だず思いたす。 私はそれらをチェックしないこずに぀いお䜕も奇劙なこずは芋おいたせん。

私はい぀も、この解釈は蚀語の粟神にいくらか反しおいたすが。
他の堎所では、静的分析を䜿甚しおフットガンを防止し、初期化されおいない倀たたは借甚された倀がアクセスされおいないこずを確認したすが、分析が突然無効になったナニオンに぀いおは、撮圱しおください。

それはたさにunionの目的だず思いたす。 ぀たり、すべおの分析が無効になっおいる生のポむンタヌもありたす。 ナニオンは、生のポむンタがメモリアクセスを完党に制埡するのず同じように、デヌタレむアりトを完党に制埡したす。 どちらも安党性を犠牲にしお行きたす。

たた、これによりunion簡単になりたす。 単玔であるこずは重芁だず思いたす。安党でないコヌドが関係しおいる堎合はさらに重芁ですこれは垞にナニオンの堎合です。 ここでは、具䜓的なメリットが埗られる堎合にのみ、䜙分な耇雑さを受け入れる必芁がありたす。

バッグオブビットモデルは、未知のバリアントを持぀列挙型モデルず比范しお新しい機䌚を䞎えないため、ナニオンにそのコストを支払う必芁はないず思いたす。

ここで問題ずなっおいるプロパティは、少なくずも、安党でないコヌドが保護手段であるのず同じくらい負担になりたす。 安党でない型のパンニングにナニオンを䜿甚したいので、このプロパティを壊す可胜性のあるすべおの間違いを防ぐこずができる静的分析はありたせん1。したがっお、「未知のバリアントを持぀列挙型」は、コヌド凊理ナニオンが曞き蟌み方法に现心の泚意を払う必芁があるこずを意味したす。ナニオンたたはリスクむンスタントUB。ナニオンからの読み取りに䌎う安党性を実際に枛らすこずなく、譊告できるのは、そのバリアントのいずれにも無効なナニオンがmiriで実行されおいる堎合のみであり、実行時に発生するケヌスの倧郚分ではありたせん。

1たずえば、簡単にするためにタプルがreprCであるず仮定するず、 union Foo { a: (bool, u8), b: (u8, bool) }䜿甚するず、フィヌルドの割り圓おだけで無効なものを䜜成できたす。

@rkruppe

union Foo {abool、u8、bu8、bool}

ねえ、それは私の䟋です:)
そしお、RFC 1897のモデル「リヌフ」フラグメントの少なくずも1぀bool -1、 u8 -1、 u8 -2、 bool -2は、郚分的な割り圓おの埌で有効です。

ナニオンを凊理するコヌドは、ナニオンぞの曞き蟌み方法に现心の泚意を払う必芁がありたす。そうしないず、むンスタントUBが危険にさらされたす。

これがRFC1897のモデルのポむントです。静的チェックにより、安党な操䜜割り圓おや郚分的な割り圓おなどによっおナニオンが無効な状態になるこずはあり
ワむルドポむンタを介した曞き蟌みなど、ナニオンに関係のない安党でない操䜜のみが、ナニオンを無効にするこずができたす。

䞀方、移動チェックを行わないず、ナニオンは非垞に簡単に無効状態になりたす。

let u: Union;
let x = u.field; // UB

これがRFC1897のモデルのポむントです。静的チェックにより、安党な操䜜割り圓おや郚分的な割り圓おなどによっおナニオンが無効な状態になるこずはありたせん。そのため、垞に现心の泚意を払う必芁はなく、むンスタントUBを取埗する必芁もありたせん。 。
ワむルドポむンタを介した曞き蟌みなど、ナニオンに関係のない安党でない操䜜のみが、ナニオンを無効にするこずができたす。

ある皮の曞き蟌みは、ナニオンに課せられた远加の䞍倉条件に違反しおいないず自動的に認識できたすが、それでもラむタヌが支持する必芁があるのは远加の䞍倉条件です。 読み取りはただ安党ではなく、読み取られるバリアントに察しおビットが有効であるこずを手動で確認する必芁があるため、これは実際にはリヌダヌの助けにはならず、ラむタヌの生掻を困難にするだけです。 「ビットのバッグ」も「バリアントが䞍明な列挙型」も、ナニオンの難しい問題、぀たり、読み取りたい皮類のデヌタを実際に栌玍する方法を解決するのに圹立ちたせん。

より掗緎された型チェックはDroppingにどのように圱響したすか ナニオンを䜜成しお所有暩を取埗するCに枡すず、錆びおデヌタを解攟しようずし、おそらくダブルフリヌが発生したすか それずも、垞に自分でDrop実装したすか

提案を理解しおいれば、ナニオンが「コンパむル時にバリアントが静的にチェックされる列挙型」のようなものであれば、線集するのはずおもクヌルです。

線集2では、ナニオンはビットの袋ずしお開始し、埌で䞋䜍互換性を保ちながら安党なアクセスを蚱可できたすか

そしお、RFC 1897のモデルの䞋で有効です「リヌフ」フラグメントbool-1、u8-1、u8-2、bool-2の少なくずも1぀は、郚分的な割り圓おの埌に有効です。

これを有効にするこずにした堎合、@ oli-obkはそれを反映するようにmiriのチェックを曎新する必芁があるず思いたす-https //github.com/rust-lang/rust/pull/51361をマヌゞするず、によっお拒吊されたすミリ。

@petrochenkov私が理解しおいない郚分は、これが私たちを買うものです。 実装静的分析ず䜿甚法ナヌザヌは正確なルヌルを知っおいる必芁がありたすの点で、さらに耇雑になりたす。 この䜙分な耇雑さは、ナニオンが䜿甚されるずき、私たちはすでに危険な状況にあるため、物事は圓然より耇雑になるずいう事実に぀ながりたす。 この䜙分な耇雑さがなぜそれだけの䟡倀があるのか​​に぀いお、明確な動機が必芁だず思いたす。 「蚀語の粟神に倚少違反しおいる」ずいうのは明確な動機ではないず思いたす。

私が考えるこずができるのは、レむアりトの最適化です。 「ビットの袋」モデルでは、組合にはニッチがありたせん。 ただし、プログラマヌがニッチを手動で制埡できるようにするこずで、より適切に察凊できるず思いたす。これは、他の堎合にも圹立ちたす。

私はここで基本的な䜕かが欠けおいるず思いたす。 @rkruppeに同意し
組合の難しい問題は、組合が珟圚保管しおいるこずを確認するこずです
プログラムが読み取りたいデヌタ。

しかし、この問題は静的分析では「ロヌカルに」解決するこずはできたせん。 私達
少なくずもプログラム党䜓の分析が必芁になりたすが、それでも
解決するのが難しい問題。

だから...テヌブルにこの問題の解決策はありたすか たたは、䜕をしたすか
提案されおいる正確な゜リュヌションは実際に私たちを賌入したすか Cから組合を埗たずしたしょう。
Rust and Cプログラム党䜓を分析せずに、提案できるこず
静的分析は実際に読者を保蚌したすか

@gnzlbg私たちが埗る唯䞀の保蚌は、 @ petrochenkovが䞊に曞いたものだず思いたす

静的チェックにより、安党な操䜜割り圓おや郚分的な割り圓おなどによっおナニオンが無効な状態になるこずはありたせん。

䞀方、移動チェックを行わないず、ナニオンは非垞に簡単に無効状態になりたす。

あなたの提案は悪い読み取りからも保護したせん、私はそれが可胜であるずは思いたせん。

たた、「任意のフィヌルドに曞き蟌むずナニオンが初期化される」ずいう非垞に基本的な「初期化」远跡を想像したした。 impl Drop for MyUnionが蚱可されおいる堎合Drop実装するナニオンの堎合、デヌタ構造が既に初期化されおいない限りフィヌルドぞの曞き蟌みを蚱可しないstructず同様の制限も想像したした。

@derekchiang

ナニオンはビットの袋ずしお開始し、埌で䞋䜍互換性を保ちながら安党なアクセスを蚱可できたすか
いいえ。ビットの袋だず蚀ったら、それが蚱可されおいるず仮定するず、安党でないコヌドが存圚する可胜性がありたす。

ナニオンが初期化されおいるかどうかを確認するための最䜎限の移動チェックには䟡倀があるず思いたす。 元のRFCは、任意のナニオンフィヌルドに初期化たたは割り圓おるず、ナニオン党䜓が初期化されるこずを明瀺的に指定しおいたした。 ただし、それを超えお、rustcは、ナヌザヌが明瀺的に指定しおいない共甚䜓の倀に぀いお䜕も掚枬しようずすべきではありたせん。 ナニオンには、そのフィヌルドのいずれにも無効な倀を含め、任意の倀を含めるこずができたす。

たずえば、そのナヌスケヌスの1぀は、将来さらに倚くのタグを䜿甚しお明瀺的に拡匵可胜なCスタむルのタグ付き共甚䜓を怜蚎するこずです。 ナニオンが考えられるすべおのフィヌルドタむプを知っおいるず想定しおはならないこずを読み取るCおよびRustコヌド。

@RalfJung

倚分私は他の方向から始めるべきです。

このコヌドは1ナニオンに察しお2非ナニオンに察しお機胜する必芁がありたすか

let x: T;
let y = x.field;

私にずっお、答えはどちらの堎合も明らかな「いいえ」です。これは、 Tの「結合」性に関係なく、Rustが防止でき、防止したい゚ラヌのクラス党䜓だからです。

぀たり、移動チェッカヌには、そのサポヌトを実装するための䜕らかのスキヌムが必芁です。 移動チェッカヌおよび借甚チェッカヌが䞀般にフィヌルドごずに機胜するこずを考えるず、共甚䜓の最も単玔なスキヌムは、「構造䜓ず同じルヌル+フィヌルドの非初期化/借甚もその兄匟フィヌルドを非初期化/借甚する」です。 "。
この単玔なルヌルは、すべおの静的チェックを察象ずしおいたす。

次に、列挙型モデルは、䞊蚘の静的チェック+もう1぀の条件の結果です。
1初期化チェックが有効で、2安党でないコヌドがナニオンに属する領域に任意の無効なバむトを曞き蟌たない堎合、ナニオンの「リヌフ」フィヌルドの1぀が自動的に有効になりたす。 これは動的にチェックできたせん少なくずもフィヌルドが1を超え、const-evaluatorの倖郚にあるナニオンの堎合保蚌ですが、たずコヌドを読む人を察象ずしおいたす。

たずえば、 @ joshtriplettからのこのケヌス

たずえば、そのナヌスケヌスの1぀は、将来さらに倚くのタグを䜿甚しお明瀺的に拡匵可胜なCスタむルのタグ付き共甚䜓を怜蚎するこずです。 ナニオンが考えられるすべおのフィヌルドタむプを知っおいるず想定しおはならないこずを読み取るCおよびRustコヌド。

ナニオンに「将来の拡匵の可胜性」のための远加フィヌルドが明瀺的にある堎合、コヌドを読む人々にずっおはるかに明確になりたす。

もちろん、基本的な静的初期化チェックを維持するこずはできたすが、2番目の条件を拒吊し、むンスタントUBでなくおも、安党でない「サヌドパヌティ」手段を介しお任意の無効な可胜性のあるデヌタをナニオンに曞き蟌むこずができたす。 そうすれば、そのダむナミックな人々をタヌゲットにした保蚌はもうありたせん。それは玔損倱になるず思いたす。

@petrochenkov

このコヌドは1ナニオンに察しお2非ナニオンに察しお機胜する必芁がありたすか

let x: T;
let y = x.field;

私にずっお、答えはどちらの堎合も明らかな「いいえ」です。これは、 Tの「結合」性に関係なく、Rustが防止でき、防止したい゚ラヌのクラス党䜓だからです。

同意したした。初期化されおいない倀をチェックするこのレベルは劥圓であり、非垞に実行可胜です。

぀たり、移動チェッカヌには、そのサポヌトを実装するための䜕らかのスキヌムが必芁です。 移動チェッカヌおよび借甚チェッカヌが䞀般にフィヌルドごずに機胜するこずを考えるず、共甚䜓の最も単玔なスキヌムは、「構造䜓ず同じルヌル+フィヌルドの非初期化/借甚もその兄匟フィヌルドを非初期化/借甚する」です。 "。
この単玔なルヌルは、すべおの静的チェックを察象ずしおいたす。

構造䜓のルヌルを理解しおいるず仮定しお、これたでのずころ同意したした。

次に、列挙型モデルは、䞊蚘の静的チェック+もう1぀の条件の結果です。
1初期化チェックが有効で、2安党でないコヌドがナニオンに属する領域に任意の無効なバむトを曞き蟌たない堎合、ナニオンの「リヌフ」フィヌルドの1぀が自動的に有効になりたす。 これは動的にチェックできたせん少なくずもフィヌルドが1を超え、const-evaluatorの倖郚にあるナニオンの堎合保蚌ですが、たずコヌドを読む人を察象ずしおいたす。

その远加条件は組合には無効です。

たずえば、 @ joshtriplettからのこのケヌス

たずえば、そのナヌスケヌスの1぀は、将来さらに倚くのタグを䜿甚しお明瀺的に拡匵可胜なCスタむルのタグ付き共甚䜓を怜蚎するこずです。 ナニオンが考えられるすべおのフィヌルドタむプを知っおいるず想定しおはならないこずを読み取るCおよびRustコヌド。

ナニオンに「将来の拡匵の可胜性」のための远加フィヌルドが明瀺的にある堎合、コヌドを読む人々にずっおはるかに明確になりたす。

これは、Cナニオンが機胜する方法でも、Rustナニオンが機胜するように指定された方法でもありたせん。 そしお、それがより明確になるのか、それずも単に異なる期埅に䞀臎するのか疑問に思いたす。これを倉曎するず、Rust共甚䜓は、蚭蚈および提案された目的の䞀郚に適合しなくなりたす。

もちろん、基本的な静的初期化チェックを維持するこずはできたすが、2番目の条件を拒吊し、むンスタントUBでなくおも、安党でない「サヌドパヌティ」手段を介しお任意の無効な可胜性のあるデヌタをナニオンに曞き蟌むこずができたす。 そうすれば、そのダむナミックな人々をタヌゲットにした保蚌はもうありたせん。それは玔損倱になるず思いたす。

これらの「安党でない「サヌドパヌティ」ずは、「FFIから組合を取埗する」こずを意味したす。これは完党に有効なナヌスケヌスです。

具䜓的な䟋を次に瀺したす。

union Event {
    event_id: u32,
    event1: Event1,
    event2: Event2,
    event3: Event3,
}

struct Event1 {
    event_id: u32, // always EVENT1
    // ... more fields ...
}
// ... more event structs ...

match u.event_id {
    EVENT1 => { /* ... */ }
    EVENT2 => { /* ... */ }
    EVENT3 => { /* ... */ }
    _ => { /* unknown event */ }
}

これは、人々が共甚䜓を䜿甚しお蚘述できる、たたは蚘述できる完党に有効なコヌドです。

@petrochenkov

このコヌドは1ナニオンに察しお2非ナニオンに察しお機胜する必芁がありたすか
私にずっお、答えはどちらの堎合も明らかな「いいえ」です。これは、Tの「結合」性に関係なく、Rustが防止でき、防止したい゚ラヌのクラス党䜓だからです。

私にずっおは倧䞈倫です。

ナニオンの最も単玔なスキヌムは、「構造䜓ず同じルヌル+フィヌルドの非初期化/借甚もその兄匟フィヌルドの非初期化/借甚」です。

うわヌ。 構造䜓ルヌルは、異なるフィヌルドが互いに玠であるずいう事実にすべお基づいおいるため、意味

1初期化チェックが有効で、2安党でないコヌドがナニオンに属する領域に任意の無効なバむトを曞き蟌たない堎合、ナニオンの「リヌフ」フィヌルドの1぀が自動的に有効になりたす。 これは動的にチェックできたせん少なくずもフィヌルドが1を超え、const-evaluatorの倖郚にあるナニオンの堎合保蚌ですが、たずコヌドを読む人を察象ずしおいたす。

基本的な劥圓性の仮定が動的にチェック可胜であるこずが非垞に望たしいず思いたすタむプ情報が䞎えられた堎合。 次に、ミリでのCTFE䞭にそれらをチェックできたす。たた、「フル」ミリ実行テストスむヌトなど䞭にもチェックできたす。最終的には、ある皮の消毒剀や、Rustがdebug_assert!攟出するモヌドを䜿甚できたす。重芁な堎所で劥圓性の䞍倉量をチェックしたす。
Cのチェックできないルヌルの経隓は、これらが問題であるずいう十分な蚌拠を䞎えおいるず思いたす。 通垞、ルヌルが䜕であるかを実際に理解しお明確にするための最初のステップは、動的にチェック可胜なルヌルを衚珟する方法を芋぀けるこずです。 䞊行性メモリモデルの堎合でも、「動的にチェック可胜な」バリアント仮想マシンの段階的な実行に関しおすべおを説明する操䜜的セマンティクスが珟れおおり、公理の長幎の未解決の問題を解決する唯䞀の方法のようです。以前に䜿甚されたモデル「薄い空気の問題のouf」はここでのキヌワヌドです。

動的にチェック可胜なルヌルを持぀こずがいかに重芁であるかを誇匵するこずはできたせん。 UBのチェックできないケヌスを0にするこずを目指すべきだず思いたす。 私たちはただそこにいたせんが、それが私たちが持぀べき目暙です。それがあなたの蚀語でUBを䜿甚する唯䞀の責任ある方法です。他のすべおはコンパむラ/蚀語の䜜者の堎合であり、すべおの人を犠牲にしお圌らの生掻を楜にしたす。結果ず䞀緒に暮らす必芁がありたす。 私は珟圚、゚むリアシングず生のポむンタヌアクセスのために動的にチェック可胜なルヌルに取り組んでいたす。
それが唯䞀の問題であるずしおも、私に関する限り、「動的にチェックできない」こずは、このアプロヌチを䜿甚しないための十分な理由です。

ずはいえ、これをチェックできない基本的な理由はわかりたせん。ナニオン内のすべおのバむトに぀いお、すべおのバリアントを調べお、このバリアントでそのバむトに蚱可されおいる倀を確認し、すべおのナニオンheh;を取埗したす。それらのセットの。 この定矩に埓っおすべおのバむトが有効である堎合、バむトのシヌケンスはナニオンに察しお有効です。
ただし、これを実際にチェックするのは非垞に困難です。これは、Rustで䜿甚する最も耇雑な基本的な型の劥圓性の䞍倉条件です。 これは、この有効性ルヌルを説明するのがやや難しいずいう事実の盎接的な結果です。そのため、私はそれが奜きではありたせん。

もちろん、基本的な静的初期化チェックを維持するこずはできたすが、2番目の条件を拒吊し、むンスタントUBでなくおも、安党でない「サヌドパヌティ」手段を介しお任意の無効な可胜性のあるデヌタをナニオンに曞き蟌むこずができたす。 そうすれば、そのダむナミックな人々をタヌゲットにした保蚌はもうありたせん。それは玔損倱になるず思いたす。

その保蚌は私たちを買うのですか それは実際にどこで圹立ちたすか 今、私が芋おいるのは、誰もが䞀生懞呜働き、それを守るように泚意しなければならないずいうこずだけです。 私たち、人々がそれから埗られる利益はわかりたせん。

@joshtriplett

将来、より倚くのタグで明瀺的に拡匵可胜なCスタむルのタグ付き共甚䜓を怜蚎しおください。 ナニオンが考えられるすべおのフィヌルドタむプを知っおいるず想定しおはならないこずを読み取るCおよびRustコヌド。

@petrochenkovによっお提案されたモデルは、 __non_exhaustive: ()フィヌルドをナニオンに远加するこずにより、これらのナヌスケヌスを可胜にしたす。 しかし、それは必芁ではないず思いたす。 おそらく、バむンディングゞェネレヌタはそのようなフィヌルドを远加するこずができたす。

@RalfJung

これは動的にチェックできたせん少なくずもフィヌルドが1を超え、const-evaluatorの倖郚にあるナニオンの堎合保蚌

基本的な劥圓性の仮定が動的にチェック可胜であるこずが非垞に望たしいず思いたす

明確化「デフォルト」/「リリヌスモヌド」ではチェックできないこずを意味したした。もちろん、いく぀かの远加のむンストルメンテヌションを䜿甚しお「スロヌモヌド」でチェックできるこずもありたすが、これに぀いおは私よりもよく曞いおいたす。

@RalfJung

@petrochenkovによっお提案されたモデルは、ナニオンに__non_exhaustive :(フィヌルドを远加するこずにより、これらのナヌス

はい、それが提案だず理解したした。

しかし、それは必芁ではないず思いたす。 おそらく、バむンディングゞェネレヌタはそのようなフィヌルドを远加するこずができたす。

可胜ですが、すべおの組合に䜓系的に远加する必芁がありたす。

ナニオンの䞻芁なナヌスケヌスを砎っお、含めるこずができるビットパタヌンの制限に䟝存する䞍特定のナヌスケヌスを支持するこずが理にかなっおいる理由に぀いおは、ただ議論がありたせん。

@joshtriplett

組合の䞻なナヌスケヌス

これが䞻なナヌスケヌスである理由は、私にはたったくわかりたせん。
タグ付き共甚䜓の共甚䜓のすべおの䜿甚/ FFIの「Rustenum゚ミュレヌション」が拡匵性を前提ずしおいるず仮定するず、 repr(C)共甚䜓に圓おはたる可胜性がありたすこれは真実ではありたせんが、私が芋たずころ、 repr(Rust)共甚䜓ドロップ制埡、初期化制埡、トランスミュヌトは、「予期しないバリアント」が突然出珟するこずを期埅しおいたせん。

@petrochenkov私は、「䞻なナヌスケヌスを壊す」ず蚀っおいなかった、私は、「䞻なナヌスケヌスを壊す」ず述べたした。 FFIは、組合の䞻なナヌスケヌスの1぀です。

そしお、それらすべおのセットの結合heh;を取りたす

「ナニオンの可胜な倀は、すべおの可胜なバリアントの可胜な倀のナニオンである」ずいうステヌトメントには、確かに魅力的な明癜さがありたす。

本圓。 しかし、それは提案ではありたせん-私たちは皆、以䞋が合法であるべきであるこずに同意したす

union F {
  x: (u8, bool),
  y: (bool, u8),
}
fn foo() -> F {
  let mut f = F { x: (5, false) };
  unsafe { f.y.1 = 17; }
  f
}

実際、これにはunsafeも必芁なのはバグだず思いたす。

したがっお、ナニオンは少なくずもバむト単䜍で取埗する必芁がありたす。
たた、「魅力的な自明性」だけでは十分な理由ではないず思いたす。 私たちが決定する䞍倉条件は、安党でないコヌド䜜成者にずっお倧きな負担です。その結果、具䜓的な利点が埗られるはずです。

@RalfJung

実はこれが安党でないこずさえ芁求するのはバグだず思いたす。

新しいMIRベヌスの安党性チェッカヌの実装に぀いおはわかりたせんが、叀いHIRベヌスの実装では、確かにチェッカヌの制限/簡略化expr1.field = expr2圢匏の匏のみが可胜な「フィヌルド」に぀いお分析されたした。割り圓お」の安党性のオプトアりト、その他すべおは、組合にずっお安党ではない䞀般的な「フィヌルドアクセス」ずしお保守的に扱われたした。

https://github.com/rust-lang/rust/issues/52786#issuecomment -408645420のコメントに答える

぀たり、コンパむラはただWrap<T>のコントラクトに぀いお䜕も知らず、たずえばレむアりトの最適化を行うこずができないずいう考えです。 わかりたした、この䜍眮は理解されおいたす。
これは、内郚的に、 Wrapのモゞュヌル内で、 Wrap<T>モゞュヌルの実装が、たずえば、ナヌザヌにリヌクしない堎合、䞀時的に「予期しない倀」を曞き蟌むこずができるこずを意味したす。コンパむラはそれらで倧䞈倫です。

予期しない倀がないこずに関するWrapの契玄の䞀郚が、フィヌルドのプラむバシヌにどの皋床正確に関連しおいるかはわかりたせん。

たず、フィヌルドがプラむベヌトかパブリックかに関係なく、予期しない倀をこれらのフィヌルドから盎接曞き蟌むこずはできたせん。 それを行うには、生のポむンタヌ、たたはFFIの反察偎のコヌドのようなものが必芁です。これは、ナニオン党䜓ぞのポむンタヌを持぀だけで、フィヌルドアクセスなしで実行できたす。 したがっお、制限されおいるフィヌルドぞのアクセス以倖の方向からこれにアプロヌチする必芁がありたす。

私があなたのコメントを解釈するずき、アプロヌチは、プラむベヌトフィヌルドナニオンたたは構造䜓では関係ありたせんはナヌザヌに未知の任意の䞍倉条件を意味するので、そのフィヌルドを盎接たたはワむルドポむンタを介しお倉曎する操䜜はありたせん問題は、その䞍特定の䞍倉条件を壊す可胜性があるため、UBになりたす。

これは、ナニオンに1぀のプラむベヌトフィヌルドがある堎合、その実装者コンパむラではないは、サヌドパヌティがそのナニオンに予期しない倀を曞き蟌むこずはないず想定できるこずを意味したす。
これは、ある意味でナヌザヌにずっおの「デフォルトのナニオンドキュメント句」です。
-デフォルトナニオンにプラむベヌトフィヌルドがある堎合、ガベヌゞを曞き蟌むこずはできたせん。
-それ以倖の堎合は、ドキュメントで明瀺的に犁止されおいない限り、ガベヌゞをナニオンに曞き蟌むこずができたす。

䞀郚のナニオンが、予期されるフィヌルドぞのpubアクセスを提䟛しながら、予期しない倀を犁止したい堎合たずえば、これらのフィヌルドに独自の䞍倉条件がない堎合、ドキュメントを介しおそれを行うこずができたす。 2番目の句が必芁です。

@RalfJung
これはあなたの䜍眮を正確に説明しおいたすか

このようなシナリオはどのように扱われたすか

mod m {
    union MyPrivateUnion { /* private fields */ }
    extern {
        fn my_private_ffi_function() -> MyPrivateUnion; // Can return garbage (?)
    }
}

私があなたのコメントを解釈するずき、アプロヌチは、プラむベヌトフィヌルドナニオンたたは構造䜓では関係ありたせんはナヌザヌに未知の任意の䞍倉条件を意味するので、そのフィヌルドを盎接たたはワむルドポむンタを介しお倉曎する操䜜はありたせん問題は、その䞍特定の䞍倉条件を壊す可胜性があるため、UBになりたす。

いいえ、それは私が意図したこずではありたせん。

耇数の䞍倉条件がありたす。 必芁な数はわかりたせんが、少なくずも2぀は必芁ですそしお、それらの名前はわかりたせん。

  • 型の「レむアりトレベルの䞍倉」たたは「構文の䞍倉」は、型の構文の圢によっお完党に定矩されたす。 これらは、「 &mut TはNULLではなく、敎列されおいる」、「 boolは0たたは1 」、「 !はできたせん」などです。存圚する」。 このレベルでは、 *mut Tはusizeず同じです。どちらも任意の倀たたは初期化された倀を蚱可したすが、その区別は別の説明のためです。 最終的には、構造䜓の再垰によっお、すべおのタむプのこれらの䞍倉条件を詳しく説明するドキュメントを䜜成する予定です。構造䜓のレむアりトレベルの䞍倉条件は、すべおのフィヌルドの䞍倉条件が維持されるこずなどです。ここでは、可芖性は圹割を果たしたせん。
Violating the layout-level invariant is instantaneous UB. This is a statement we can make because we have defined this invariant in very simple terms, and we make it part of the definition of the language itself. We can then exploit this UB (and we already do), e.g. to perform enum layout optimizations.
  • タむプの「カスタムタむプレベル䞍倉条件」たたは「セマンティック䞍倉条件」は、そのタむプを実装する人によっお遞択されたす。 コンパむラは、それを衚珟する蚀語がないため、この䞍倉条件を知るこずができたせん。蚀語定矩に぀いおも同じこずが蚀えたす。 この䞍倉条件が䜕であるかさえ蚀えないので、この䞍倉条件UBに違反するこずはできたせん。 カスタム䞍倉条件を持぀こずさえ可胜であるずいう事実は、あらゆる有甚な型システムの特城です抜象化。 これに぀いおは、過去のブログ投皿で詳しく曞いおいたす。

    カスタムのセマンティックむンバリアントずUBの関係は、安党でないコヌドが、倖郚コヌドによっお保持されおいるセマンティックむンバリアントに䟝存しおいる可胜性があるこずを宣蚀するこずVecのサむズフィヌルドにランダムなものを入れるだけでは正しくありたせん。 私が間違っおいるず蚀ったこずに泚意しおください私は時々 unsoundずいう甚語を䜿甚したす-しかし未定矩の動䜜ではありたせ&mut ZST゚むリアシングルヌルに関する説明です。 ぶら䞋がっおいる適切に配眮されたnull以倖の&mut ZST䜜成するこずは、すぐにUBになるこずはありたせんが、これが起こらないこずに䟝存する安党でないコヌドを曞く可胜性があるため、それでも正しくない/正しくありたせん。

これら2぀の抂念を䞀臎させるのは良いこずですが、実甚的ではないず思いたす。 たず、䞀郚のタむプ関数ポむンタヌ、dyn特性では、カスタムのセマンティック䞍倉条件の定矩は、実際には蚀語でのUBの定矩を


予期しない倀がないこずに぀いおWraps契玄の䞀郚がどの皋床正確にフィヌルドのプラむバシヌに関連しおいるかはわかりたせんが、

基本的に、型がそのカスタム䞍倉条件を遞択するずき、安党なコヌドが実行できるすべおのものが䞍倉条件を保持するこずを確認する必芁

たずえば、構造䜓のパブリックフィヌルドは、フィヌルドタむプのカスタム䞍倉条件ずは異なるカスタム䞍倉条件を持぀こずはできたせん。結局のずころ、安党なナヌザヌは、そのフィヌルドに任意のデヌタを曞き蟌んだり、フィヌルドから読み取っお「良奜」を期埅したりできたす。デヌタ。 すべおのフィヌルドが公開されおいる構造䜓は安党に構築でき、フィヌルドにさらに制限を課したす。

パブリックフィヌルドずの結合...たあ、それはやや興味深いです。 ナニオンフィヌルドの読み取りはずにかく安党ではないので、そこでは䜕も倉わりたせん。 ナニオンフィヌルドの蚘述は安党であるため、パブリックフィヌルドを持぀ナニオンは、フィヌルドに入力されるそのフィヌルドの型のカスタム䞍倉条件を満たす任意のデヌタを凊理できる必芁がありたす。 これが非垞に圹立぀ずは思えたせん...

したがっお、芁玄するず、カスタム䞍倉条件を遞択するずきは、倖郚の安党なコヌドがこの䞍倉条件を壊さないようにするのはあなたの責任ですそしお、これを達成するのに圹立぀プラむベヌトフィヌルドのようなツヌルがありたす。 そのコヌドが安党なコヌドができないこずをするずき、あなたの䞍倉条件に違反しないこずは倖囜のunafeコヌドの責任です。


これは、内郚的に、Wrapのモゞュヌル内で、Wrapの実装を意味したすたずえば、モゞュヌルは、ナヌザヌにリヌクしない堎合、䞀時的に「予期しない倀」を曞き蟌むこずができ、コンパむラはそれらに問題がありたせん。

正しい。 ここではパニックの安党性が懞念事項ですが、おそらくご存知でしょう。 これは、 Vec 、安党に実行できるのず同じです。

let sz = self.size;
self.size = 1337;
self.size = sz;

UBはありたせん。


mod m {
    union MyPrivateUnion { /* private fields */ }
    extern {
        fn my_private_ffi_function() -> MyPrivateUnion; // Can return garbage (?)
    }
}

構文レむアりトの䞍倉条件に関しお、 my_private_ffi_functionは䜕でも実行できたす関数呌び出しABIず眲名が䞀臎するず仮定。 セマンティックカスタム䞍倉条件に関しおは、コヌドには衚瀺されたせん-このモゞュヌルを䜜成した人は誰でも䞍倉条件を念頭に眮いおいたので、ナニオン定矩の暪にそれを文曞化しおから、FFI関数が䞍倉条件を満たす倀を返すこずを確認する必芁がありたす。

私は぀いに、 &mut T初期化する必芁があるかどうか、い぀初期化する必芁があるか、および䞊蚘の2皮類の䞍倉条件に぀いおのブログ投皿を曞きたした。

https://github.com/rust-lang/rust/issues/55149でただカバヌされおいない、ここで远跡するものが残っおい

E0658はただここを指しおいたす

゚ラヌ[E0658] Copyフィヌルドを持぀ナニオンは䞍安定です問題32836を参照

圌らはCopy実装しおいないので、これは珟圚アトミックでひどく遊んでいたす。 誰かが回避策を知っおいたすか

https://github.com/rust-lang/rust/issues/55149が実装されおいる堎合、ナニオンでManuallyDrop<AtomicFoo>を䜿甚できるようになりたす。 それたでは、回避策はNightlyを䜿甚するこずですたたはunionを䜿甚せずに別の方法を芋぀けおください。

これを実装すれば、 ManuallyDropも必芁ありたせん。 結局のずころ、rustcはAtomic*がDrop実装しおいないこずを知っおいたす。

远跡の問題を新しい問題に切り替えるように自分を割り圓おたす。

このペヌゞは圹に立ちたしたか
0 / 5 - 0 評䟡