File: CodeGen\CodeGenAwaitUsingTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Emit\Microsoft.CodeAnalysis.CSharp.Emit.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Emit.UnitTests)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
#nullable disable
 
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
    [CompilerTrait(CompilerFeature.AsyncStreams)]
    public class CodeGenAwaitUsingTests : CSharpTestBase
    {
        [Fact]
        public void TestWithCSharp7_3_01()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task M()
    {
        await using (var x = new C())
        {
        }
    }
    System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, parseOptions: TestOptions.Regular7_3);
            comp.VerifyDiagnostics(
                // (6,9): error CS8652: The feature 'asynchronous using' is not available in C# 7.3. Please use language version 8.0 or greater.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "await").WithArguments("asynchronous using", "8.0").WithLocation(6, 9)
                );
        }
 
        [Fact]
        public void TestWithCSharp7_3_02()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task M()
    {
        await using (var x = new C())
        {
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, parseOptions: TestOptions.Regular7_3);
            comp.VerifyDiagnostics(
                // (6,9): error CS8652: The feature 'asynchronous using' is not available in C# 7.3. Please use language version 8.0 or greater.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "await").WithArguments("asynchronous using", "8.0").WithLocation(6, 9),
                // 0.cs(6,22): error CS8370: Feature 'pattern-based disposal' is not available in C# 7.3. Please use language version 8.0 or greater.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "var x = new C()").WithArguments("pattern-based disposal", "8.0").WithLocation(6, 22)
                );
        }
 
        [Fact]
        public void TestInNonAsyncVoidMethod()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    void M()
    {
        await using (var x = new C())
        {
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,9): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await").WithLocation(6, 9)
                );
        }
 
        [Fact]
        public void TestInNonAsyncMethodReturningInt()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    int M()
    {
        await using (var x = new C())
        {
            return 1;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,9): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<int>'.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await").WithArguments("int").WithLocation(6, 9)
                );
        }
 
        [Fact]
        public void TestInNonAsyncAnonymousMethod()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    void M()
    {
        System.Action x = () =>
        {
            await using (var y = new C())
            {
                return;
            }
        };
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (8,13): error CS4034: The 'await' operator can only be used within an async lambda expression. Consider marking this lambda expression with the 'async' modifier.
                //             await using (var y = new C())
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncLambda, "await").WithArguments("lambda expression").WithLocation(8, 13)
                );
        }
 
        [Fact]
        public void TestWithTaskReturningDisposeAsync()
        {
            string source = @"
using System.Threading.Tasks;
class C : System.IAsyncDisposable
{
    public static async Task Main()
    {
        await using (var y = new C()) { }
    }
    public async Task DisposeAsync() { }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (3,11): error CS0738: 'C' does not implement interface member 'IAsyncDisposable.DisposeAsync()'. 'C.DisposeAsync()' cannot implement 'IAsyncDisposable.DisposeAsync()' because it does not have the matching return type of 'ValueTask'.
                // class C : System.IAsyncDisposable
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "System.IAsyncDisposable").WithArguments("C", "System.IAsyncDisposable.DisposeAsync()", "C.DisposeAsync()", "System.Threading.Tasks.ValueTask").WithLocation(3, 11),
                // (9,23): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     public async Task DisposeAsync() { }
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "DisposeAsync").WithLocation(9, 23)
                );
        }
 
        [Fact]
        public void TestInAsyncAnonymousMethod()
        {
            string source = @"
using System.Threading.Tasks;
class C : System.IAsyncDisposable
{
    C()
    {
        System.Console.Write(""C "");
    }
    public static async Task Main()
    {
        System.Func<Task> x = async () =>
        {
            await using (var y = new C())
            {
                System.Console.Write(""body "");
            }
            System.Console.Write(""end"");
        };
        await x();
    }
    public async ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync1 "");
        await Task.Yield();
        System.Console.Write(""DisposeAsync2 "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "C body DisposeAsync1 DisposeAsync2 end");
        }
 
        [Fact]
        public void TestInUnsafeRegion()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task<int> M<T>()
    {
        unsafe
        {
            await using (var x = new C())
            {
                return 1;
            }
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.UnsafeDebugDll);
            comp.VerifyDiagnostics(
                // (8,13): error CS4004: Cannot await in an unsafe context
                //             await using (var x = new C())
                Diagnostic(ErrorCode.ERR_AwaitInUnsafeContext, "await").WithLocation(8, 13)
                );
        }
 
        [Fact]
        public void TestInLock()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task<int> M<T>()
    {
        lock(this)
        {
            await using (var x = new C())
            {
                return 1;
            }
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (8,13): error CS1996: Cannot await in the body of a lock statement
                //             await using (var x = new C())
                Diagnostic(ErrorCode.ERR_BadAwaitInLock, "await").WithLocation(8, 13)
                );
        }
 
        [Fact]
        public void TestWithObsoleteDisposeAsync_01()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (var x = new C())
        {
        }
    }
    [System.Obsolete]
    async System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
    {
        await System.Threading.Tasks.Task.Yield();
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            // https://github.com/dotnet/roslyn/issues/30257 Confirm whether this behavior is ok (currently matching behavior of obsolete Dispose in non-async using)
        }
 
        [Fact]
        public void TestWithObsoleteDisposeAsync_02()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (var x = new C())
        {
        }
    }
    [System.Obsolete]
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        await System.Threading.Tasks.Task.Yield();
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // 0.cs(6,22): warning CS0612: 'C.DisposeAsync()' is obsolete
                //         await using (var x = new C())
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "var x = new C()").WithArguments("C.DisposeAsync()").WithLocation(6, 22)
                );
 
            comp = CreateCompilationWithTasksExtensions([source, IAsyncDisposableDefinition], parseOptions: TestOptions.Regular7);
            comp.VerifyDiagnostics(
                // (6,9): error CS8107: Feature 'asynchronous using' is not available in C# 7.0. Please use language version 8.0 or greater.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "await").WithArguments("asynchronous using", "8.0").WithLocation(6, 9),
                // (6,22): warning CS0612: 'C.DisposeAsync()' is obsolete
                //         await using (var x = new C())
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "var x = new C()").WithArguments("C.DisposeAsync()").WithLocation(6, 22),
                // (6,22): error CS8107: Feature 'pattern-based disposal' is not available in C# 7.0. Please use language version 8.0 or greater.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7, "var x = new C()").WithArguments("pattern-based disposal", "8.0").WithLocation(6, 22)
                );
 
            comp = CreateCompilationWithTasksExtensions([source, IAsyncDisposableDefinition], parseOptions: TestOptions.Regular8, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // 0.cs(6,22): warning CS0612: 'C.DisposeAsync()' is obsolete
                //         await using (var x = new C())
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "var x = new C()").WithArguments("C.DisposeAsync()").WithLocation(6, 22)
                );
        }
 
        [Fact]
        public void TestWithObsoleteDispose()
        {
            string source = @"
class C : System.IDisposable
{
    public static void Main()
    {
        using (var x = new C())
        {
        }
    }
    [System.Obsolete]
    public void Dispose()
    {
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics();
        }
 
        [Fact]
        public void TestInCatchBlock()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        try
        {
            System.Console.Write(""try "");
            throw new System.ArgumentNullException();
        }
        catch (System.ArgumentNullException)
        {
            await using (var x = new C())
            {
                System.Console.Write(""using "");
            }
            System.Console.Write(""end"");
        }
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "try using dispose_start dispose_end end");
        }
 
        [Fact]
        public void MissingAwaitInAsyncMethod()
        {
            string source = @"
class C
{
    public static async System.Threading.Tasks.Task Main()
    {
        System.Action a = () =>
        {
            System.Action b = async () =>
            {
                await local();
                await using (null) { }
            }; // these awaits don't count towards Main method
        };
 
        async System.Threading.Tasks.Task local()
        {
            await local();
            await using (null) { }
            // neither do these
        }
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (4,53): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //     public static async System.Threading.Tasks.Task Main()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "Main").WithLocation(4, 53)
                );
        }
 
        [Fact]
        public void MissingAwaitInAsyncMethod2()
        {
            string source = @"
class C
{
    public static void Main()
    {
        System.Action lambda1 = async () =>
        {
            System.Action b = async () =>
            {
                await local();
                await using (null) { }
            }; // these awaits don't count towards lambda
        };
 
        System.Action lambda2 = async () => await local2(); // this await counts towards lambda
 
        async System.Threading.Tasks.Task local()
        {
            System.Func<System.Threading.Tasks.Task> c = innerLocal;
 
            async System.Threading.Tasks.Task innerLocal()
            {
                await local();
                await using (null) { }
                // these awaits don't count towards lambda either
            }
        }
 
        async System.Threading.Tasks.Task local2() => await local(); // this await counts towards local function
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (17,43): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         async System.Threading.Tasks.Task local()
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "local").WithLocation(17, 43),
                // (6,42): warning CS1998: This async method lacks 'await' operators and will run synchronously. Consider using the 'await' operator to await non-blocking API calls, or 'await Task.Run(...)' to do CPU-bound work on a background thread.
                //         System.Action lambda1 = async () =>
                Diagnostic(ErrorCode.WRN_AsyncLacksAwaits, "=>").WithLocation(6, 42)
                );
        }
 
        [Fact]
        public void TestInFinallyBlock()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    static async System.Threading.Tasks.Task<int> Main()
    {
        try
        {
        }
        finally
        {
            await using (var x = new C())
            {
                System.Console.Write(""using "");
            }
        }
 
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        public void TestThrowingDisposeAsync()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    static async System.Threading.Tasks.Task Main()
    {
        try
        {
            await using (var x = new C())
            {
                System.Console.Write(""using "");
            }
        }
        catch (System.Exception e)
        {
            System.Console.Write($""caught {e.Message}"");
            return;
        }
        System.Console.Write(""SKIPPED"");
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        bool b = true;
        if (b) throw new System.Exception(""message"");
        System.Console.Write(""SKIPPED"");
        await System.Threading.Tasks.Task.Yield();
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using caught message");
        }
 
        [Fact]
        public void TestRegularAwaitInFinallyBlock()
        {
            string source = @"
using System.Threading.Tasks;
class C
{
    static async Task<int> Main()
    {
        try
        {
        }
        finally
        {
            System.Console.Write(""before "");
            await Task.Yield();
            System.Console.Write(""after"");
        }
        return 1;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "before after");
        }
 
        [Fact]
        public void TestMissingIAsyncDisposable()
        {
            string source = @"
class C
{
    async System.Threading.Tasks.Task<int> M()
    {
        await using (new C())
        {
        }
        await using (var x = new C())
        {
            return 1;
        }
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(source);
            comp.VerifyDiagnostics(
                // (6,22): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "new C()").WithArguments("C").WithLocation(6, 22),
                // (9,22): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "var x = new C()").WithArguments("C").WithLocation(9, 22)
                );
        }
 
        [Fact]
        public void TestMissingIAsyncDisposableAndMissingValueTaskAndMissingAsync()
        {
            string source = @"
class C
{
    System.Threading.Tasks.Task<int> M()
    {
        await using (new C())
        {
        }
        await using (var x = new C())
        {
            return 1;
        }
    }
}
";
            var comp = CreateCompilationWithMscorlib46(source);
            comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_ValueTask);
            comp.VerifyDiagnostics(
                // (6,9): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<Task<int>>'.
                //         await using (new C())
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await").WithArguments("System.Threading.Tasks.Task<int>").WithLocation(6, 9),
                // (6,22): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "new C()").WithArguments("C").WithLocation(6, 22),
                // (9,9): error CS4032: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task<Task<int>>'.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutAsyncMethod, "await").WithArguments("System.Threading.Tasks.Task<int>").WithLocation(9, 9),
                // (9,22): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "var x = new C()").WithArguments("C").WithLocation(9, 22),
                // (11,20): error CS0029: Cannot implicitly convert type 'int' to 'System.Threading.Tasks.Task<int>'
                //             return 1;
                Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "System.Threading.Tasks.Task<int>").WithLocation(11, 20)
                );
        }
 
        [Fact]
        public void TestMissingIDisposable()
        {
            string source = @"
class C
{
    int M()
    {
        using (new C())
        {
        }
        using (var x = new C())
        {
            return 1;
        }
    }
}
";
            var comp = CreateCompilationWithMscorlib46(source);
            comp.MakeTypeMissing(SpecialType.System_IDisposable);
            comp.VerifyEmitDiagnostics(
                // (6,16): error CS1674: 'C': type used in a using statement must implement 'System.IDisposable'.
                //         using (new C())
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "new C()").WithArguments("C").WithLocation(6, 16),
                // (9,16): error CS1674: 'C': type used in a using statement must implement 'System.IDisposable'.
                //         using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "var x = new C()").WithArguments("C").WithLocation(9, 16)
                );
        }
 
        [Fact]
        public void TestMissingDisposeAsync()
        {
            string source = @"
namespace System
{
    public interface IAsyncDisposable
    {
        // missing DisposeAsync
    }
}
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task<int> M()
    {
        await using (new C()) { }
        await using (var x = new C()) { return 1; }
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(source);
            comp.VerifyDiagnostics();
            comp.VerifyEmitDiagnostics(
                // (13,9): error CS0656: Missing compiler required member 'System.IAsyncDisposable.DisposeAsync'
                //         await using (new C()) { }
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "await").WithArguments("System.IAsyncDisposable", "DisposeAsync").WithLocation(13, 9),
                // (14,9): error CS0656: Missing compiler required member 'System.IAsyncDisposable.DisposeAsync'
                //         await using (var x = new C()) { return 1; }
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "await").WithArguments("System.IAsyncDisposable", "DisposeAsync").WithLocation(14, 9)
                );
        }
 
        [Fact]
        public void TestMissingDispose()
        {
            string source = @"
class C : System.IDisposable
{
    int M()
    {
        using (new C()) { }
        using (var x = new C()) { return 1; }
    }
    public void Dispose()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(source);
            comp.MakeMemberMissing(SpecialMember.System_IDisposable__Dispose);
            comp.VerifyEmitDiagnostics(
                // (6,9): error CS0656: Missing compiler required member 'System.IDisposable.Dispose'
                //         using (new C()) { }
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "using (new C()) { }").WithArguments("System.IDisposable", "Dispose").WithLocation(6, 9),
                // (7,9): error CS0656: Missing compiler required member 'System.IDisposable.Dispose'
                //         using (var x = new C()) { return 1; }
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "using (var x = new C()) { return 1; }").WithArguments("System.IDisposable", "Dispose").WithLocation(7, 9)
                );
        }
 
        [Fact]
        public void TestBadDisposeAsync_01()
        {
            string source = @"
namespace System
{
    public interface IAsyncDisposable
    {
        int DisposeAsync(); // bad return type
    }
}
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task<int> M<T>()
    {
        await using (new C()) { }
        await using (var x = new C()) { return 1; }
    }
    int System.IAsyncDisposable.DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(source);
            comp.VerifyDiagnostics();
            comp.VerifyEmitDiagnostics(
                // (13,9): error CS0656: Missing compiler required member 'System.IAsyncDisposable.DisposeAsync'
                //         await using (new C()) { }
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "await").WithArguments("System.IAsyncDisposable", "DisposeAsync").WithLocation(13, 9),
                // (14,9): error CS0656: Missing compiler required member 'System.IAsyncDisposable.DisposeAsync'
                //         await using (var x = new C()) { return 1; }
                Diagnostic(ErrorCode.ERR_MissingPredefinedMember, "await").WithArguments("System.IAsyncDisposable", "DisposeAsync").WithLocation(14, 9)
                );
        }
 
        [Fact]
        public void TestBadDisposeAsync_02()
        {
            string source = @"
namespace System
{
    public interface IAsyncDisposable
    {
        int DisposeAsync(); // bad return type
    }
}
class C : System.IAsyncDisposable
{
    async System.Threading.Tasks.Task<int> M<T>()
    {
        await using (new C()) { }
        await using (var x = new C()) { return 1; }
    }
    public int DisposeAsync()
    {
        throw null;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(source);
            comp.VerifyDiagnostics(
                // (13,22): error CS1061: 'int' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
                //         await using (new C()) { }
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "new C()").WithArguments("int", "GetAwaiter").WithLocation(13, 22),
                // (14,22): error CS1061: 'int' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
                //         await using (var x = new C()) { return 1; }
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "var x = new C()").WithArguments("int", "GetAwaiter").WithLocation(14, 22)
                );
        }
 
        [Fact]
        public void TestMissingTaskType_01()
        {
            string lib_cs = @"
public class Base : System.IAsyncDisposable
{
    System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
 
            string comp_cs = @"
public class C : Base
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""body "");
            return 1;
        }
    }
}
";
            var libComp = CreateCompilationWithTasksExtensions(lib_cs + IAsyncDisposableDefinition);
            var comp = CreateCompilationWithTasksExtensions(comp_cs, references: new[] { libComp.EmitToImageReference() }, options: TestOptions.DebugExe);
            comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_ValueTask);
            comp.VerifyDiagnostics(
                // (6,9): error CS0518: Predefined type 'System.Threading.Tasks.ValueTask' is not defined or imported
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "await").WithArguments("System.Threading.Tasks.ValueTask").WithLocation(6, 9)
                );
        }
 
        [Fact]
        public void TestMissingTaskType_02()
        {
            string lib_cs = @"
public class Base : System.IAsyncDisposable
{
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
 
            string comp_cs = @"
public class C : Base
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""body "");
            return 1;
        }
    }
}
";
            var libComp = CreateCompilationWithTasksExtensions(lib_cs + IAsyncDisposableDefinition);
            var comp = CreateCompilationWithTasksExtensions(comp_cs, references: new[] { libComp.EmitToImageReference() }, options: TestOptions.DebugExe);
            comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_ValueTask);
            comp.VerifyEmitDiagnostics();
        }
 
        [Fact]
        public void TestWithDeclaration()
        {
            string source = @"
class C : System.IAsyncDisposable, System.IDisposable
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""body "");
            return 1;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
    public void Dispose()
    {
        System.Console.Write(""IGNORED"");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
        }
 
        [Fact]
        public void TestIAsyncDisposableInRegularUsing()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static int Main()
    {
        using (var x = new C())
        {
            return 1;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,16): error CS8418: 'C': type used in a using statement must implement 'System.IDisposable'. Did you mean 'await using' rather than 'using'?
                //         using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIDispWrongAsync, "var x = new C()").WithArguments("C").WithLocation(6, 16)
                );
        }
 
        [Fact]
        public void TestIAsyncDisposableInRegularUsing_Expression()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static int Main()
    {
        using (new C())
        {
            return 1;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,16): error CS8418: 'C': type used in a using statement must implement 'System.IDisposable'. Did you mean 'await using'?
                //         using (new C())
                Diagnostic(ErrorCode.ERR_NoConvToIDispWrongAsync, "new C()").WithArguments("C").WithLocation(6, 16)
                );
        }
 
        [Fact]
        public void TestIAsyncDisposableInRegularUsing_WithDispose()
        {
            string source = @"
class C : System.IAsyncDisposable, System.IDisposable
{
    public static int Main()
    {
        using (var x = new C())
        {
            System.Console.Write(""body "");
            return 1;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""IGNORED"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
    public void Dispose()
    {
        System.Console.Write(""Dispose"");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body Dispose");
        }
 
        [Fact]
        public void TestIDisposableInAwaitUsing()
        {
            string source = @"
class C : System.IDisposable
{
    async System.Threading.Tasks.Task<int> M()
    {
        await using (var x = new C())
        {
            return 1;
        }
    }
    public void Dispose()
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,22): error CS8417: 'C': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'?
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDispWrongAsync, "var x = new C()").WithArguments("C").WithLocation(6, 22)
                );
        }
 
        [Fact]
        public void TestIDisposableInAwaitUsing_Expression()
        {
            string source = @"
class C : System.IDisposable
{
    async System.Threading.Tasks.Task<int> M()
    {
        await using (new C())
        {
            return 1;
        }
    }
    public void Dispose()
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,22): error CS8417: 'C': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'. Did you mean 'using' rather than 'await using'?
                //         await using (new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDispWrongAsync, "new C()").WithArguments("C").WithLocation(6, 22)
                );
        }
 
        [Fact]
        public void TestWithDynamicDeclaration_ExplicitInterfaceImplementation()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (dynamic x = new C())
        {
            System.Console.Write(""body "");
        }
        System.Console.Write(""end "");
        return 1;
    }
    System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
    {
        System.Console.Write(""DisposeAsync "");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, references: new[] { CSharpRef });
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body DisposeAsync end");
        }
 
        [Fact]
        public void TestWithDynamicDeclaration()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (dynamic x = new C())
        {
            System.Console.Write(""body "");
        }
        System.Console.Write(""end "");
        return 1;
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync "");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, references: new[] { CSharpRef });
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body DisposeAsync end");
        }
 
        [Fact]
        public void TestWithExpression_01()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (new C())
        {
            System.Console.Write(""body "");
            return;
        }
    }
    System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            var verifier = CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
            verifier.VerifyIL("C.<Main>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      306 (0x132)
  .maxstack  3
  .locals init (int V_0,
                object V_1,
                System.Runtime.CompilerServices.ValueTaskAwaiter V_2,
                System.Threading.Tasks.ValueTask V_3,
                C.<Main>d__0 V_4,
                System.Exception V_5,
                int V_6)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int C.<Main>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_000c
    IL_000a:  br.s       IL_0011
    IL_000c:  br         IL_0099
    IL_0011:  nop
    IL_0012:  ldarg.0
    IL_0013:  newobj     ""C..ctor()""
    IL_0018:  stfld      ""C C.<Main>d__0.<>s__1""
    IL_001d:  ldarg.0
    IL_001e:  ldnull
    IL_001f:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_0024:  ldarg.0
    IL_0025:  ldc.i4.0
    IL_0026:  stfld      ""int C.<Main>d__0.<>s__3""
    .try
    {
      IL_002b:  nop
      IL_002c:  ldstr      ""body ""
      IL_0031:  call       ""void System.Console.Write(string)""
      IL_0036:  nop
      IL_0037:  br.s       IL_0039
      IL_0039:  ldarg.0
      IL_003a:  ldc.i4.1
      IL_003b:  stfld      ""int C.<Main>d__0.<>s__3""
      IL_0040:  leave.s    IL_004c
    }
    catch object
    {
      IL_0042:  stloc.1
      IL_0043:  ldarg.0
      IL_0044:  ldloc.1
      IL_0045:  stfld      ""object C.<Main>d__0.<>s__2""
      IL_004a:  leave.s    IL_004c
    }
    IL_004c:  ldarg.0
    IL_004d:  ldfld      ""C C.<Main>d__0.<>s__1""
    IL_0052:  brfalse.s  IL_00bd
    IL_0054:  ldarg.0
    IL_0055:  ldfld      ""C C.<Main>d__0.<>s__1""
    IL_005a:  callvirt   ""System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()""
    IL_005f:  stloc.3
    IL_0060:  ldloca.s   V_3
    IL_0062:  call       ""System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()""
    IL_0067:  stloc.2
    IL_0068:  ldloca.s   V_2
    IL_006a:  call       ""bool System.Runtime.CompilerServices.ValueTaskAwaiter.IsCompleted.get""
    IL_006f:  brtrue.s   IL_00b5
    IL_0071:  ldarg.0
    IL_0072:  ldc.i4.0
    IL_0073:  dup
    IL_0074:  stloc.0
    IL_0075:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_007a:  ldarg.0
    IL_007b:  ldloc.2
    IL_007c:  stfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_0081:  ldarg.0
    IL_0082:  stloc.s    V_4
    IL_0084:  ldarg.0
    IL_0085:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
    IL_008a:  ldloca.s   V_2
    IL_008c:  ldloca.s   V_4
    IL_008e:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.ValueTaskAwaiter, C.<Main>d__0>(ref System.Runtime.CompilerServices.ValueTaskAwaiter, ref C.<Main>d__0)""
    IL_0093:  nop
    IL_0094:  leave      IL_0131
    IL_0099:  ldarg.0
    IL_009a:  ldfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_009f:  stloc.2
    IL_00a0:  ldarg.0
    IL_00a1:  ldflda     ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_00a6:  initobj    ""System.Runtime.CompilerServices.ValueTaskAwaiter""
    IL_00ac:  ldarg.0
    IL_00ad:  ldc.i4.m1
    IL_00ae:  dup
    IL_00af:  stloc.0
    IL_00b0:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_00b5:  ldloca.s   V_2
    IL_00b7:  call       ""void System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()""
    IL_00bc:  nop
    IL_00bd:  ldarg.0
    IL_00be:  ldfld      ""object C.<Main>d__0.<>s__2""
    IL_00c3:  stloc.1
    IL_00c4:  ldloc.1
    IL_00c5:  brfalse.s  IL_00e2
    IL_00c7:  ldloc.1
    IL_00c8:  isinst     ""System.Exception""
    IL_00cd:  stloc.s    V_5
    IL_00cf:  ldloc.s    V_5
    IL_00d1:  brtrue.s   IL_00d5
    IL_00d3:  ldloc.1
    IL_00d4:  throw
    IL_00d5:  ldloc.s    V_5
    IL_00d7:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_00dc:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_00e1:  nop
    IL_00e2:  ldarg.0
    IL_00e3:  ldfld      ""int C.<Main>d__0.<>s__3""
    IL_00e8:  stloc.s    V_6
    IL_00ea:  ldloc.s    V_6
    IL_00ec:  ldc.i4.1
    IL_00ed:  beq.s      IL_00f1
    IL_00ef:  br.s       IL_00f3
    IL_00f1:  leave.s    IL_011d
    IL_00f3:  ldarg.0
    IL_00f4:  ldnull
    IL_00f5:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_00fa:  ldarg.0
    IL_00fb:  ldnull
    IL_00fc:  stfld      ""C C.<Main>d__0.<>s__1""
    IL_0101:  leave.s    IL_011d
  }
  catch System.Exception
  {
    IL_0103:  stloc.s    V_5
    IL_0105:  ldarg.0
    IL_0106:  ldc.i4.s   -2
    IL_0108:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_010d:  ldarg.0
    IL_010e:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
    IL_0113:  ldloc.s    V_5
    IL_0115:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
    IL_011a:  nop
    IL_011b:  leave.s    IL_0131
  }
  IL_011d:  ldarg.0
  IL_011e:  ldc.i4.s   -2
  IL_0120:  stfld      ""int C.<Main>d__0.<>1__state""
  IL_0125:  ldarg.0
  IL_0126:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
  IL_012b:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
  IL_0130:  nop
  IL_0131:  ret
}");
        }
 
        [Fact]
        public void TestWithExpression_02()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (new C())
        {
            System.Console.Write(""body "");
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            var verifier = CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
            verifier.VerifyIL("C.<Main>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      306 (0x132)
  .maxstack  3
  .locals init (int V_0,
                object V_1,
                System.Runtime.CompilerServices.ValueTaskAwaiter V_2,
                System.Threading.Tasks.ValueTask V_3,
                C.<Main>d__0 V_4,
                System.Exception V_5,
                int V_6)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int C.<Main>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_000c
    IL_000a:  br.s       IL_0011
    IL_000c:  br         IL_0099
    IL_0011:  nop
    IL_0012:  ldarg.0
    IL_0013:  newobj     ""C..ctor()""
    IL_0018:  stfld      ""C C.<Main>d__0.<>s__1""
    IL_001d:  ldarg.0
    IL_001e:  ldnull
    IL_001f:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_0024:  ldarg.0
    IL_0025:  ldc.i4.0
    IL_0026:  stfld      ""int C.<Main>d__0.<>s__3""
    .try
    {
      IL_002b:  nop
      IL_002c:  ldstr      ""body ""
      IL_0031:  call       ""void System.Console.Write(string)""
      IL_0036:  nop
      IL_0037:  br.s       IL_0039
      IL_0039:  ldarg.0
      IL_003a:  ldc.i4.1
      IL_003b:  stfld      ""int C.<Main>d__0.<>s__3""
      IL_0040:  leave.s    IL_004c
    }
    catch object
    {
      IL_0042:  stloc.1
      IL_0043:  ldarg.0
      IL_0044:  ldloc.1
      IL_0045:  stfld      ""object C.<Main>d__0.<>s__2""
      IL_004a:  leave.s    IL_004c
    }
    IL_004c:  ldarg.0
    IL_004d:  ldfld      ""C C.<Main>d__0.<>s__1""
    IL_0052:  brfalse.s  IL_00bd
    IL_0054:  ldarg.0
    IL_0055:  ldfld      ""C C.<Main>d__0.<>s__1""
    IL_005a:  callvirt   ""System.Threading.Tasks.ValueTask C.DisposeAsync()""
    IL_005f:  stloc.3
    IL_0060:  ldloca.s   V_3
    IL_0062:  call       ""System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()""
    IL_0067:  stloc.2
    IL_0068:  ldloca.s   V_2
    IL_006a:  call       ""bool System.Runtime.CompilerServices.ValueTaskAwaiter.IsCompleted.get""
    IL_006f:  brtrue.s   IL_00b5
    IL_0071:  ldarg.0
    IL_0072:  ldc.i4.0
    IL_0073:  dup
    IL_0074:  stloc.0
    IL_0075:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_007a:  ldarg.0
    IL_007b:  ldloc.2
    IL_007c:  stfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_0081:  ldarg.0
    IL_0082:  stloc.s    V_4
    IL_0084:  ldarg.0
    IL_0085:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
    IL_008a:  ldloca.s   V_2
    IL_008c:  ldloca.s   V_4
    IL_008e:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.ValueTaskAwaiter, C.<Main>d__0>(ref System.Runtime.CompilerServices.ValueTaskAwaiter, ref C.<Main>d__0)""
    IL_0093:  nop
    IL_0094:  leave      IL_0131
    IL_0099:  ldarg.0
    IL_009a:  ldfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_009f:  stloc.2
    IL_00a0:  ldarg.0
    IL_00a1:  ldflda     ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_00a6:  initobj    ""System.Runtime.CompilerServices.ValueTaskAwaiter""
    IL_00ac:  ldarg.0
    IL_00ad:  ldc.i4.m1
    IL_00ae:  dup
    IL_00af:  stloc.0
    IL_00b0:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_00b5:  ldloca.s   V_2
    IL_00b7:  call       ""void System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()""
    IL_00bc:  nop
    IL_00bd:  ldarg.0
    IL_00be:  ldfld      ""object C.<Main>d__0.<>s__2""
    IL_00c3:  stloc.1
    IL_00c4:  ldloc.1
    IL_00c5:  brfalse.s  IL_00e2
    IL_00c7:  ldloc.1
    IL_00c8:  isinst     ""System.Exception""
    IL_00cd:  stloc.s    V_5
    IL_00cf:  ldloc.s    V_5
    IL_00d1:  brtrue.s   IL_00d5
    IL_00d3:  ldloc.1
    IL_00d4:  throw
    IL_00d5:  ldloc.s    V_5
    IL_00d7:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_00dc:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_00e1:  nop
    IL_00e2:  ldarg.0
    IL_00e3:  ldfld      ""int C.<Main>d__0.<>s__3""
    IL_00e8:  stloc.s    V_6
    IL_00ea:  ldloc.s    V_6
    IL_00ec:  ldc.i4.1
    IL_00ed:  beq.s      IL_00f1
    IL_00ef:  br.s       IL_00f3
    IL_00f1:  leave.s    IL_011d
    IL_00f3:  ldarg.0
    IL_00f4:  ldnull
    IL_00f5:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_00fa:  ldarg.0
    IL_00fb:  ldnull
    IL_00fc:  stfld      ""C C.<Main>d__0.<>s__1""
    IL_0101:  leave.s    IL_011d
  }
  catch System.Exception
  {
    IL_0103:  stloc.s    V_5
    IL_0105:  ldarg.0
    IL_0106:  ldc.i4.s   -2
    IL_0108:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_010d:  ldarg.0
    IL_010e:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
    IL_0113:  ldloc.s    V_5
    IL_0115:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
    IL_011a:  nop
    IL_011b:  leave.s    IL_0131
  }
  IL_011d:  ldarg.0
  IL_011e:  ldc.i4.s   -2
  IL_0120:  stfld      ""int C.<Main>d__0.<>1__state""
  IL_0125:  ldarg.0
  IL_0126:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
  IL_012b:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
  IL_0130:  nop
  IL_0131:  ret
}
");
        }
 
        [Fact]
        public void TestWithExpression_03()
        {
            string source = @"
class C
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (new C())
        {
            System.Console.Write(""body "");
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            var verifier = CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
            verifier.VerifyIL("C.<Main>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      306 (0x132)
  .maxstack  3
  .locals init (int V_0,
                object V_1,
                System.Runtime.CompilerServices.ValueTaskAwaiter V_2,
                System.Threading.Tasks.ValueTask V_3,
                C.<Main>d__0 V_4,
                System.Exception V_5,
                int V_6)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int C.<Main>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_000c
    IL_000a:  br.s       IL_0011
    IL_000c:  br         IL_0099
    IL_0011:  nop
    IL_0012:  ldarg.0
    IL_0013:  newobj     ""C..ctor()""
    IL_0018:  stfld      ""C C.<Main>d__0.<>s__1""
    IL_001d:  ldarg.0
    IL_001e:  ldnull
    IL_001f:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_0024:  ldarg.0
    IL_0025:  ldc.i4.0
    IL_0026:  stfld      ""int C.<Main>d__0.<>s__3""
    .try
    {
      IL_002b:  nop
      IL_002c:  ldstr      ""body ""
      IL_0031:  call       ""void System.Console.Write(string)""
      IL_0036:  nop
      IL_0037:  br.s       IL_0039
      IL_0039:  ldarg.0
      IL_003a:  ldc.i4.1
      IL_003b:  stfld      ""int C.<Main>d__0.<>s__3""
      IL_0040:  leave.s    IL_004c
    }
    catch object
    {
      IL_0042:  stloc.1
      IL_0043:  ldarg.0
      IL_0044:  ldloc.1
      IL_0045:  stfld      ""object C.<Main>d__0.<>s__2""
      IL_004a:  leave.s    IL_004c
    }
    IL_004c:  ldarg.0
    IL_004d:  ldfld      ""C C.<Main>d__0.<>s__1""
    IL_0052:  brfalse.s  IL_00bd
    IL_0054:  ldarg.0
    IL_0055:  ldfld      ""C C.<Main>d__0.<>s__1""
    IL_005a:  callvirt   ""System.Threading.Tasks.ValueTask C.DisposeAsync()""
    IL_005f:  stloc.3
    IL_0060:  ldloca.s   V_3
    IL_0062:  call       ""System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()""
    IL_0067:  stloc.2
    IL_0068:  ldloca.s   V_2
    IL_006a:  call       ""bool System.Runtime.CompilerServices.ValueTaskAwaiter.IsCompleted.get""
    IL_006f:  brtrue.s   IL_00b5
    IL_0071:  ldarg.0
    IL_0072:  ldc.i4.0
    IL_0073:  dup
    IL_0074:  stloc.0
    IL_0075:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_007a:  ldarg.0
    IL_007b:  ldloc.2
    IL_007c:  stfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_0081:  ldarg.0
    IL_0082:  stloc.s    V_4
    IL_0084:  ldarg.0
    IL_0085:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
    IL_008a:  ldloca.s   V_2
    IL_008c:  ldloca.s   V_4
    IL_008e:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.ValueTaskAwaiter, C.<Main>d__0>(ref System.Runtime.CompilerServices.ValueTaskAwaiter, ref C.<Main>d__0)""
    IL_0093:  nop
    IL_0094:  leave      IL_0131
    IL_0099:  ldarg.0
    IL_009a:  ldfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_009f:  stloc.2
    IL_00a0:  ldarg.0
    IL_00a1:  ldflda     ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_00a6:  initobj    ""System.Runtime.CompilerServices.ValueTaskAwaiter""
    IL_00ac:  ldarg.0
    IL_00ad:  ldc.i4.m1
    IL_00ae:  dup
    IL_00af:  stloc.0
    IL_00b0:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_00b5:  ldloca.s   V_2
    IL_00b7:  call       ""void System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()""
    IL_00bc:  nop
    IL_00bd:  ldarg.0
    IL_00be:  ldfld      ""object C.<Main>d__0.<>s__2""
    IL_00c3:  stloc.1
    IL_00c4:  ldloc.1
    IL_00c5:  brfalse.s  IL_00e2
    IL_00c7:  ldloc.1
    IL_00c8:  isinst     ""System.Exception""
    IL_00cd:  stloc.s    V_5
    IL_00cf:  ldloc.s    V_5
    IL_00d1:  brtrue.s   IL_00d5
    IL_00d3:  ldloc.1
    IL_00d4:  throw
    IL_00d5:  ldloc.s    V_5
    IL_00d7:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_00dc:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_00e1:  nop
    IL_00e2:  ldarg.0
    IL_00e3:  ldfld      ""int C.<Main>d__0.<>s__3""
    IL_00e8:  stloc.s    V_6
    IL_00ea:  ldloc.s    V_6
    IL_00ec:  ldc.i4.1
    IL_00ed:  beq.s      IL_00f1
    IL_00ef:  br.s       IL_00f3
    IL_00f1:  leave.s    IL_011d
    IL_00f3:  ldarg.0
    IL_00f4:  ldnull
    IL_00f5:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_00fa:  ldarg.0
    IL_00fb:  ldnull
    IL_00fc:  stfld      ""C C.<Main>d__0.<>s__1""
    IL_0101:  leave.s    IL_011d
  }
  catch System.Exception
  {
    IL_0103:  stloc.s    V_5
    IL_0105:  ldarg.0
    IL_0106:  ldc.i4.s   -2
    IL_0108:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_010d:  ldarg.0
    IL_010e:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
    IL_0113:  ldloc.s    V_5
    IL_0115:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
    IL_011a:  nop
    IL_011b:  leave.s    IL_0131
  }
  IL_011d:  ldarg.0
  IL_011e:  ldc.i4.s   -2
  IL_0120:  stfld      ""int C.<Main>d__0.<>1__state""
  IL_0125:  ldarg.0
  IL_0126:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder C.<Main>d__0.<>t__builder""
  IL_012b:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
  IL_0130:  nop
  IL_0131:  ret
}
");
        }
 
        [Fact]
        public void TestWithNullExpression()
        {
            string source = @"
class C
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (null)
        {
            System.Console.Write(""body"");
            return;
        }
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body");
        }
 
        [Fact]
        public void TestWithMethodName()
        {
            string source = @"
class C
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (Main)
        {
        }
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,22): error CS8410: 'method group': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable'
                //         await using (Main)
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "Main").WithArguments("method group").WithLocation(6, 22)
                );
        }
 
        [Fact]
        public void TestWithDynamicExpression()
        {
            string source = @"
class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        dynamic d = new C();
        await using (d)
        {
            System.Console.Write(""body "");
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe, references: new[] { CSharpRef });
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
        }
 
        [Fact]
        public void TestWithStructExpression_01()
        {
            string source = @"
struct S : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (new S())
        {
            System.Console.Write(""body "");
            return;
        }
    }
    System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            var verifier = CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
            verifier.VerifyIL("S.<Main>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      298 (0x12a)
  .maxstack  3
  .locals init (int V_0,
                object V_1,
                System.Runtime.CompilerServices.ValueTaskAwaiter V_2,
                System.Threading.Tasks.ValueTask V_3,
                S.<Main>d__0 V_4,
                System.Exception V_5,
                int V_6)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int S.<Main>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_000c
    IL_000a:  br.s       IL_0011
    IL_000c:  br         IL_0098
    IL_0011:  nop
    IL_0012:  ldarg.0
    IL_0013:  ldflda     ""S S.<Main>d__0.<>s__1""
    IL_0018:  initobj    ""S""
    IL_001e:  ldarg.0
    IL_001f:  ldnull
    IL_0020:  stfld      ""object S.<Main>d__0.<>s__2""
    IL_0025:  ldarg.0
    IL_0026:  ldc.i4.0
    IL_0027:  stfld      ""int S.<Main>d__0.<>s__3""
    .try
    {
      IL_002c:  nop
      IL_002d:  ldstr      ""body ""
      IL_0032:  call       ""void System.Console.Write(string)""
      IL_0037:  nop
      IL_0038:  br.s       IL_003a
      IL_003a:  ldarg.0
      IL_003b:  ldc.i4.1
      IL_003c:  stfld      ""int S.<Main>d__0.<>s__3""
      IL_0041:  leave.s    IL_004d
    }
    catch object
    {
      IL_0043:  stloc.1
      IL_0044:  ldarg.0
      IL_0045:  ldloc.1
      IL_0046:  stfld      ""object S.<Main>d__0.<>s__2""
      IL_004b:  leave.s    IL_004d
    }
    IL_004d:  ldarg.0
    IL_004e:  ldflda     ""S S.<Main>d__0.<>s__1""
    IL_0053:  constrained. ""S""
    IL_0059:  callvirt   ""System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()""
    IL_005e:  stloc.3
    IL_005f:  ldloca.s   V_3
    IL_0061:  call       ""System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()""
    IL_0066:  stloc.2
    IL_0067:  ldloca.s   V_2
    IL_0069:  call       ""bool System.Runtime.CompilerServices.ValueTaskAwaiter.IsCompleted.get""
    IL_006e:  brtrue.s   IL_00b4
    IL_0070:  ldarg.0
    IL_0071:  ldc.i4.0
    IL_0072:  dup
    IL_0073:  stloc.0
    IL_0074:  stfld      ""int S.<Main>d__0.<>1__state""
    IL_0079:  ldarg.0
    IL_007a:  ldloc.2
    IL_007b:  stfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter S.<Main>d__0.<>u__1""
    IL_0080:  ldarg.0
    IL_0081:  stloc.s    V_4
    IL_0083:  ldarg.0
    IL_0084:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder S.<Main>d__0.<>t__builder""
    IL_0089:  ldloca.s   V_2
    IL_008b:  ldloca.s   V_4
    IL_008d:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.ValueTaskAwaiter, S.<Main>d__0>(ref System.Runtime.CompilerServices.ValueTaskAwaiter, ref S.<Main>d__0)""
    IL_0092:  nop
    IL_0093:  leave      IL_0129
    IL_0098:  ldarg.0
    IL_0099:  ldfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter S.<Main>d__0.<>u__1""
    IL_009e:  stloc.2
    IL_009f:  ldarg.0
    IL_00a0:  ldflda     ""System.Runtime.CompilerServices.ValueTaskAwaiter S.<Main>d__0.<>u__1""
    IL_00a5:  initobj    ""System.Runtime.CompilerServices.ValueTaskAwaiter""
    IL_00ab:  ldarg.0
    IL_00ac:  ldc.i4.m1
    IL_00ad:  dup
    IL_00ae:  stloc.0
    IL_00af:  stfld      ""int S.<Main>d__0.<>1__state""
    IL_00b4:  ldloca.s   V_2
    IL_00b6:  call       ""void System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()""
    IL_00bb:  nop
    IL_00bc:  ldarg.0
    IL_00bd:  ldfld      ""object S.<Main>d__0.<>s__2""
    IL_00c2:  stloc.1
    IL_00c3:  ldloc.1
    IL_00c4:  brfalse.s  IL_00e1
    IL_00c6:  ldloc.1
    IL_00c7:  isinst     ""System.Exception""
    IL_00cc:  stloc.s    V_5
    IL_00ce:  ldloc.s    V_5
    IL_00d0:  brtrue.s   IL_00d4
    IL_00d2:  ldloc.1
    IL_00d3:  throw
    IL_00d4:  ldloc.s    V_5
    IL_00d6:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_00db:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_00e0:  nop
    IL_00e1:  ldarg.0
    IL_00e2:  ldfld      ""int S.<Main>d__0.<>s__3""
    IL_00e7:  stloc.s    V_6
    IL_00e9:  ldloc.s    V_6
    IL_00eb:  ldc.i4.1
    IL_00ec:  beq.s      IL_00f0
    IL_00ee:  br.s       IL_00f2
    IL_00f0:  leave.s    IL_0115
    IL_00f2:  ldarg.0
    IL_00f3:  ldnull
    IL_00f4:  stfld      ""object S.<Main>d__0.<>s__2""
    IL_00f9:  leave.s    IL_0115
  }
  catch System.Exception
  {
    IL_00fb:  stloc.s    V_5
    IL_00fd:  ldarg.0
    IL_00fe:  ldc.i4.s   -2
    IL_0100:  stfld      ""int S.<Main>d__0.<>1__state""
    IL_0105:  ldarg.0
    IL_0106:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder S.<Main>d__0.<>t__builder""
    IL_010b:  ldloc.s    V_5
    IL_010d:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
    IL_0112:  nop
    IL_0113:  leave.s    IL_0129
  }
  IL_0115:  ldarg.0
  IL_0116:  ldc.i4.s   -2
  IL_0118:  stfld      ""int S.<Main>d__0.<>1__state""
  IL_011d:  ldarg.0
  IL_011e:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder S.<Main>d__0.<>t__builder""
  IL_0123:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
  IL_0128:  nop
  IL_0129:  ret
}");
        }
 
        [Fact]
        public void TestWithStructExpression_02()
        {
            string source = @"
struct S : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        await using (new S())
        {
            System.Console.Write(""body "");
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            var verifier = CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
            verifier.VerifyIL("S.<Main>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      292 (0x124)
  .maxstack  3
  .locals init (int V_0,
                object V_1,
                System.Runtime.CompilerServices.ValueTaskAwaiter V_2,
                System.Threading.Tasks.ValueTask V_3,
                S.<Main>d__0 V_4,
                System.Exception V_5,
                int V_6)
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int S.<Main>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_000c
    IL_000a:  br.s       IL_0011
    IL_000c:  br         IL_0092
    IL_0011:  nop
    IL_0012:  ldarg.0
    IL_0013:  ldflda     ""S S.<Main>d__0.<>s__1""
    IL_0018:  initobj    ""S""
    IL_001e:  ldarg.0
    IL_001f:  ldnull
    IL_0020:  stfld      ""object S.<Main>d__0.<>s__2""
    IL_0025:  ldarg.0
    IL_0026:  ldc.i4.0
    IL_0027:  stfld      ""int S.<Main>d__0.<>s__3""
    .try
    {
      IL_002c:  nop
      IL_002d:  ldstr      ""body ""
      IL_0032:  call       ""void System.Console.Write(string)""
      IL_0037:  nop
      IL_0038:  br.s       IL_003a
      IL_003a:  ldarg.0
      IL_003b:  ldc.i4.1
      IL_003c:  stfld      ""int S.<Main>d__0.<>s__3""
      IL_0041:  leave.s    IL_004d
    }
    catch object
    {
      IL_0043:  stloc.1
      IL_0044:  ldarg.0
      IL_0045:  ldloc.1
      IL_0046:  stfld      ""object S.<Main>d__0.<>s__2""
      IL_004b:  leave.s    IL_004d
    }
    IL_004d:  ldarg.0
    IL_004e:  ldflda     ""S S.<Main>d__0.<>s__1""
    IL_0053:  call       ""System.Threading.Tasks.ValueTask S.DisposeAsync()""
    IL_0058:  stloc.3
    IL_0059:  ldloca.s   V_3
    IL_005b:  call       ""System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()""
    IL_0060:  stloc.2
    IL_0061:  ldloca.s   V_2
    IL_0063:  call       ""bool System.Runtime.CompilerServices.ValueTaskAwaiter.IsCompleted.get""
    IL_0068:  brtrue.s   IL_00ae
    IL_006a:  ldarg.0
    IL_006b:  ldc.i4.0
    IL_006c:  dup
    IL_006d:  stloc.0
    IL_006e:  stfld      ""int S.<Main>d__0.<>1__state""
    IL_0073:  ldarg.0
    IL_0074:  ldloc.2
    IL_0075:  stfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter S.<Main>d__0.<>u__1""
    IL_007a:  ldarg.0
    IL_007b:  stloc.s    V_4
    IL_007d:  ldarg.0
    IL_007e:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder S.<Main>d__0.<>t__builder""
    IL_0083:  ldloca.s   V_2
    IL_0085:  ldloca.s   V_4
    IL_0087:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.ValueTaskAwaiter, S.<Main>d__0>(ref System.Runtime.CompilerServices.ValueTaskAwaiter, ref S.<Main>d__0)""
    IL_008c:  nop
    IL_008d:  leave      IL_0123
    IL_0092:  ldarg.0
    IL_0093:  ldfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter S.<Main>d__0.<>u__1""
    IL_0098:  stloc.2
    IL_0099:  ldarg.0
    IL_009a:  ldflda     ""System.Runtime.CompilerServices.ValueTaskAwaiter S.<Main>d__0.<>u__1""
    IL_009f:  initobj    ""System.Runtime.CompilerServices.ValueTaskAwaiter""
    IL_00a5:  ldarg.0
    IL_00a6:  ldc.i4.m1
    IL_00a7:  dup
    IL_00a8:  stloc.0
    IL_00a9:  stfld      ""int S.<Main>d__0.<>1__state""
    IL_00ae:  ldloca.s   V_2
    IL_00b0:  call       ""void System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()""
    IL_00b5:  nop
    IL_00b6:  ldarg.0
    IL_00b7:  ldfld      ""object S.<Main>d__0.<>s__2""
    IL_00bc:  stloc.1
    IL_00bd:  ldloc.1
    IL_00be:  brfalse.s  IL_00db
    IL_00c0:  ldloc.1
    IL_00c1:  isinst     ""System.Exception""
    IL_00c6:  stloc.s    V_5
    IL_00c8:  ldloc.s    V_5
    IL_00ca:  brtrue.s   IL_00ce
    IL_00cc:  ldloc.1
    IL_00cd:  throw
    IL_00ce:  ldloc.s    V_5
    IL_00d0:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_00d5:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_00da:  nop
    IL_00db:  ldarg.0
    IL_00dc:  ldfld      ""int S.<Main>d__0.<>s__3""
    IL_00e1:  stloc.s    V_6
    IL_00e3:  ldloc.s    V_6
    IL_00e5:  ldc.i4.1
    IL_00e6:  beq.s      IL_00ea
    IL_00e8:  br.s       IL_00ec
    IL_00ea:  leave.s    IL_010f
    IL_00ec:  ldarg.0
    IL_00ed:  ldnull
    IL_00ee:  stfld      ""object S.<Main>d__0.<>s__2""
    IL_00f3:  leave.s    IL_010f
  }
  catch System.Exception
  {
    IL_00f5:  stloc.s    V_5
    IL_00f7:  ldarg.0
    IL_00f8:  ldc.i4.s   -2
    IL_00fa:  stfld      ""int S.<Main>d__0.<>1__state""
    IL_00ff:  ldarg.0
    IL_0100:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder S.<Main>d__0.<>t__builder""
    IL_0105:  ldloc.s    V_5
    IL_0107:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetException(System.Exception)""
    IL_010c:  nop
    IL_010d:  leave.s    IL_0123
  }
  IL_010f:  ldarg.0
  IL_0110:  ldc.i4.s   -2
  IL_0112:  stfld      ""int S.<Main>d__0.<>1__state""
  IL_0117:  ldarg.0
  IL_0118:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder S.<Main>d__0.<>t__builder""
  IL_011d:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder.SetResult()""
  IL_0122:  nop
  IL_0123:  ret
}");
        }
 
        [Fact]
        public void Struct_ExplicitImplementation()
        {
            string source =
@"using System;
using System.Threading.Tasks;
class C
{
    internal bool _disposed;
}
struct S : IAsyncDisposable
{
    C _c;
    S(C c)
    {
        _c = c;
    }
    static async Task Main()
    {
        var s = new S(new C());
        await using (s)
        {
        }
        Console.WriteLine(s._c._disposed);
    }
    ValueTask IAsyncDisposable.DisposeAsync()
    {
        _c._disposed = true;
        return new ValueTask(Task.CompletedTask);
    }
}";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "True");
        }
 
        [Fact]
        public void TestWithNullableExpression()
        {
            string source = @"
struct S : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        S? s = new S();
        await using (s)
        {
            System.Console.Write(""body "");
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""DisposeAsync"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body DisposeAsync");
        }
 
        [Fact]
        public void TestWithNullNullableExpression()
        {
            string source = @"
struct S : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task Main()
    {
        S? s = null;
        await using (s)
        {
            System.Console.Write(""body"");
            return;
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write(""NOT RELEVANT"");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "body");
        }
 
        [Fact]
        [WorkItem(24267, "https://github.com/dotnet/roslyn/issues/24267")]
        public void AssignsInAsyncWithAwaitUsing()
        {
            var comp = CreateCompilationWithTasksExtensions(@"
class C
{
    public static void M2()
    {
        int a=0, x, y, z;
        L1();
        a++;
        x++;
        y++;
        z++;
 
        async void L1()
        {
            x = 0;
            await using (null) { }
            y = 0;
 
            // local function exists with a pending branch from the async using, in which `y` was not assigned
        }
    }
}" + IAsyncDisposableDefinition);
            comp.VerifyDiagnostics(
                // (9,9): error CS0165: Use of unassigned local variable 'x'
                //         x++;
                Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(9, 9),
                // (10,9): error CS0165: Use of unassigned local variable 'y'
                //         y++;
                Diagnostic(ErrorCode.ERR_UseDefViolation, "y").WithArguments("y").WithLocation(10, 9),
                // (11,9): error CS0165: Use of unassigned local variable 'z'
                //         z++;
                Diagnostic(ErrorCode.ERR_UseDefViolation, "z").WithArguments("z").WithLocation(11, 9)
                );
        }
 
        [Fact]
        public void TestWithMultipleResources()
        {
            string source = @"
class S : System.IAsyncDisposable
{
    private int _i;
    S(int i)
    {
        System.Console.Write($""ctor{i} "");
        _i = i;
    }
    public static async System.Threading.Tasks.Task Main()
    {
        await using (S s1 = new S(1), s2 = new S(2))
        {
            System.Console.Write(""body "");
            return;
        }
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose{_i}_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose{_i}_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "ctor1 ctor2 body dispose2_start dispose2_end dispose1_start dispose1_end");
        }
 
        [Fact]
        public void TestWithMultipleResourcesAndException()
        {
            string source = @"
class S : System.IAsyncDisposable
{
    private int _i;
    S(int i)
    {
        System.Console.Write($""ctor{i} "");
        _i = i;
    }
    public static async System.Threading.Tasks.Task Main()
    {
        try
        {
            await using (S s1 = new S(1), s2 = new S(2))
            {
                System.Console.Write(""body "");
                throw new System.Exception();
            }
        }
        catch (System.Exception)
        {
            System.Console.Write(""caught"");
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose{_i} "");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "ctor1 ctor2 body dispose2 dispose1 caught");
        }
 
        [Fact]
        public void TestWithMultipleResourcesAndExceptionInSecondResource()
        {
            string source = @"
class S : System.IAsyncDisposable
{
    private int _i;
    S(int i)
    {
        System.Console.Write($""ctor{i} "");
        if (i == 1)
        {
            _i = i;
        }
        else
        {
            throw new System.Exception();
        }
    }
    public static async System.Threading.Tasks.Task Main()
    {
        try
        {
            await using (S s1 = new S(1), s2 = new S(2))
            {
                System.Console.Write(""SKIPPED"");
            }
        }
        catch (System.Exception)
        {
            System.Console.Write(""caught"");
        }
    }
    public System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose{_i} "");
        return new System.Threading.Tasks.ValueTask(System.Threading.Tasks.Task.CompletedTask);
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "ctor1 ctor2 dispose1 caught");
        }
 
        [Fact]
        public void TestAwaitExpressionInfo_IEquatable()
        {
            string source = @"
public class C
{
    void GetAwaiter() { }
    void GetResult() { }
    bool IsCompleted => true;
}
public class D
{
    void GetAwaiter() { }
    void GetResult() { }
    bool IsCompleted => true;
}
";
            var comp = CreateCompilation(source);
            var getAwaiter1 = (MethodSymbol)comp.GetMember("C.GetAwaiter");
            var isCompleted1 = (PropertySymbol)comp.GetMember("C.IsCompleted");
            var getResult1 = (MethodSymbol)comp.GetMember("C.GetResult");
            var first = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), isCompleted1.GetPublicSymbol(), getResult1.GetPublicSymbol(), false);
 
            var nulls1 = new AwaitExpressionInfo(null, isCompleted1.GetPublicSymbol(), getResult1.GetPublicSymbol(), false);
            var nulls2 = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), null, getResult1.GetPublicSymbol(), false);
            var nulls3 = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), isCompleted1.GetPublicSymbol(), null, false);
            var nulls4 = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), isCompleted1.GetPublicSymbol(), null, true);
 
            Assert.False(first.Equals(nulls1));
            Assert.False(first.Equals(nulls2));
            Assert.False(first.Equals(nulls3));
            Assert.False(first.Equals(nulls4));
 
            Assert.False(nulls1.Equals(first));
            Assert.False(nulls2.Equals(first));
            Assert.False(nulls3.Equals(first));
            Assert.False(nulls4.Equals(first));
 
            _ = nulls1.GetHashCode();
            _ = nulls2.GetHashCode();
            _ = nulls3.GetHashCode();
            _ = nulls4.GetHashCode();
 
            object nullObj = null;
            Assert.False(first.Equals(nullObj));
 
            var getAwaiter2 = (MethodSymbol)comp.GetMember("D.GetAwaiter");
            var isCompleted2 = (PropertySymbol)comp.GetMember("D.IsCompleted");
            var getResult2 = (MethodSymbol)comp.GetMember("D.GetResult");
            var second1 = new AwaitExpressionInfo(getAwaiter2.GetPublicSymbol(), isCompleted1.GetPublicSymbol(), getResult1.GetPublicSymbol(), false);
            var second2 = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), isCompleted2.GetPublicSymbol(), getResult1.GetPublicSymbol(), false);
            var second3 = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), isCompleted1.GetPublicSymbol(), getResult2.GetPublicSymbol(), false);
            var second4 = new AwaitExpressionInfo(getAwaiter2.GetPublicSymbol(), isCompleted2.GetPublicSymbol(), getResult2.GetPublicSymbol(), false);
 
            Assert.False(first.Equals(second1));
            Assert.False(first.Equals(second2));
            Assert.False(first.Equals(second3));
            Assert.False(first.Equals(second4));
 
            Assert.False(second1.Equals(first));
            Assert.False(second2.Equals(first));
            Assert.False(second3.Equals(first));
            Assert.False(second4.Equals(first));
 
            Assert.True(first.Equals(first));
            Assert.True(first.Equals((object)first));
 
            var another = new AwaitExpressionInfo(getAwaiter1.GetPublicSymbol(), isCompleted1.GetPublicSymbol(), getResult1.GetPublicSymbol(), false);
            Assert.True(first.GetHashCode() == another.GetHashCode());
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_ExtensionMethod()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
        }
 
        return 1;
    }
}
public static class Extensions
{
    public static System.Threading.Tasks.ValueTask DisposeAsync(this C c)
        => throw null;
}
";
            // extension methods do not contribute to pattern-based disposal
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (6,22): error CS8410: 'C': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "var x = new C()").WithArguments("C").WithLocation(6, 22)
                );
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_TwoOverloads()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
        }
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync(int i = 0)
    {
        System.Console.Write($""dispose"");
        await System.Threading.Tasks.Task.Yield();
    }
    public System.Threading.Tasks.ValueTask DisposeAsync(params string[] s)
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "dispose");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_Expression_ExtensionMethod()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (new C())
        {
        }
 
        return 1;
    }
}
public static class Extensions
{
    public static System.Threading.Tasks.ValueTask DisposeAsync(this C c)
        => throw null;
}
";
            // extension methods do not contribute to pattern-based disposal
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics(
                // (6,22): error CS8410: 'C': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "new C()").WithArguments("C").WithLocation(6, 22)
                );
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_Expression_InstanceMethod()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (new C())
        {
            System.Console.Write(""using "");
        }
 
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""using "");
        }
 
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        [WorkItem("https://github.com/dotnet/roslyn/issues/72573")]
        public void TestPatternBasedDisposal_InterfaceNotPreferredOverInstanceMethod()
        {
            string source = @"
public class C : System.IAsyncDisposable
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""using "");
        }
 
        System.Console.Write(""return"");
        return 1;
    }
    System.Threading.Tasks.ValueTask System.IAsyncDisposable.DisposeAsync()
        => throw null;
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod_OptionalParameter()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""using "");
        }
 
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync(int i = 0)
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod_ParamsParameter()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
            System.Console.Write(""using "");
        }
 
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync(params int[] x)
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end({x.Length}) "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end(0) return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod_ReturningVoid()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
        }
 
        return 1;
    }
    public void DisposeAsync()
    {
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,22): error CS4008: Cannot await 'void'
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_BadAwaitArgVoidCall, "var x = new C()").WithLocation(6, 22)
                );
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod_ReturningInt()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
        }
 
        return 1;
    }
    public int DisposeAsync()
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,22): error CS1061: 'int' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?)
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "var x = new C()").WithArguments("int", "GetAwaiter").WithLocation(6, 22)
                );
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod_Inaccessible()
        {
            string source = @"
public class D
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        await using (var x = new C())
        {
        }
 
        return 1;
    }
}
public class C
{
    private System.Threading.Tasks.ValueTask DisposeAsync()
        => throw null;
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // 0.cs(6,22): error CS8410: 'C': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (var x = new C())
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "var x = new C()").WithArguments("C").WithLocation(6, 22));
        }
 
        [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_InstanceMethod_UsingDeclaration()
        {
            string source = @"
public class C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        {
            await using var x = new C();
            System.Console.Write(""using "");
        }
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.ValueTask DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            var verifier = CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
 
            // Sequence point highlights `await using ...`
            verifier.VerifyIL("C.<Main>d__0.System.Runtime.CompilerServices.IAsyncStateMachine.MoveNext()", @"
{
  // Code size      303 (0x12f)
  .maxstack  3
  .locals init (int V_0,
                int V_1,
                object V_2,
                System.Runtime.CompilerServices.ValueTaskAwaiter V_3,
                System.Threading.Tasks.ValueTask V_4,
                C.<Main>d__0 V_5,
                System.Exception V_6)
  // sequence point: <hidden>
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""int C.<Main>d__0.<>1__state""
  IL_0006:  stloc.0
  .try
  {
    // sequence point: <hidden>
    IL_0007:  ldloc.0
    IL_0008:  brfalse.s  IL_000c
    IL_000a:  br.s       IL_0011
    IL_000c:  br         IL_0091
    // sequence point: {
    IL_0011:  nop
    // sequence point: {
    IL_0012:  nop
    // sequence point: await using var x = new C();
    IL_0013:  ldarg.0
    IL_0014:  newobj     ""C..ctor()""
    IL_0019:  stfld      ""C C.<Main>d__0.<x>5__1""
    // sequence point: <hidden>
    IL_001e:  ldarg.0
    IL_001f:  ldnull
    IL_0020:  stfld      ""object C.<Main>d__0.<>s__2""
    IL_0025:  ldarg.0
    IL_0026:  ldc.i4.0
    IL_0027:  stfld      ""int C.<Main>d__0.<>s__3""
    .try
    {
      // sequence point: System.Console.Write(""using "");
      IL_002c:  ldstr      ""using ""
      IL_0031:  call       ""void System.Console.Write(string)""
      IL_0036:  nop
      // sequence point: <hidden>
      IL_0037:  leave.s    IL_0043
    }
    catch object
    {
      // sequence point: <hidden>
      IL_0039:  stloc.2
      IL_003a:  ldarg.0
      IL_003b:  ldloc.2
      IL_003c:  stfld      ""object C.<Main>d__0.<>s__2""
      IL_0041:  leave.s    IL_0043
    }
    // sequence point: <hidden>
    IL_0043:  ldarg.0
    IL_0044:  ldfld      ""C C.<Main>d__0.<x>5__1""
    IL_0049:  brfalse.s  IL_00b5
    IL_004b:  ldarg.0
    IL_004c:  ldfld      ""C C.<Main>d__0.<x>5__1""
    IL_0051:  callvirt   ""System.Threading.Tasks.ValueTask C.DisposeAsync()""
    IL_0056:  stloc.s    V_4
    IL_0058:  ldloca.s   V_4
    IL_005a:  call       ""System.Runtime.CompilerServices.ValueTaskAwaiter System.Threading.Tasks.ValueTask.GetAwaiter()""
    IL_005f:  stloc.3
    // sequence point: <hidden>
    IL_0060:  ldloca.s   V_3
    IL_0062:  call       ""bool System.Runtime.CompilerServices.ValueTaskAwaiter.IsCompleted.get""
    IL_0067:  brtrue.s   IL_00ad
    IL_0069:  ldarg.0
    IL_006a:  ldc.i4.0
    IL_006b:  dup
    IL_006c:  stloc.0
    IL_006d:  stfld      ""int C.<Main>d__0.<>1__state""
    // async: yield
    IL_0072:  ldarg.0
    IL_0073:  ldloc.3
    IL_0074:  stfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_0079:  ldarg.0
    IL_007a:  stloc.s    V_5
    IL_007c:  ldarg.0
    IL_007d:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> C.<Main>d__0.<>t__builder""
    IL_0082:  ldloca.s   V_3
    IL_0084:  ldloca.s   V_5
    IL_0086:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.AwaitUnsafeOnCompleted<System.Runtime.CompilerServices.ValueTaskAwaiter, C.<Main>d__0>(ref System.Runtime.CompilerServices.ValueTaskAwaiter, ref C.<Main>d__0)""
    IL_008b:  nop
    IL_008c:  leave      IL_012e
    // async: resume
    IL_0091:  ldarg.0
    IL_0092:  ldfld      ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_0097:  stloc.3
    IL_0098:  ldarg.0
    IL_0099:  ldflda     ""System.Runtime.CompilerServices.ValueTaskAwaiter C.<Main>d__0.<>u__1""
    IL_009e:  initobj    ""System.Runtime.CompilerServices.ValueTaskAwaiter""
    IL_00a4:  ldarg.0
    IL_00a5:  ldc.i4.m1
    IL_00a6:  dup
    IL_00a7:  stloc.0
    IL_00a8:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_00ad:  ldloca.s   V_3
    IL_00af:  call       ""void System.Runtime.CompilerServices.ValueTaskAwaiter.GetResult()""
    IL_00b4:  nop
    // sequence point: <hidden>
    IL_00b5:  ldarg.0
    IL_00b6:  ldfld      ""object C.<Main>d__0.<>s__2""
    IL_00bb:  stloc.2
    IL_00bc:  ldloc.2
    IL_00bd:  brfalse.s  IL_00da
    IL_00bf:  ldloc.2
    IL_00c0:  isinst     ""System.Exception""
    IL_00c5:  stloc.s    V_6
    IL_00c7:  ldloc.s    V_6
    IL_00c9:  brtrue.s   IL_00cd
    IL_00cb:  ldloc.2
    IL_00cc:  throw
    IL_00cd:  ldloc.s    V_6
    IL_00cf:  call       ""System.Runtime.ExceptionServices.ExceptionDispatchInfo System.Runtime.ExceptionServices.ExceptionDispatchInfo.Capture(System.Exception)""
    IL_00d4:  callvirt   ""void System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()""
    IL_00d9:  nop
    IL_00da:  ldarg.0
    IL_00db:  ldfld      ""int C.<Main>d__0.<>s__3""
    IL_00e0:  pop
    IL_00e1:  ldarg.0
    IL_00e2:  ldnull
    IL_00e3:  stfld      ""object C.<Main>d__0.<>s__2""
    // sequence point: }
    IL_00e8:  nop
    IL_00e9:  ldarg.0
    IL_00ea:  ldnull
    IL_00eb:  stfld      ""C C.<Main>d__0.<x>5__1""
    // sequence point: System.Console.Write(""return"");
    IL_00f0:  ldstr      ""return""
    IL_00f5:  call       ""void System.Console.Write(string)""
    IL_00fa:  nop
    // sequence point: return 1;
    IL_00fb:  ldc.i4.1
    IL_00fc:  stloc.1
    IL_00fd:  leave.s    IL_0119
  }
  catch System.Exception
  {
    // async: catch handler, sequence point: <hidden>
    IL_00ff:  stloc.s    V_6
    IL_0101:  ldarg.0
    IL_0102:  ldc.i4.s   -2
    IL_0104:  stfld      ""int C.<Main>d__0.<>1__state""
    IL_0109:  ldarg.0
    IL_010a:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> C.<Main>d__0.<>t__builder""
    IL_010f:  ldloc.s    V_6
    IL_0111:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetException(System.Exception)""
    IL_0116:  nop
    IL_0117:  leave.s    IL_012e
  }
  // sequence point: }
  IL_0119:  ldarg.0
  IL_011a:  ldc.i4.s   -2
  IL_011c:  stfld      ""int C.<Main>d__0.<>1__state""
  // sequence point: <hidden>
  IL_0121:  ldarg.0
  IL_0122:  ldflda     ""System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int> C.<Main>d__0.<>t__builder""
  IL_0127:  ldloc.1
  IL_0128:  call       ""void System.Runtime.CompilerServices.AsyncTaskMethodBuilder<int>.SetResult(int)""
  IL_012d:  nop
  IL_012e:  ret
}
", sequencePoints: "C+<Main>d__0.MoveNext", source: source);
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_Awaitable()
        {
            string source = @"
public struct C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        {
            await using var x = new C();
            System.Console.Write(""using "");
        }
        System.Console.Write(""return"");
        return 1;
    }
    public Awaitable DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        System.Console.Write($""dispose_end "");
        return new Awaitable();
    }
}
 
public class Awaitable
{
    public Awaiter GetAwaiter() { return new Awaiter(); }
}
public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
{
    public bool IsCompleted { get { return true; } }
    public bool GetResult() { return true; }
    public void OnCompleted(System.Action continuation) { }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_ReturnsTask()
        {
            string source = @"
public struct C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        {
            await using var x = new C();
            System.Console.Write(""using "");
        }
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.Task DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        [WorkItem(32316, "https://github.com/dotnet/roslyn/issues/32316")]
        public void TestPatternBasedDisposal_ReturnsTaskOfInt()
        {
            string source = @"
public struct C
{
    public static async System.Threading.Tasks.Task<int> Main()
    {
        {
            await using var x = new C();
            System.Console.Write(""using "");
        }
        System.Console.Write(""return"");
        return 1;
    }
    public async System.Threading.Tasks.Task<int> DisposeAsync()
    {
        System.Console.Write($""dispose_start "");
        await System.Threading.Tasks.Task.Yield();
        System.Console.Write($""dispose_end "");
        return 1;
    }
}
";
            // it's okay to await `Task<int>` even if we don't care about the result
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "using dispose_start dispose_end return");
        }
 
        [Fact]
        public void TestInRegularMethod()
        {
            string source = @"
class C
{
    void M()
    {
        await using var x = new object();
        await using (var y = new object()) { }
    }
}";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.VerifyDiagnostics(
                // (6,9): error CS8410: 'object': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using var x = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "await using var x = new object();").WithArguments("object").WithLocation(6, 9),
                // (6,9): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
                //         await using var x = new object();
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await").WithLocation(6, 9),
                // (7,9): error CS4033: The 'await' operator can only be used within an async method. Consider marking this method with the 'async' modifier and changing its return type to 'Task'.
                //         await using (var y = new object()) { }
                Diagnostic(ErrorCode.ERR_BadAwaitWithoutVoidAsyncMethod, "await").WithLocation(7, 9),
                // (7,22): error CS8410: 'object': type used in an async using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                //         await using (var y = new object()) { }
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "var y = new object()").WithArguments("object").WithLocation(7, 22)
                );
        }
 
        [Fact]
        [WorkItem(30956, "https://github.com/dotnet/roslyn/issues/30956")]
        public void GetAwaiterBoxingConversion()
        {
            var source =
@"using System;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
 
struct StructAwaitable { }
 
class Disposable
{
    public StructAwaitable DisposeAsync() => new StructAwaitable();
}
 
static class Extensions
{
    public static TaskAwaiter GetAwaiter(this object x)
    {
        if (x == null) throw new ArgumentNullException(nameof(x));
        Console.Write(x);
        return Task.CompletedTask.GetAwaiter();
    }
}
 
class Program
{
    static async Task Main()
    {
        await using (new Disposable())
        {
        }
    }
}";
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.ReleaseExe);
            CompileAndVerify(comp, expectedOutput: "StructAwaitable");
        }
 
        [Fact, WorkItem(45111, "https://github.com/dotnet/roslyn/issues/45111")]
        public void MissingIAsyncDisposableInterfaceInPatternDisposal()
        {
            var source = @"
using System.Threading.Tasks;
 
await using (new C()) { }
 
class C
{
    public Task DisposeAsync()
    {
        System.Console.Write(""DISPOSED"");
        return Task.CompletedTask;
    }
}
";
            var comp = CreateCompilationWithTasksExtensions(source);
            Assert.Equal(TypeKind.Error, comp.GetWellKnownType(WellKnownType.System_IAsyncDisposable).TypeKind);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "DISPOSED");
        }
 
        [Fact, WorkItem(45111, "https://github.com/dotnet/roslyn/issues/45111")]
        public void MissingIDisposableInterfaceOnClass()
        {
            var source = @"
using (new C()) { }
 
class C
{
    public void Dispose()
    {
    }
}
";
            var comp = CreateCompilation(source);
            comp.MakeTypeMissing(SpecialType.System_IDisposable);
            comp.VerifyDiagnostics(
                // source(2,8): error CS1674: 'C': type used in a using statement must implement 'System.IDisposable'.
                // using (new C()) { }
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "new C()").WithArguments("C").WithLocation(2, 8)
                );
        }
 
        [Fact, WorkItem(45111, "https://github.com/dotnet/roslyn/issues/45111")]
        public void MissingIDisposableInterfaceOnRefStruct()
        {
            var source = @"
using (new C()) { }
 
ref struct C
{
    public void Dispose()
    {
        System.Console.Write(""DISPOSED"");
    }
}
";
            var comp = CreateCompilation(source);
            comp.MakeTypeMissing(SpecialType.System_IDisposable);
            comp.VerifyDiagnostics();
            CompileAndVerify(comp, expectedOutput: "DISPOSED");
        }
 
        [Fact]
        public void RefStruct_AwaitInside()
        {
            var source = """
                using System.Threading.Tasks;
                class C
                {
                    async Task M()
                    {
                        using (new R())
                        {
                            await Task.Yield();
                        }
                    }
                }
                ref struct R
                {
                    public void Dispose() { }
                }
                """;
            // https://github.com/dotnet/roslyn/issues/73280 - should not be a langversion error since this remains an error in C# 13
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (6,16): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         using (new R())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "new R()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(6, 16));
 
            var expectedDiagnostics = new[]
            {
                // (6,16): error CS4007: Instance of type 'R' cannot be preserved across 'await' or 'yield' boundary.
                //         using (new R())
                Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new R()").WithArguments("R").WithLocation(6, 16)
            };
 
            CreateCompilation(source, parseOptions: TestOptions.Regular13).VerifyEmitDiagnostics(expectedDiagnostics);
            CreateCompilation(source).VerifyEmitDiagnostics(expectedDiagnostics);
        }
 
        [Fact]
        public void RefStruct_YieldReturnInside()
        {
            var source = """
                using System.Collections.Generic;
                class C
                {
                    IEnumerable<int> M()
                    {
                        using (new R())
                        {
                            yield return 1;
                        }
                    }
                }
                ref struct R
                {
                    public void Dispose() { }
                }
                """;
 
            var expectedDiagnostics = new[]
            {
                // (6,16): error CS4007: Instance of type 'R' cannot be preserved across 'await' or 'yield' boundary.
                //         using (new R())
                Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new R()").WithArguments("R").WithLocation(6, 16)
            };
 
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyEmitDiagnostics(expectedDiagnostics);
            CreateCompilation(source, parseOptions: TestOptions.Regular13).VerifyEmitDiagnostics(expectedDiagnostics);
            CreateCompilation(source).VerifyEmitDiagnostics(expectedDiagnostics);
        }
 
        [Fact]
        public void RefStruct_YieldBreakInside()
        {
            var source = """
                using System;
                using System.Collections.Generic;
                class C
                {
                    static void Main()
                    {
                        foreach (var x in M(true)) { Console.Write(x); }
                        Console.Write(" ");
                        foreach (var x in M(false)) { Console.Write(x); }
                    }
                    static IEnumerable<int> M(bool b)
                    {
                        yield return 123;
                        using (new R())
                        {
                            if (b) { yield break; }
                        }
                        yield return 456;
                    }
                }
                ref struct R
                {
                    public R() => Console.Write("C");
                    public void Dispose() => Console.Write("D");
                }
                """;
 
            var expectedOutput = "123CD 123CD456";
 
            CompileAndVerify(source, expectedOutput: expectedOutput, parseOptions: TestOptions.Regular12).VerifyDiagnostics();
            CompileAndVerify(source, expectedOutput: expectedOutput, parseOptions: TestOptions.Regular13).VerifyDiagnostics();
            CompileAndVerify(source, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact]
        public void RefStruct_AwaitResource()
        {
            var source = """
                using System;
                using System.Threading.Tasks;
                class C
                {
                    static async Task Main()
                    {
                        Console.Write("1");
                        using ((await GetC()).GetR())
                        {
                            Console.Write("2");
                        }
                        Console.Write("3");
                    }
                    static async Task<C> GetC()
                    {
                        Console.Write("Ga");
                        await Task.Yield();
                        Console.Write("Gb");
                        return new C();
                    }
                    R GetR() => new R();
                }
                ref struct R
                {
                    public R() => Console.Write("C");
                    public void Dispose() => Console.Write("D");
                }
                """;
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (8,16): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         using ((await GetC()).GetR())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "(await GetC()).GetR()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(8, 16));
 
            var expectedOutput = "1GaGbC2D3";
 
            CompileAndVerify(source, expectedOutput: expectedOutput, parseOptions: TestOptions.Regular13, verify: Verification.FailsILVerify).VerifyDiagnostics();
            CompileAndVerify(source, expectedOutput: expectedOutput, verify: Verification.FailsILVerify).VerifyDiagnostics();
        }
 
        [Fact]
        public void RefStruct_AwaitOutside()
        {
            var source = """
                using System;
                using System.Threading.Tasks;
                class C
                {
                    static async Task Main()
                    {
                        Console.Write("1");
                        await Task.Yield();
                        Console.Write("2");
                        using (new R())
                        {
                            Console.Write("3");
                        }
                        Console.Write("4");
                        await Task.Yield();
                        Console.Write("5");
                    }
                }
                ref struct R
                {
                    public R() => Console.Write("C");
                    public void Dispose() => Console.Write("D");
                }
                """;
            CreateCompilation(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (10,16): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         using (new R())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "new R()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(10, 16));
 
            var expectedOutput = "12C3D45";
 
            CompileAndVerify(source, expectedOutput: expectedOutput, parseOptions: TestOptions.Regular13).VerifyDiagnostics();
            CompileAndVerify(source, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact]
        public void RefStruct_YieldReturnOutside()
        {
            var source = """
                using System;
                using System.Collections.Generic;
                class C
                {
                    static void Main()
                    {
                        foreach (var x in M())
                        {
                            Console.Write(x);
                        }
                    }
                    static IEnumerable<string> M()
                    {
                        Console.Write("1");
                        yield return "a";
                        Console.Write("2");
                        using (new R())
                        {
                            Console.Write("3");
                        }
                        Console.Write("4");
                        yield return "b";
                        Console.Write("5");
                    }
                }
                ref struct R
                {
                    public R() => Console.Write("C");
                    public void Dispose() => Console.Write("D");
                }
                """;
 
            var expectedOutput = "1a2C3D4b5";
 
            CompileAndVerify(source, expectedOutput: expectedOutput, parseOptions: TestOptions.Regular12).VerifyDiagnostics();
            CompileAndVerify(source, expectedOutput: expectedOutput, parseOptions: TestOptions.Regular13).VerifyDiagnostics();
            CompileAndVerify(source, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact]
        public void RefStruct_AwaitUsing()
        {
            var source = """
                using System;
                using System.Threading.Tasks;
                class C
                {
                    static async Task Main()
                    {
                        Console.Write("1");
                        await using (new R())
                        {
                            Console.Write("2");
                        }
                        Console.Write("3");
                    }
                }
                ref struct R
                {
                    public R() => Console.Write("C");
                    public ValueTask DisposeAsync()
                    {
                        Console.Write("D");
                        return default;
                    }
                }
                """;
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (8,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         await using (new R())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "new R()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(8, 22));
 
            var expectedOutput = "1C2D3";
 
            var comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular13, options: TestOptions.ReleaseExe);
            CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics();
 
            comp = CreateCompilationWithTasksExtensions(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact]
        public void RefStruct_AwaitUsing_AwaitInside()
        {
            var source = """
                using System.Threading.Tasks;
                class C
                {
                    async Task M()
                    {
                        await using (new R())
                        {
                            await Task.Yield();
                        }
                    }
                }
                ref struct R
                {
                    public ValueTask DisposeAsync() => default;
                }
                """;
            // https://github.com/dotnet/roslyn/issues/73280 - should not be a langversion error since this remains an error in C# 13
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (6,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         await using (new R())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "new R()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(6, 22));
 
            var expectedDiagnostics = new[]
            {
                // (6,22): error CS4007: Instance of type 'R' cannot be preserved across 'await' or 'yield' boundary.
                //         await using (new R())
                Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new R()").WithArguments("R").WithLocation(6, 22)
            };
 
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular13).VerifyEmitDiagnostics(expectedDiagnostics);
            CreateCompilationWithTasksExtensions(source).VerifyEmitDiagnostics(expectedDiagnostics);
        }
 
        [Fact]
        public void RefStruct_AwaitUsing_YieldReturnInside()
        {
            var source = """
                using System.Collections.Generic;
                using System.Threading.Tasks;
                class C
                {
                    async IAsyncEnumerable<int> M()
                    {
                        await using (new R())
                        {
                            yield return 123;
                        }
                    }
                }
                ref struct R
                {
                    public ValueTask DisposeAsync() => default;
                }
                """ + AsyncStreamsTypes;
            // https://github.com/dotnet/roslyn/issues/73280 - should not be a langversion error since this remains an error in C# 13
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (7,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         await using (new R())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "new R()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(7, 22));
 
            var expectedDiagnostics = new[]
            {
                // (7,22): error CS4007: Instance of type 'R' cannot be preserved across 'await' or 'yield' boundary.
                //         await using (new R())
                Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "new R()").WithArguments("R").WithLocation(7, 22)
            };
 
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular13).VerifyEmitDiagnostics(expectedDiagnostics);
            CreateCompilationWithTasksExtensions(source).VerifyEmitDiagnostics(expectedDiagnostics);
        }
 
        [Fact]
        public void RefStruct_AwaitUsing_YieldReturnInside_Var()
        {
            var source = """
                using System.Collections.Generic;
                using System.Threading.Tasks;
                class C
                {
                    async IAsyncEnumerable<int> M()
                    {
                        await using var _ = new R();
                        yield return 123;
                    }
                }
                ref struct R
                {
                    public ValueTask DisposeAsync() => default;
                }
                """ + AsyncStreamsTypes;
            // https://github.com/dotnet/roslyn/issues/73280 - should not be a langversion error since this remains an error in C# 13
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (7,21): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         await using var _ = new R();
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "var").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(7, 21));
 
            var expectedDiagnostics = new[]
            {
                // (7,25): error CS4007: Instance of type 'R' cannot be preserved across 'await' or 'yield' boundary.
                //         await using var _ = new R();
                Diagnostic(ErrorCode.ERR_ByRefTypeAndAwait, "_ = new R()").WithArguments("R").WithLocation(7, 25)
            };
 
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular13).VerifyEmitDiagnostics(expectedDiagnostics);
            CreateCompilationWithTasksExtensions(source).VerifyEmitDiagnostics(expectedDiagnostics);
        }
 
        [Fact]
        public void RefStruct_AwaitUsing_YieldBreakInside()
        {
            var source = """
                using System;
                using System.Collections.Generic;
                using System.Threading.Tasks;
                class C
                {
                    static async Task Main()
                    {
                        await foreach (var x in M(true)) { Console.Write(x); }
                        Console.Write(" ");
                        await foreach (var x in M(false)) { Console.Write(x); }
                    }
                    static async IAsyncEnumerable<int> M(bool b)
                    {
                        yield return 1;
                        await using (new R())
                        {
                            if (b) { yield break; }
                        }
                        yield return 2;
                    }
                }
                ref struct R
                {
                    public R() => Console.Write("C");
                    public ValueTask DisposeAsync()
                    {
                        Console.Write("D");
                        return default;
                    }
                }
                """ + AsyncStreamsTypes;
            CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular12).VerifyDiagnostics(
                // (15,22): error CS9202: Feature 'ref and unsafe in async and iterator methods' is not available in C# 12.0. Please use language version 13.0 or greater.
                //         await using (new R())
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion12, "new R()").WithArguments("ref and unsafe in async and iterator methods", "13.0").WithLocation(15, 22));
 
            var expectedOutput = "1CD 1CD2";
 
            var comp = CreateCompilationWithTasksExtensions(source, parseOptions: TestOptions.Regular13, options: TestOptions.ReleaseExe);
            CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics();
 
            comp = CreateCompilationWithTasksExtensions(source, options: TestOptions.ReleaseExe);
            CompileAndVerify(comp, expectedOutput: expectedOutput).VerifyDiagnostics();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/73691")]
        public void PatternBasedFails_WithInterfaceImplementation()
        {
            var source = """
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
 
await using var x = new Class1();
 
internal class Class1 : IAsyncDisposable
{
    async ValueTask IAsyncDisposable.DisposeAsync()
    {
        System.Console.Write("DISPOSED");
        await Task.Yield();
    }
}
 
internal static class EnumerableExtensions
{
    public static ValueTask DisposeAsync(this IEnumerable<object> objects)
    {
        throw null;
    }
}
""";
            var comp = CreateCompilationWithTasksExtensions([source, IAsyncDisposableDefinition]);
            CompileAndVerify(comp, expectedOutput: "DISPOSED").VerifyDiagnostics();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/73691")]
        public void PatternBasedFails_NoInterfaceImplementation()
        {
            var source = """
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
 
await using var x = new Class1();
 
internal class Class1 { }
 
internal static class EnumerableExtensions
{
    public static ValueTask DisposeAsync(this IEnumerable<object> objects)
    {
        throw null;
    }
}
""";
            var comp = CreateCompilationWithTasksExtensions([source, IAsyncDisposableDefinition]);
            comp.VerifyEmitDiagnostics(
                // (5,1): error CS8410: 'Class1': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                // await using var x = new Class1();
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "await using var x = new Class1();").WithArguments("Class1").WithLocation(5, 1));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/73691")]
        public void PatternBasedFails_WithInterfaceImplementation_UseSite()
        {
            // We attempt to bind pattern-based disposal (and collect diagnostics)
            // then we bind to the IAsyncDisposable interface, which reports a use-site error
            // and so we add the collected diagnostics
            var source = """
using System;
using System.Threading.Tasks;
using System.Collections.Generic;
 
internal class Class1 : IAsyncDisposable
{
    ValueTask IAsyncDisposable.DisposeAsync()
    {
        throw null;
    }
 
    public async Task MethodWithCompilerError()
    {
        await using var x = new Class1();
    }
}
 
internal static class EnumerableExtensions
{
    public static ValueTask DisposeAsync(this IEnumerable<object> objects)
    {
        throw null;
    }
}
 
namespace System.Threading.Tasks
{
    public struct ValueTask
    {
        public Awaiter GetAwaiter() => null;
        public class Awaiter : System.Runtime.CompilerServices.INotifyCompletion
        {
            public void OnCompleted(Action a) { }
            public bool IsCompleted => true;
            public void GetResult() { }
        }
    }
}
""";
 
            var ilSrc = """
.class interface public auto ansi abstract beforefieldinit System.IAsyncDisposable
{
    .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerFeatureRequiredAttribute::.ctor(string) = ( 01 00 02 68 69 00 00 )
    .method public hidebysig newslot abstract virtual instance valuetype [mscorlib]System.Threading.Tasks.ValueTask DisposeAsync () cil managed 
    {
    }
}
""";
            var comp = CreateCompilationWithIL(source, ilSrc);
            comp.VerifyEmitDiagnostics(
                // (5,16): error CS9041: 'IAsyncDisposable' requires compiler feature 'hi', which is not supported by this version of the C# compiler.
                // internal class Class1 : IAsyncDisposable
                Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "Class1").WithArguments("System.IAsyncDisposable", "hi").WithLocation(5, 16),
                // (5,25): error CS9041: 'IAsyncDisposable' requires compiler feature 'hi', which is not supported by this version of the C# compiler.
                // internal class Class1 : IAsyncDisposable
                Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "IAsyncDisposable").WithArguments("System.IAsyncDisposable", "hi").WithLocation(5, 25),
                // (7,15): error CS9041: 'IAsyncDisposable' requires compiler feature 'hi', which is not supported by this version of the C# compiler.
                //     ValueTask IAsyncDisposable.DisposeAsync()
                Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "IAsyncDisposable").WithArguments("System.IAsyncDisposable", "hi").WithLocation(7, 15),
                // (7,32): error CS0539: 'Class1.DisposeAsync()' in explicit interface declaration is not found among members of the interface that can be implemented
                //     ValueTask IAsyncDisposable.DisposeAsync()
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "DisposeAsync").WithArguments("Class1.DisposeAsync()").WithLocation(7, 32),
                // (14,9): error CS9041: 'IAsyncDisposable' requires compiler feature 'hi', which is not supported by this version of the C# compiler.
                //         await using var x = new Class1();
                Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "await using var x = new Class1();").WithArguments("System.IAsyncDisposable", "hi").WithLocation(14, 9),
                // (14,9): error CS9041: 'IAsyncDisposable' requires compiler feature 'hi', which is not supported by this version of the C# compiler.
                //         await using var x = new Class1();
                Diagnostic(ErrorCode.ERR_UnsupportedCompilerFeature, "await").WithArguments("System.IAsyncDisposable", "hi").WithLocation(14, 9));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72819")]
        public void PatternBasedFails_AwaitUsing_08()
        {
            var src = """
using System;
using System.Threading.Tasks;
 
interface IMyAsyncDisposable1
{
    ValueTask DisposeAsync();
}
 
interface IMyAsyncDisposable2
{
    ValueTask DisposeAsync();
}
 
struct S2 : IMyAsyncDisposable1, IMyAsyncDisposable2, IAsyncDisposable
{
    ValueTask IMyAsyncDisposable1.DisposeAsync() => throw null;
    ValueTask IMyAsyncDisposable2.DisposeAsync() => throw null;
 
    public ValueTask DisposeAsync()
    {
        System.Console.Write('D');
        return ValueTask.CompletedTask;
    }
}
 
class C
{
    static async Task Main()
    {
        await Test<S2>();
    }
 
    static async Task Test<T>() where T : IMyAsyncDisposable1, IMyAsyncDisposable2, IAsyncDisposable, new()
    {
        await using (new T())
        {
            System.Console.Write(123);
        }
    }
}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe);
            CompileAndVerify(comp,
                expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "123D" : null,
                verify: ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped).VerifyDiagnostics();
        }
 
        [Fact, WorkItem("https://devdiv.visualstudio.com/DevDiv/_workitems/edit/2066463")]
        public void PatternBasedFails_AwaitUsing_Private()
        {
            var src = """
using System;
using System.Threading.Tasks;
 
await using var service = new Service1();
 
public sealed class Service1 : IAsyncDisposable
{
    private Task DisposeAsync()
    {
        return Task.CompletedTask;
    }
 
    ValueTask IAsyncDisposable.DisposeAsync()
    {
        System.Console.Write("ran");
        return new ValueTask(DisposeAsync());
    }
}
""";
            var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80);
            CompileAndVerify(comp,
                expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "ran" : null,
                verify: ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped).VerifyDiagnostics();
        }
    }
}