私は正しくビルドして実行するコンパイラを持っていますが、PEVerifyは特定の時点でそれを確認できないと呼びます。エラー、対応するソースコード、問題のポイントのILDasm出力を注意深く見てから、PEVerifyのバグが疑われるところまで問題を見つけることはできませんが、.NETとMonoのバージョン同じ場所で同じエラーを報告します。次のようにこのコードはなぜ検証に失敗しますか?
internal static bool InAsyncMethod(Expression value)
{
INodeWithBody ancestor = value.GetAncestor<BlockExpression>() ?? (INodeWithBody) value.GetAncestor<Method>();
return ContextAnnotations.IsAsync(ancestor);
}
誤差は次のように報告される:0x11
Offsest
[IL]: Error: [D:\SDL-1.3.0-4423\boo\build\Boo.Lang.Compiler.dll : Boo.Lang.Compiler.TypeSystem.AsyncHelper::InAsyncMethod][offset 0x00000011][found ref 'Boo.Lang.Compiler.Ast.Node'][expected ref Boo.Lang.Compiler.Ast.INodeWithBody'] Unexpected type on the stack.
??
式の後半に相当します。 ILDASMから:
.method assembly hidebysig static bool InAsyncMethod(class Boo.Lang.Compiler.Ast.Expression 'value') cil managed
{
// Code size 29 (0x1d)
.maxstack 2
.locals init ([0] class Boo.Lang.Compiler.Ast.INodeWithBody ancestor,
[1] bool CS$1$0000)
IL_0000: nop
IL_0001: ldarg.0
IL_0002: callvirt instance !!0 Boo.Lang.Compiler.Ast.Node::GetAncestor<class Boo.Lang.Compiler.Ast.BlockExpression>()
IL_0007: dup
IL_0008: brtrue.s IL_0011
IL_000a: pop
IL_000b: ldarg.0
IL_000c: callvirt instance !!0 Boo.Lang.Compiler.Ast.Node::GetAncestor<class Boo.Lang.Compiler.Ast.Method>()
IL_0011: stloc.0
IL_0012: ldloc.0
IL_0013: call bool Boo.Lang.Compiler.Steps.ContextAnnotations::IsAsync(class Boo.Lang.Compiler.Ast.INodeWithBody)
IL_0018: stloc.1
IL_0019: br.s IL_001b
IL_001b: ldloc.1
IL_001c: ret
} // end of method AsyncHelper::InAsyncMethod
Boo.Lang.Compiler.Ast.Node
クラスは、すべてのASTノードの基本クラスです。 BlockExpression
およびMethod
はそれぞれlambdaおよびメソッドのノードクラスであり、いずれもINodeWithBody
インターフェイスを実装しています。 C#(型の問題があればビルドしません)とIL(000c
でGetAncestor<Method>
呼び出しの戻り値の型がメソッド呼び出しの最初の型パラメーターであることがわかります)の両方で、すべてが正しく表示されます。
明らかに値がMethod
の場合、PEVerifyはタイプNode
の値を扱っていると思う原因になりますか?それを修正する方法はありますか?
長年に渡ってこれらの自分自身をデバッグしたことは、たいていいつも '? : '条件付き演算子。検証者は、長年にわたり条件文を処理するための戦略を変更しており、かなり混乱する可能性があります。 –
@EricLippert今回は '??'演算子でした。 (詳細については、受け入れられた答えを参照してください。)2つの別々のステートメントとして書き直しました。これは、コードが完全に同等であるべきであるため少し奇妙です。私は 'csc'が一義的なILを生成するのを見て驚いています! –
'??'演算子はちょうど派手なドレスの '?:'演算子です。 ( '&&'と '||'と '?.')' csc'がこれを生成している場合、(1)あなたのcscのバージョンが別のバージョンの検証者に対してテストされました。 (2)cscは条件付きコードパスでもう一つのフリークインのバグを持っています。それを報告してください、私は今回はそれを修正する必要はありません喜んで、または(3)両方。 –