Skip to content

await on a type parameter with an interface constraint drops the operand (LdObjIfRef not supported) #4017

Description

@christophwille

Awaiting a type parameter constrained to an awaitable interface produces output that does not compile: the operand is dropped and replaced with an unsupported-opcode comment.

Input

public interface IAwaitable
{
	TaskAwaiter GetAwaiter();
}

public async Task TypeParameterWithInterfaceConstraint<T>(T value) where T : IAwaitable
{
	await value;
}

Actual output

public async Task TypeParameterWithInterfaceConstraint<T>(T value) where T : IAwaitable
{
	await (IAwaitable)/*OpCode not supported: LdObjIfRef*/;
}

This is CS0119.

Expected output

public async Task TypeParameterWithInterfaceConstraint<T>(T value) where T : IAwaitable
{
	await value;
}

Notes

The constrained. prefixed callvirt to GetAwaiter lowers to an LdObjIfRef, and ExpressionBuilder has no case for that instruction, so the operand is lost entirely.

The sibling shapes decompile correctly, which narrows this to the interface-constrained case:

  • where T : ClassAwaitable (class constraint) round-trips
  • where T : struct, IAwaitable round-trips

Both are covered by AwaitReceivers.TypeParameterWithClassConstraint / TypeParameterWithStructConstraint in ICSharpCode.Decompiler.Tests/TestCases/Pretty/AsyncAwaitPatterns.cs.

Metadata

Metadata

Assignees

No one assigned

    标签

    Type

    No type

    项目

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions