Repository navigation
静的構築子が書く静的フィールドを診断で断つ - #257
Conversation
PRレビュー / PR review変更 14 ファイル、コミット 8 件。 / 14 files, 8 commits. 検証の要否 / Verification required以下を走らせ、失敗した試験の名前と失敗の様子を変更前と突き合わせてください。総数だけで判断しないでください。 dotnet build ComputeWeave.sln -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.SourceGenerators/ComputeWeave.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.Internals/ComputeWeave.Tests.Internals.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests/ComputeWeave.Tests.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.DeviceLost/ComputeWeave.Tests.DeviceLost.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests.SourceGenerators/ComputeWeave.D2D1.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests/ComputeWeave.D2D1.Tests.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests.AssemblyLevelAttributes/ComputeWeave.D2D1.Tests.AssemblyLevelAttributes.csproj -c Release -p:Platform=x64ビルドエラーを出す診断を変えた場合は、アナライザーの試験に加えて解全体の検証が要ります。 慎重を要する箇所 / Guarded areas touched
寿命の追跡と危険の追跡は別々の保証です。一方を保っても他方が保たれるとは限りません。 公開APIまたは生成される記述子を変えた場合は、該当部分の互換性、生成の決定性、基準データの検査を走らせてください。 確認できた点 / Confirmed
これは自動の確認で、査読の代わりにはなりません。指摘は判断の材料であって、従う義務はありません。 |
…icConstructorAssignment # Conflicts: # src/ComputeWeave.D2D1.SourceGenerators/AnalyzerReleases.Unshipped.md # src/ComputeWeave.SourceGenerators/AnalyzerReleases.Unshipped.md
…icConstructorAssignment # Conflicts: # src/ComputeWeave.D2D1.SourceGenerators/AnalyzerReleases.Unshipped.md
Summary / 概要
静的構築子が値を入れる静的フィールドを取り込む形を、
CMPW0130、Direct2D ではCMPWD2D0103で断ります。課題 #250 を直します。C# は型が最初に触れられたときに静的構築子を走らせ、静的フィールドの初期化子の後に本体を実行します。静的構築子が書いた静的フィールドは、その後ずっとその値を持ちます。生成HLSLは静的構築子を持たず、フィールドを初期化子の値で、初期化子が無ければ初期化子を持たない静的変数として書き出します。どちらのシェーダーコンパイラもそれを断らずに 0 として読むので、シェーダーは C# が計算しない値を黙って計算します。
歩きは、シェーダー型と、取り込んだメソッド・構築子・静的フィールドが属する型のそれぞれについて静的構築子を辿り、呼び出しが解決するメソッド、局所関数、構築子を初期化子の歩きと同じ形で追います。生成HLSLが宣言する静的フィールド(シェーダー自身のものと取り込んだもの)への書きを、どの型の静的構築子からであっても報告し、書いた位置とその構築子の型を名指しします。読みは報告しません。
Linked issue / 関連する課題
Closes #250
Kind / 種別
Behavior change / 挙動の変更
これまで診断なく通っていた次の形が、
CMPW0130/CMPWD2D0103の誤りになります。いずれも C# と違う値を計算していた形です。readonlyかどうかを問わず)を、初期化子や本文が読む形書きと見るのは、代入(単純代入と複合代入)、増分と減分、
refとoutの引数です。refは呼び先が書けるので書きに数えます。静的構築子がフィールドを読むだけの形、生成HLSLが宣言しないフィールドを書く形は報告しません。診断が2つ増えるので、同梱する文書が述べる診断の件数は、この枝の土台で
CMPWが112から113へ、CMPWD2Dが100から101へ動き、PR #254 が入った origin/main を併合した先端では114と102です。上のどの形も持たない入力の生成物は変わりません。Verification / 検証
土台は
730eab57、実装はaf839246、試験はa6c8dd57、台帳はc301dd42です。計算側の生成器は土台の588件に対して598件、Direct2D側の生成器は236件に対して237件で、いずれも失敗0件です。土台の値は PR #243 の併合の先端で測ったものです。計算側で増える10件は足した行10本、Direct2D側の1件は足した試験1本です。表の検査は21文書409行が描画で欠けず、件数の検査は4文書とも一致、出荷の記録の検査は6 file の216項目がそれぞれ1つの履歴を持つと述べ、乖離の監査は待ち行列が空です。直す前の形を測りました
生成器へ通した形と、生成物と同じ形の手書きの HLSL を同梱の DXC(1.7.2308.7)と SDK 10.0.26100.0 の FXC へ当てて格納される値を読んだもの、C# をコンソールで走らせた値です。実機では読んでいません。
readonlyの静的フィールドへ静的構築子が 5 を書き、本文が読む生成HLSLは
static const float V;とstatic float V;で、初期化子を持たない定数もどちらのコンパイラも断りません。変異
実装をコミットしてから、歩きの判断を1つずつ壊しました。当てた木は
c301dd42で、変異を当てない対照では2つのスイートとも失敗0件です。狙った試験は計算側75件、Direct2D側10件で、初期化子の歩きの試験を含みます。生成物を全数で突き合わせました
解の11 project を
-t:Rebuildと-p:EmitCompilerGeneratedFiles=trueで1本ずつ建て直し、書き出された file を土台で同じ道具で採った値と突き合わせました。11 project とも誤り0件で建ちます。両方に在る file は1080で、そのうち1078が1バイト同一、内容が違うものが2、片方にしか無いものは0です。違う2件は Direct2D の記述子で、同じコミットを2回建てても動く DXBC の検査値です。この木に既に在るシェーダーの生成物は1件も変わらず、新しい報告に当たるものもありません。origin/main の併合
この枝を出したあとに PR #254 が既定ブランチへ入ったので、
fa7f369eの origin/main を併合しました(6bdad9cd)。衝突は両側の出荷前の記録で、#254 のCMPW0129とCMPWD2D0101の行とこの枝の行を1つの表に並べ、同梱する文書の件数を114と102へ数え直しました。#254 は呼び出しの記録から再帰を断つ処理で、この枝の歩きと重なる箇所はありません。併合の先端で生成器の試験2本は計算側626件と Direct2D側241件がいずれも失敗0件で、生成物の全数調査は origin/main と突き合わせて1080 file のうち1078が1バイト同一、違う2件は同じ既知の DXBC の検査値、片方にしか無い file は0です。Direct2D 側の番号の変更
この枝を出したあとに開いた PR #258 も Direct2D 側に
CMPWD2D0102を足していて、2本を併合した木は文字どおりには衝突せず、記述子が2つともCMPWD2D0102のまま誤りも警告も出さずに建ちます。この枝の側をCMPWD2D0103へ移しました。記述子と出荷前の記録はcf1905fe、試験はaf5eb90c、乖離台帳の行はae9f4e9cです。移した先端で計算側の生成器は626件、Direct2D 側は241件が失敗0件で、表、件数、出荷の記録、乖離の4つの検査は通ります。同じ識別子を2つの記述子が持つことを試験で断つ PR #260 を別に出しました。その後に #258 が既定ブランチへ入ったので、4e654727の origin/main を併合しました(0ef04d1f)。衝突は Direct2D 側の出荷前の記録の行で、#258 のCMPWD2D0102とこの枝のCMPWD2D0103を並べ、同梱する文書の Direct2D 側の件数を103へ数え直しました。この先端で生成器の試験2本は計算側626件と Direct2D 側248件が失敗0件で、生成物の全数調査は origin/main と突き合わせて1080 file のうち1078が1バイト同一、違う2件は同じ既知の DXBC の検査値、片方にしか無い file は0です。走らせていないもの
ComputeWeave.Tests、ComputeWeave.D2D1.Tests、ComputeWeave.Tests.Internals、ComputeWeave.Tests.DeviceLost、ComputeWeave.Tests.DebugLayer、ComputeWeave.Tests.GlobalStatements、ComputeWeave.D2D1.Tests.AssemblyLevelAttributesは手元では走らせていません。変更は生成器の歩き1つと診断の追加に閉じており、上の全数比較のとおり生成物が1件も変わらないので、生成物を照合する試験と実行時の面に届く経路がありません。CI は併合の先端0ef04d1fでビルドとテストの工程を通しました。そこで走った試験はComputeWeave.Tests4189、ComputeWeave.Tests.Internals1085、ComputeWeave.Tests.DeviceLost43、ComputeWeave.D2D1.Tests206、ComputeWeave.D2D1.Tests.AssemblyLevelAttributes4で、生成器の2本は626と248で、いずれも失敗0件です。Checklist / 確認
If this touches a guarded area / 慎重を要する箇所に触れる場合
Notes for the reviewer / 査読者への注記
静的構築子を持つ型を丸ごと断らなかった理由
静的構築子を持つ型の静的フィールドを全て断つ形は簡単ですが、構築子が触れないフィールドまで断ります。初期化子を持つフィールドは静的構築子が書き換えない限り生成HLSLと一致するので、断る根拠がありません。書きを見る形なら、断る条件と測った表がちょうど一致します。
触れる型を取り込んだ宣言の型まで広げた理由
C# は型が最初に触れられたときに静的構築子を走らせます。シェーダーが触れる型は、シェーダー型と、取り込んだメソッド、構築子、静的フィールドが属する型です。フィールドの型の静的構築子だけを見ると、本文がメソッドを取り込んだ型の静的構築子がシェーダーの静的フィールドへ書く形を見逃します。触れる型をこの4つから集めれば、静的構築子が書きうる生成HLSLの静的フィールドは全て覆えます。書きの対象を生成HLSLが宣言するフィールドに限るので、取り込まれないフィールドへの書きは報告しません。
初期化子の歩きと1つの歩きを共有した理由
呼び出しが解決するメソッド、局所関数、構築子を辿る部分は、初期化子の歩き(PR #243)と同じです。2箇所に同じ辿り方を書くと片方だけ直す形が生まれるので、辿る部分を1つの型にまとめ、初期化子の歩きはその上に、他の型のフィールドの初期化子へ入る辺と報告を載せ、静的構築子の歩きは書きの報告だけを載せる形にしました。初期化子の歩きの試験と変異はそのまま通ります。
触らなかったもの
静的構築子がシェーダーの静的フィールド以外へ与える効果は写しません。静的構築子の本体を生成HLSLへ書き出す道は無く、生成HLSLが宣言する静的フィールドに効かない効果はシェーダーの値に現れないので、報告もしません。
静的構築子の本体の中で、文の順や条件によって書きが起きない形も、書きとして報告します。歩きは文の順を追いません。
ref引数で渡した静的フィールドを呼び先が書かない形も、書きとして報告します。呼び先が書けることが判定で、書いたかどうかは見ていません。歩く静的構築子は触れる型のものだけです。触れた型の静的構築子がさらに別の型を触れ、その型の静的構築子が生成HLSLの静的フィールドを書く連鎖は、その別の型を取り込んでいなければ歩きません。取り込んだ宣言から先の連鎖は、呼び出しが解決する宣言を辿る形で届きます。
前提が崩れたときの戻し方
歩きは1つの処理で、両生成器から1行ずつ呼ばれています。呼び出しを外せば報告は消え、書き出しは変わりません。誤検出が出るなら、触れる型の集め方、書きの判定、歩きの辺がそれぞれ1箇所です。
測っていないこと
実機の値。Direct2D 側は生成器の試験1本で診断が出ることを確かめ、FXC の値は手書きの HLSL で読んだにとどまります。