Skip to content

Local read behind else branch in async method lifted unnecessarily #21077

@stephentoub

Description

@stephentoub

Version Used:
2.3.1.61913 (0ce1a70)

Steps to Reproduce:
Compile this program in release and look at the IL:

using System.Threading.Tasks;

class Program
{
    static void Main() { }

    static async Task Method1(bool value)
    {
        int i = 42;
        int j = i;
        await Task.Yield();
    }

    static async Task Method2(bool value)
    {
        int i = 42;
        if (value)
        {
            int j = i;
            await Task.Yield();
        }
        else
        {
            await Task.Yield();
        }
    }

    static async Task Method3(bool value)
    {
        int i = 42;
        if (value)
        {
            await Task.Yield();
        }
        else
        {
            int j = i;
            await Task.Yield();
        }
    }
}

Expected Behavior:
No Int32 value is lifted to the state machine for any of the async methods.

Actual Behavior:
In both Method1 and Method2, the compiler correct deduces that there's no need to lift i from being a local to a field:

Method1:
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
private YieldAwaitable.YieldAwaiter <>u__1;

Method2:
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
private YieldAwaitable.YieldAwaiter <>u__1;
public bool value;

but for Method3, it fails to realize this and promotes the i local to being a field, consuming unnecessary space on the state machine object when it's boxed to the heap:

Method3:
public int <>1__state;
public AsyncTaskMethodBuilder <>t__builder;
private YieldAwaitable.YieldAwaiter <>u__1;
private int <i>5__1;
public bool value;

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions