File: CodeGen\CodeGenUsingDeclarationTests.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.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.CodeGen
{
    public class CodeGenUsingDeclarationTests : EmitMetadataTestBase
    {
        [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)]
        public void UsingVariableVarEmitTest()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Dispose() { }
}
class C2
{
    public static void Main()
    {
        using var c1 = new C1(); 
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       19 (0x13)
  .maxstack  1
  .locals init (C1 V_0) //c1
  // sequence point: using var c1 = new C1();
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    // sequence point: }
    IL_0006:  leave.s    IL_0012
  }
  finally
  {
    // sequence point: <hidden>
    IL_0008:  ldloc.0
    IL_0009:  brfalse.s  IL_0011
    IL_000b:  ldloc.0
    IL_000c:  callvirt   ""void System.IDisposable.Dispose()""
    // sequence point: <hidden>
    IL_0011:  endfinally
  }
  // sequence point: }
  IL_0012:  ret
}", sequencePoints: "C2.Main", source: source);
        }
 
        [Fact]
        public void UsingVariableEmitTest()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Method1() { }
    public void Dispose() { }
}
class C2
{
    public static void Main()
    {
        using var c1 = new C1(); 
        c1.Method1();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       25 (0x19)
  .maxstack  1
  .locals init (C1 V_0) //c1
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  ldloc.0
    IL_0007:  callvirt   ""void C1.Method1()""
    IL_000c:  leave.s    IL_0018
  }
  finally
  {
    IL_000e:  ldloc.0
    IL_000f:  brfalse.s  IL_0017
    IL_0011:  ldloc.0
    IL_0012:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0017:  endfinally
  }
  IL_0018:  ret
}");
        }
 
        [Fact]
        public void UsingVariableTypedVariable()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Method1() { }
    public void Dispose() { }
}
class C2
{
    public static void Main()
    {
        using C1 c1 = new C1(); 
        c1.Method1();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       25 (0x19)
  .maxstack  1
  .locals init (C1 V_0) //c1
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  ldloc.0
    IL_0007:  callvirt   ""void C1.Method1()""
    IL_000c:  leave.s    IL_0018
  }
  finally
  {
    IL_000e:  ldloc.0
    IL_000f:  brfalse.s  IL_0017
    IL_0011:  ldloc.0
    IL_0012:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0017:  endfinally
  }
  IL_0018:  ret
}");
        }
 
        [Fact]
        public void PreexistingVariablesUsingDeclarationEmitTest()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Dispose() { }
    public void Method1() { }
}
class C2
{
    public static void Main()
    {
        C1 c0 = new C1();
        c0.Method1();
        using var c1 = new C1();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       29 (0x1d)
  .maxstack  1
  .locals init (C1 V_0) //c1
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  callvirt   ""void C1.Method1()""
  IL_000a:  newobj     ""C1..ctor()""
  IL_000f:  stloc.0
  .try
  {
    IL_0010:  leave.s    IL_001c
  }
  finally
  {
    IL_0012:  ldloc.0
    IL_0013:  brfalse.s  IL_001b
    IL_0015:  ldloc.0
    IL_0016:  callvirt   ""void System.IDisposable.Dispose()""
    IL_001b:  endfinally
  }
  IL_001c:  ret
}");
        }
 
        [Fact]
        public void TwoUsingVarsInARow()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void M() { } 
    public void Dispose() { }
}
class C2
{
    public static void Main()                                                                                                           
    {
        using C1 o1 = new C1();
        using C1 o2 = new C1();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       35 (0x23)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1) //o2
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  newobj     ""C1..ctor()""
    IL_000b:  stloc.1
    .try
    {
      IL_000c:  leave.s    IL_0022
    }
    finally
    {
      IL_000e:  ldloc.1
      IL_000f:  brfalse.s  IL_0017
      IL_0011:  ldloc.1
      IL_0012:  callvirt   ""void System.IDisposable.Dispose()""
      IL_0017:  endfinally
    }
  }
  finally
  {
    IL_0018:  ldloc.0
    IL_0019:  brfalse.s  IL_0021
    IL_001b:  ldloc.0
    IL_001c:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0021:  endfinally
  }
  IL_0022:  ret
}");
        }
 
        [Fact]
        public void UsingVarSandwich()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void M() { } 
    public void Dispose() { }
}
class C2
{
    public static void Main()                                                                                                           
    {
        using C1 o1 = new C1();
        o1.M();
        using C1 o2 = new C1();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       41 (0x29)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1) //o2
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  ldloc.0
    IL_0007:  callvirt   ""void C1.M()""
    IL_000c:  newobj     ""C1..ctor()""
    IL_0011:  stloc.1
    .try
    {
      IL_0012:  leave.s    IL_0028
    }
    finally
    {
      IL_0014:  ldloc.1
      IL_0015:  brfalse.s  IL_001d
      IL_0017:  ldloc.1
      IL_0018:  callvirt   ""void System.IDisposable.Dispose()""
      IL_001d:  endfinally
    }
  }
  finally
  {
    IL_001e:  ldloc.0
    IL_001f:  brfalse.s  IL_0027
    IL_0021:  ldloc.0
    IL_0022:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0027:  endfinally
  }
  IL_0028:  ret
}");
        }
 
        [Fact]
        public void InsideOfUsingVarInCorrectOrder()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void M() { } 
    public void Dispose() { }
}
class C2
{
    public static void Main()                                                                                                           
    {
        using C1 o1 = new C1();
        using C1 o2 = new C1();
        o2.M();
        o1.M();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       47 (0x2f)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1) //o2
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  newobj     ""C1..ctor()""
    IL_000b:  stloc.1
    .try
    {
      IL_000c:  ldloc.1
      IL_000d:  callvirt   ""void C1.M()""
      IL_0012:  ldloc.0
      IL_0013:  callvirt   ""void C1.M()""
      IL_0018:  leave.s    IL_002e
    }
    finally
    {
      IL_001a:  ldloc.1
      IL_001b:  brfalse.s  IL_0023
      IL_001d:  ldloc.1
      IL_001e:  callvirt   ""void System.IDisposable.Dispose()""
      IL_0023:  endfinally
    }
  }
  finally
  {
    IL_0024:  ldloc.0
    IL_0025:  brfalse.s  IL_002d
    IL_0027:  ldloc.0
    IL_0028:  callvirt   ""void System.IDisposable.Dispose()""
    IL_002d:  endfinally
  }
  IL_002e:  ret
}");
        }
 
        [Fact]
        public void AsPartOfLabelStatement()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Dispose() { Console.Write(""Dispose; "");}
}
class C2
{
    public static void Main()                                                                                                           
    {
        label1:
        using C1 o1 = new C1();
        using C1 o2 = new C1();
        label2:
        using C1 o3 = new C1();
    }
}";
            CompileAndVerify(source, expectedOutput: "Dispose; Dispose; Dispose; ").VerifyIL("C2.Main", @"
{
  // Code size       51 (0x33)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1, //o2
                C1 V_2) //o3
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  newobj     ""C1..ctor()""
    IL_000b:  stloc.1
    .try
    {
      IL_000c:  newobj     ""C1..ctor()""
      IL_0011:  stloc.2
      .try
      {
        IL_0012:  leave.s    IL_0032
      }
      finally
      {
        IL_0014:  ldloc.2
        IL_0015:  brfalse.s  IL_001d
        IL_0017:  ldloc.2
        IL_0018:  callvirt   ""void System.IDisposable.Dispose()""
        IL_001d:  endfinally
      }
    }
    finally
    {
      IL_001e:  ldloc.1
      IL_001f:  brfalse.s  IL_0027
      IL_0021:  ldloc.1
      IL_0022:  callvirt   ""void System.IDisposable.Dispose()""
      IL_0027:  endfinally
    }
  }
  finally
  {
    IL_0028:  ldloc.0
    IL_0029:  brfalse.s  IL_0031
    IL_002b:  ldloc.0
    IL_002c:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0031:  endfinally
  }
  IL_0032:  ret
}
");
        }
 
        [Fact]
        public void AsPartOfMultipleLabelStatements()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Dispose() { Console.Write(""Dispose; "");}
}
class C2
{
    public static void Main()                                                                                                           
    {
        label1:
        label2:
        Console.Write(""Start; "");
        label3:
        label4:
        label5:
        label6:
        using C1 o1 = new C1();
        Console.Write(""Middle1; "");
        using C1 o2 = new C1();
        Console.Write(""Middle2; "");
        label7:
        using C1 o3 = new C1();
        Console.Write(""End; "");
    }
}";
            CompileAndVerify(source, expectedOutput: "Start; Middle1; Middle2; End; Dispose; Dispose; Dispose; ").VerifyIL("C2.Main", @"
{
  // Code size       91 (0x5b)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1, //o2
                C1 V_2) //o3
  IL_0000:  ldstr      ""Start; ""
  IL_0005:  call       ""void System.Console.Write(string)""
  IL_000a:  newobj     ""C1..ctor()""
  IL_000f:  stloc.0
  .try
  {
    IL_0010:  ldstr      ""Middle1; ""
    IL_0015:  call       ""void System.Console.Write(string)""
    IL_001a:  newobj     ""C1..ctor()""
    IL_001f:  stloc.1
    .try
    {
      IL_0020:  ldstr      ""Middle2; ""
      IL_0025:  call       ""void System.Console.Write(string)""
      IL_002a:  newobj     ""C1..ctor()""
      IL_002f:  stloc.2
      .try
      {
        IL_0030:  ldstr      ""End; ""
        IL_0035:  call       ""void System.Console.Write(string)""
        IL_003a:  leave.s    IL_005a
      }
      finally
      {
        IL_003c:  ldloc.2
        IL_003d:  brfalse.s  IL_0045
        IL_003f:  ldloc.2
        IL_0040:  callvirt   ""void System.IDisposable.Dispose()""
        IL_0045:  endfinally
      }
    }
    finally
    {
      IL_0046:  ldloc.1
      IL_0047:  brfalse.s  IL_004f
      IL_0049:  ldloc.1
      IL_004a:  callvirt   ""void System.IDisposable.Dispose()""
      IL_004f:  endfinally
    }
  }
  finally
  {
    IL_0050:  ldloc.0
    IL_0051:  brfalse.s  IL_0059
    IL_0053:  ldloc.0
    IL_0054:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0059:  endfinally
  }
  IL_005a:  ret
}
");
        }
 
        [Fact]
        public void InsideTryCatchFinallyBlocks()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public string Text { get; set; }
    public void Dispose() { Console.Write($""Dispose {Text}; "");}
}
class C2
{
    public static void Main()                                                                                                           
    {
        try
        {
            using var x = new C1() { Text = ""Try"" };
            throw new Exception();
        }
        catch
        {
            using var x = new C1(){ Text = ""Catch"" };
        }
        finally
        {
            using var x = new C1(){ Text = ""Finally"" };
        }
    }
}";
            CompileAndVerify(source, expectedOutput: "Dispose Try; Dispose Catch; Dispose Finally; ").VerifyIL("C2.Main", @"
{
  // Code size       96 (0x60)
  .maxstack  3
  .locals init (C1 V_0, //x
                C1 V_1, //x
                C1 V_2) //x
  .try
  {
    .try
    {
      IL_0000:  newobj     ""C1..ctor()""
      IL_0005:  dup
      IL_0006:  ldstr      ""Try""
      IL_000b:  callvirt   ""void C1.Text.set""
      IL_0010:  stloc.0
      .try
      {
        IL_0011:  newobj     ""System.Exception..ctor()""
        IL_0016:  throw
      }
      finally
      {
        IL_0017:  ldloc.0
        IL_0018:  brfalse.s  IL_0020
        IL_001a:  ldloc.0
        IL_001b:  callvirt   ""void System.IDisposable.Dispose()""
        IL_0020:  endfinally
      }
    }
    catch object
    {
      IL_0021:  pop
      IL_0022:  newobj     ""C1..ctor()""
      IL_0027:  dup
      IL_0028:  ldstr      ""Catch""
      IL_002d:  callvirt   ""void C1.Text.set""
      IL_0032:  stloc.1
      .try
      {
        IL_0033:  leave.s    IL_003f
      }
      finally
      {
        IL_0035:  ldloc.1
        IL_0036:  brfalse.s  IL_003e
        IL_0038:  ldloc.1
        IL_0039:  callvirt   ""void System.IDisposable.Dispose()""
        IL_003e:  endfinally
      }
      IL_003f:  leave.s    IL_005f
    }
  }
  finally
  {
    IL_0041:  newobj     ""C1..ctor()""
    IL_0046:  dup
    IL_0047:  ldstr      ""Finally""
    IL_004c:  callvirt   ""void C1.Text.set""
    IL_0051:  stloc.2
    .try
    {
      IL_0052:  leave.s    IL_005e
    }
    finally
    {
      IL_0054:  ldloc.2
      IL_0055:  brfalse.s  IL_005d
      IL_0057:  ldloc.2
      IL_0058:  callvirt   ""void System.IDisposable.Dispose()""
      IL_005d:  endfinally
    }
    IL_005e:  endfinally
  }
  IL_005f:  ret
}
");
        }
 
        [Fact]
        public void InsideTryCatchFinallyBlocksAsync()
        {
            string source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    public string Text { get; set; }
 
    public C1(string text)
    {
        Text = text;
        Console.WriteLine($""Created {Text}"");
    }
 
    public ValueTask DisposeAsync()
    {
        Console.WriteLine($""Dispose Async {Text}"");
        return new ValueTask(Task.CompletedTask);
    }
}
class C2
{
    public static async Task Main()                                                                                                           
    {
        try
        {
            await using var x = new C1(""Try"");
            throw new Exception();
        }
        catch
        {
            await using var x =  new C1(""Catch"");
        }
        finally
        {
            await using var x = new C1(""Finally"");
        }
    }
}";
            string expectedOutput = @"
Created Try
Dispose Async Try
Created Catch
Dispose Async Catch
Created Finally
Dispose Async Finally
";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe).VerifyDiagnostics();
 
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void UsingDeclarationUsingPatternIntersectionEmitTest()
        {
            var source = @"
    using System;
    ref struct S1
    {
        public void M()
        {
            Console.WriteLine(""This method has run."");
        }
        public void Dispose()
        {
            Console.WriteLine(""This object has been properly disposed."");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            using S1 s1 = new S1();
            s1.M();
        }
    }";
 
            var output = @"This method has run.
This object has been properly disposed.";
            CompileAndVerify(source, expectedOutput: output).VerifyIL("Program.Main", @"
{
  // Code size       26 (0x1a)
  .maxstack  1
  .locals init (S1 V_0) //s1
  IL_0000:  ldloca.s   V_0
  IL_0002:  initobj    ""S1""
  .try
  {
    IL_0008:  ldloca.s   V_0
    IL_000a:  call       ""void S1.M()""
    IL_000f:  leave.s    IL_0019
  }
  finally
  {
    IL_0011:  ldloca.s   V_0
    IL_0013:  call       ""void S1.Dispose()""
    IL_0018:  endfinally
  }
  IL_0019:  ret
}
");
        }
 
        [Fact]
        public void UsingVariableUsingPatternIntersectionTwoDisposeMethodsEmitTest()
        {
            var source = @"
    using System;
    class C1 : IDisposable
    {
        public void M()
        {
            Console.WriteLine(""This method has run."");
        }
        public void Dispose()
        {
            Console.WriteLine(""This object has been disposed by C1.Dispose()."");
        }
        void IDisposable.Dispose()
        {
            Console.WriteLine(""This object has been disposed by IDisposable.Dispose()."");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            using C1 o1 = new C1();
            o1.M();
        }
    }";
 
            var output = @"This method has run.
This object has been disposed by IDisposable.Dispose().";
            CompileAndVerify(source, expectedOutput: output).VerifyIL("Program.Main", @"
{
  // Code size       25 (0x19)
  .maxstack  1
  .locals init (C1 V_0) //o1
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  ldloc.0
    IL_0007:  callvirt   ""void C1.M()""
    IL_000c:  leave.s    IL_0018
  }
  finally
  {
    IL_000e:  ldloc.0
    IL_000f:  brfalse.s  IL_0017
    IL_0011:  ldloc.0
    IL_0012:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0017:  endfinally
  }
  IL_0018:  ret
}");
        }
 
        [Fact]
        public void UsingDeclarationUsingPatternExtensionMethod()
        {
            var source = @"
    using System;
    ref struct S1
    {
    }
    internal static class C2
    {
        internal static void Dispose(this S1 s1)
        {
            Console.Write(""Disposed; "");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            using S1 s1 = new S1();
        }
    }";
 
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (17,13): error CS1674: 'S1': type used in a using statement must implement 'System.IDisposable'.
                //             using S1 s1 = new S1();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using S1 s1 = new S1();").WithArguments("S1").WithLocation(17, 13)
                );
        }
 
        [Fact]
        public void MultipleUsingVarEmitTest()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    public void Dispose() { }
}
class C2
{
    public static void Main()                                                                                                           
    {
        using C1 o1 = new C1(), o2 = new C1();
    }
}";
            CompileAndVerify(source).VerifyIL("C2.Main", @"
{
  // Code size       35 (0x23)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1) //o2
  IL_0000:  newobj     ""C1..ctor()""
  IL_0005:  stloc.0
  .try
  {
    IL_0006:  newobj     ""C1..ctor()""
    IL_000b:  stloc.1
    .try
    {
      IL_000c:  leave.s    IL_0022
    }
    finally
    {
      IL_000e:  ldloc.1
      IL_000f:  brfalse.s  IL_0017
      IL_0011:  ldloc.1
      IL_0012:  callvirt   ""void System.IDisposable.Dispose()""
      IL_0017:  endfinally
    }
  }
  finally
  {
    IL_0018:  ldloc.0
    IL_0019:  brfalse.s  IL_0021
    IL_001b:  ldloc.0
    IL_001c:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0021:  endfinally
  }
  IL_0022:  ret
}");
        }
 
        [Fact]
        public void MultipleUsingVarPrecedingCodeEmitTest()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    private string name;
    public C1(string name)
    {
        this.name = name;
        Console.WriteLine(""Object "" + name + "" has been created."");
    }
    public void M() { } 
    public void Dispose()
    {
        Console.WriteLine(""Object "" + name + "" has been disposed."");
    }
}
class C2
{
    public static void Main()                                                                                                           
    {
        C1 o0 = new C1(""first"");
        o0.M();
        using C1 o1 = new C1(""second""), o2 = new C1(""third"");
    }
}";
            var output = @"Object first has been created.
Object second has been created.
Object third has been created.
Object third has been disposed.
Object second has been disposed.";
            CompileAndVerify(source, expectedOutput: output).VerifyIL("C2.Main", @"
{
  // Code size       60 (0x3c)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1) //o2
  IL_0000:  ldstr      ""first""
  IL_0005:  newobj     ""C1..ctor(string)""
  IL_000a:  callvirt   ""void C1.M()""
  IL_000f:  ldstr      ""second""
  IL_0014:  newobj     ""C1..ctor(string)""
  IL_0019:  stloc.0
  .try
  {
    IL_001a:  ldstr      ""third""
    IL_001f:  newobj     ""C1..ctor(string)""
    IL_0024:  stloc.1
    .try
    {
      IL_0025:  leave.s    IL_003b
    }
    finally
    {
      IL_0027:  ldloc.1
      IL_0028:  brfalse.s  IL_0030
      IL_002a:  ldloc.1
      IL_002b:  callvirt   ""void System.IDisposable.Dispose()""
      IL_0030:  endfinally
    }
  }
  finally
  {
    IL_0031:  ldloc.0
    IL_0032:  brfalse.s  IL_003a
    IL_0034:  ldloc.0
    IL_0035:  callvirt   ""void System.IDisposable.Dispose()""
    IL_003a:  endfinally
  }
  IL_003b:  ret
}");
        }
 
        [Fact]
        public void MultipleUsingVarFollowingCodeEmitTest()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    private string name;
    public C1(string name)
    {
        this.name = name;
        Console.WriteLine(""Object "" + name + "" has been created."");
    }
    public void M() { } 
    public void Dispose()
    {
        Console.WriteLine(""Object "" + name + "" has been disposed."");
    }
}
class C2
{
    public static void Main()                                                                                                           
    {
        using C1 o1 = new C1(""first""), o2 = new C1(""second"");
        C1 o0 = new C1(""third"");
        o0.M();
    }
}";
            var output = @"Object first has been created.
Object second has been created.
Object third has been created.
Object second has been disposed.
Object first has been disposed.";
            CompileAndVerify(source, expectedOutput: output).VerifyIL("C2.Main", @"
{
  // Code size       60 (0x3c)
  .maxstack  1
  .locals init (C1 V_0, //o1
                C1 V_1) //o2
  IL_0000:  ldstr      ""first""
  IL_0005:  newobj     ""C1..ctor(string)""
  IL_000a:  stloc.0
  .try
  {
    IL_000b:  ldstr      ""second""
    IL_0010:  newobj     ""C1..ctor(string)""
    IL_0015:  stloc.1
    .try
    {
      IL_0016:  ldstr      ""third""
      IL_001b:  newobj     ""C1..ctor(string)""
      IL_0020:  callvirt   ""void C1.M()""
      IL_0025:  leave.s    IL_003b
    }
    finally
    {
      IL_0027:  ldloc.1
      IL_0028:  brfalse.s  IL_0030
      IL_002a:  ldloc.1
      IL_002b:  callvirt   ""void System.IDisposable.Dispose()""
      IL_0030:  endfinally
    }
  }
  finally
  {
    IL_0031:  ldloc.0
    IL_0032:  brfalse.s  IL_003a
    IL_0034:  ldloc.0
    IL_0035:  callvirt   ""void System.IDisposable.Dispose()""
    IL_003a:  endfinally
  }
  IL_003b:  ret
}");
        }
 
        [Fact]
        public void JumpBackOverUsingDeclaration()
        {
            string source = @"
using System;
class C1 : IDisposable
{
    private string name;
    public C1(string name)
    {
        this.name = name;
    }
    public void Dispose()
    {
        Console.WriteLine(""Disposed "" + name);
    }
}
class C2
{
    public static void Main()                                                                                                           
    {
        int x = 0;
        label1:
        {
            using C1 o1 = new C1(""first"");
            if(x++ < 3)
            {
                goto label1;
            }
        }
    }
}";
            var output = @"Disposed first
Disposed first
Disposed first
Disposed first";
            CompileAndVerify(source, expectedOutput: output).VerifyIL("C2.Main", @"
{
  // Code size       36 (0x24)
  .maxstack  3
  .locals init (int V_0, //x
                C1 V_1) //o1
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldstr      ""first""
  IL_0007:  newobj     ""C1..ctor(string)""
  IL_000c:  stloc.1
  .try
  {
    IL_000d:  ldloc.0
    IL_000e:  dup
    IL_000f:  ldc.i4.1
    IL_0010:  add
    IL_0011:  stloc.0
    IL_0012:  ldc.i4.3
    IL_0013:  bge.s      IL_0017
    IL_0015:  leave.s    IL_0002
    IL_0017:  leave.s    IL_0023
  }
  finally
  {
    IL_0019:  ldloc.1
    IL_001a:  brfalse.s  IL_0022
    IL_001c:  ldloc.1
    IL_001d:  callvirt   ""void System.IDisposable.Dispose()""
    IL_0022:  endfinally
  }
  IL_0023:  ret
}
");
        }
 
        [Fact]
        public void UsingVariableFromAwaitExpressionDisposesOnlyIfAwaitSucceeds()
        {
            var source = @"
using System;
using System.Threading.Tasks;
 
class C2 : IDisposable
{
    public void Dispose()
    {
        Console.Write($""Dispose; "");
    }
}
 
class C
{
    static Task<IDisposable> GetDisposable()
    {
        return Task.FromResult<IDisposable>(new C2());
    }
 
    static Task<IDisposable> GetDisposableError()
    {
        throw null;
    }
 
    static async Task Main()
    {
        try
        {
            using IDisposable x = await GetDisposable(); // disposed
            using IDisposable y = await GetDisposableError(); // not disposed as never assigned
        }
        catch { } 
    }
}
";
            CompileAndVerify(source, expectedOutput: "Dispose; ");
        }
 
        [Fact]
        public void UsingDeclarationAsync()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    public ValueTask DisposeAsync() 
    { 
        Console.WriteLine(""Dispose async"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c = new C1();
    }
}";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe).VerifyDiagnostics();
 
            CompileAndVerify(compilation, expectedOutput: "Dispose async");
        }
 
        [Fact]
        public void UsingDeclarationAsyncExplicit()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    ValueTask IAsyncDisposable.DisposeAsync() 
    { 
        Console.WriteLine(""Dispose async"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c = new C1();
    }
}";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe).VerifyDiagnostics();
 
            CompileAndVerify(compilation, expectedOutput: "Dispose async");
        }
 
        [Fact]
        public void UsingDeclarationAsyncWithMultipleDeclarations()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    string text;
 
    public C1(string text)
    {
        this.text = text;
        Console.WriteLine($""Created {text}"");
    }
 
    public ValueTask DisposeAsync() 
    { 
        Console.WriteLine($""Dispose async {text}"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c = new C1(""first""), c2 = new C1(""second""), c3 = new C1(""third"");
        Console.WriteLine(""After declarations"");
    }
}";
            string expectedOutput = @"
Created first
Created second
Created third
After declarations
Dispose async third
Dispose async second
Dispose async first
";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe).VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void UsingDeclarationAsyncWithMultipleInARow()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    string text;
 
    public C1(string text)
    {
        this.text = text;
        Console.WriteLine($""Created {text}"");
    }
 
    public ValueTask DisposeAsync() 
    { 
        Console.WriteLine($""Dispose async {text}"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c1 = new C1(""first"");
        await using C1 c2 = new C1(""second"");
        await using C1 c3 = new C1(""third"");
        Console.WriteLine(""After declarations"");
    }
}";
            string expectedOutput = @"
Created first
Created second
Created third
After declarations
Dispose async third
Dispose async second
Dispose async first
";
 
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe).VerifyDiagnostics();
            CompileAndVerify(compilation, expectedOutput: expectedOutput);
        }
 
        [Fact]
        public void UsingDeclarationWithNull()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IDisposable
{
    public void Dispose() 
    {
        Console.Write(""Dispose; "");
    }
}
 
 class C2 : IAsyncDisposable
{
    public ValueTask DisposeAsync() 
    { 
        System.Console.WriteLine(""Dispose async"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C3
{
    static async Task Main()
    {
        using C1 c1 = null; 
        await using C2 c2 = null;
        Console.Write(""After declarations; "");
    }
}";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe).VerifyDiagnostics();
 
            CompileAndVerify(compilation, expectedOutput: "After declarations; ");
        }
 
        [Fact]
        public void UsingDeclarationAsyncMissingValueTask_01()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    ValueTask IAsyncDisposable.DisposeAsync() 
    { 
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c1 = new C1();
    }
}";
 
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_ValueTask);
            comp.VerifyDiagnostics(
                // (16,9): error CS0518: Predefined type 'System.Threading.Tasks.ValueTask' is not defined or imported
                //         await using C1 c1 = new C1();
                Diagnostic(ErrorCode.ERR_PredefinedTypeNotFound, "await").WithArguments("System.Threading.Tasks.ValueTask").WithLocation(16, 9)
                );
        }
 
        [Fact]
        public void UsingDeclarationAsyncMissingValueTask_02()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1 : IAsyncDisposable
{
    public ValueTask DisposeAsync() 
    { 
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c1 = new C1();
    }
}";
 
            var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition });
            comp.MakeTypeMissing(WellKnownType.System_Threading_Tasks_ValueTask);
            comp.VerifyEmitDiagnostics();
        }
 
        [Fact]
        public void UsingDeclarationAsync_WithOptionalParameter()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1
{
    public ValueTask DisposeAsync(int i = 1) 
    { 
        Console.WriteLine($""Dispose async {i}"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c = new C1();
    }
}";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
 
            CompileAndVerify(compilation, expectedOutput: "Dispose async 1");
        }
 
        [Fact]
        public void UsingDeclarationAsync_WithParamsParameter()
        {
            var source = @"
using System;
using System.Threading.Tasks;
class C1
{
    public ValueTask DisposeAsync(params object[] o) 
    { 
        Console.WriteLine($""Dispose async {o.Length}"");
        return new ValueTask(Task.CompletedTask);
    }
}
 
class C2
{
    static async Task Main()
    {
        await using C1 c = new C1();
    }
}";
            var compilation = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }, options: TestOptions.DebugExe);
 
            CompileAndVerify(compilation, expectedOutput: "Dispose async 0");
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Const()
        {
            var source = """
class C
{
    void M()
    {
        using const var obj = new object();
    }
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,9): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                //         using const var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using const var obj = new object();").WithArguments("object").WithLocation(5, 9),
                // (5,15): error CS9229: Modifiers cannot be placed on using declarations
                //         using const var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "const").WithLocation(5, 15));
 
            source = """
using const var obj = new object();
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,1): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                // using const var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using const var obj = new object();").WithArguments("object").WithLocation(1, 1),
                // (1,7): error CS9229: Modifiers cannot be placed on using declarations
                // using const var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "const").WithLocation(1, 7));
 
            source = """
using (const var obj2 = new object()) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,8): error CS1525: Invalid expression term 'const'
                // using (const var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "const").WithArguments("const").WithLocation(1, 8),
                // (1,8): error CS1026: ) expected
                // using (const var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "const").WithLocation(1, 8),
                // (1,8): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // using (const var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const var obj2 = new object()) ").WithLocation(1, 8),
                // (1,14): error CS0822: Implicitly-typed variables cannot be constant
                // using (const var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableCannotBeConst, "var obj2 = new object()").WithLocation(1, 14),
                // (1,37): error CS1003: Syntax error, ',' expected
                // using (const var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 37),
                // (1,39): error CS1002: ; expected
                // using (const var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 39));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Const_Async()
        {
            var source = """
await using const var obj = new object();
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,1): warning CS0028: '<top-level-statements-entry-point>' has the wrong signature to be an entry point
                // await using const var obj = new object();
                Diagnostic(ErrorCode.WRN_InvalidMainSig, "await using const var obj = new object();").WithArguments("<top-level-statements-entry-point>").WithLocation(1, 1),
                // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
                Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1),
                // (1,1): error CS8410: 'object': type used in an asynchronous using statement must implement 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method.
                // await using const var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "await using const var obj = new object();").WithArguments("object").WithLocation(1, 1),
                // (1,13): error CS9229: Modifiers cannot be placed on using declarations
                // await using const var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "const").WithLocation(1, 13));
 
            source = """
await using (const var obj = new object()) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,1): warning CS0028: '<top-level-statements-entry-point>' has the wrong signature to be an entry point
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.WRN_InvalidMainSig, "await using (const var obj = new object()) { }").WithArguments("<top-level-statements-entry-point>").WithLocation(1, 1),
                // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
                Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1),
                // (1,14): error CS1525: Invalid expression term 'const'
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "const").WithArguments("const").WithLocation(1, 14),
                // (1,14): error CS1026: ) expected
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "const").WithLocation(1, 14),
                // (1,14): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const var obj = new object()) ").WithLocation(1, 14),
                // (1,20): error CS0822: Implicitly-typed variables cannot be constant
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableCannotBeConst, "var obj = new object()").WithLocation(1, 20),
                // (1,42): error CS1003: Syntax error, ',' expected
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 42),
                // (1,44): error CS1002: ; expected
                // await using (const var obj = new object()) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 44));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Const_ExplicitType()
        {
            var source = """
class C
{
    void M()
    {
        using const System.IDisposable obj = null;
    }
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,15): error CS9229: Modifiers cannot be placed on using declarations
                //         using const System.IDisposable obj = null;
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "const").WithLocation(5, 15),
                // (5,40): warning CS0219: The variable 'obj' is assigned but its value is never used
                //         using const System.IDisposable obj = null;
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "obj").WithArguments("obj").WithLocation(5, 40));
 
            source = """
using const System.IDisposable obj = null;
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,7): error CS9229: Modifiers cannot be placed on using declarations
                // using const System.IDisposable obj = null;
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "const").WithLocation(1, 7),
                // (1,32): warning CS0219: The variable 'obj' is assigned but its value is never used
                // using const System.IDisposable obj = null;
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "obj").WithArguments("obj").WithLocation(1, 32));
 
            source = """
using (const System.IDisposable obj) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,8): error CS1525: Invalid expression term 'const'
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "const").WithArguments("const").WithLocation(1, 8),
                // (1,8): error CS1026: ) expected
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "const").WithLocation(1, 8),
                // (1,8): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const System.IDisposable obj) ").WithLocation(1, 8),
                // (1,33): error CS0145: A const field requires a value to be provided
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.ERR_ConstValueRequired, "obj").WithLocation(1, 33),
                // (1,33): warning CS0168: The variable 'obj' is declared but never used
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.WRN_UnreferencedVar, "obj").WithArguments("obj").WithLocation(1, 33),
                // (1,36): error CS1003: Syntax error, ',' expected
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 36),
                // (1,38): error CS1002: ; expected
                // using (const System.IDisposable obj) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 38));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Const_Async_ExplicitType()
        {
            var source = """
await using const System.IAsyncDisposable obj = null;
""";
            var comp = CreateCompilation(source, targetFramework: TargetFramework.Net70);
            comp.VerifyEmitDiagnostics(
                // (1,1): warning CS0028: '<top-level-statements-entry-point>' has the wrong signature to be an entry point
                // await using const System.IAsyncDisposable obj = null;
                Diagnostic(ErrorCode.WRN_InvalidMainSig, "await using const System.IAsyncDisposable obj = null;").WithArguments("<top-level-statements-entry-point>").WithLocation(1, 1),
                // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
                Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1),
                // (1,13): error CS9229: Modifiers cannot be placed on using declarations
                // await using const System.IAsyncDisposable obj = null;
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "const").WithLocation(1, 13),
                // (1,43): warning CS0219: The variable 'obj' is assigned but its value is never used
                // await using const System.IAsyncDisposable obj = null;
                Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "obj").WithArguments("obj").WithLocation(1, 43));
 
            source = """
await using (const System.IAsyncDisposable obj) { }
""";
            comp = CreateCompilation(source, targetFramework: TargetFramework.Net70);
            comp.VerifyEmitDiagnostics(
                // (1,1): warning CS0028: '<top-level-statements-entry-point>' has the wrong signature to be an entry point
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.WRN_InvalidMainSig, "await using (const System.IAsyncDisposable obj) { }").WithArguments("<top-level-statements-entry-point>").WithLocation(1, 1),
                // error CS5001: Program does not contain a static 'Main' method suitable for an entry point
                Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1),
                // (1,14): error CS1525: Invalid expression term 'const'
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "const").WithArguments("const").WithLocation(1, 14),
                // (1,14): error CS1026: ) expected
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "const").WithLocation(1, 14),
                // (1,14): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "const System.IAsyncDisposable obj) ").WithLocation(1, 14),
                // (1,44): error CS0145: A const field requires a value to be provided
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.ERR_ConstValueRequired, "obj").WithLocation(1, 44),
                // (1,44): warning CS0168: The variable 'obj' is declared but never used
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.WRN_UnreferencedVar, "obj").WithArguments("obj").WithLocation(1, 44),
                // (1,47): error CS1003: Syntax error, ',' expected
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 47),
                // (1,49): error CS1002: ; expected
                // await using (const System.IAsyncDisposable obj) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 49));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Readonly()
        {
            var source = """
class C
{
    void M()
    {
        using readonly var obj = new object();
    }
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,9): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                //         using readonly var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using readonly var obj = new object();").WithArguments("object").WithLocation(5, 9),
                // (5,15): error CS9229: Modifiers cannot be placed on using declarations
                //         using readonly var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "readonly").WithLocation(5, 15));
 
            source = """
using readonly var obj = new object();
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,1): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                // using readonly var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using readonly var obj = new object();").WithArguments("object").WithLocation(1, 1),
                // (1,7): error CS9229: Modifiers cannot be placed on using declarations
                // using readonly var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "readonly").WithLocation(1, 7));
 
            source = """
using (readonly var obj2 = new object()) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,8): error CS1525: Invalid expression term 'readonly'
                // using (readonly var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "readonly").WithArguments("readonly").WithLocation(1, 8),
                // (1,8): error CS1026: ) expected
                // using (readonly var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "readonly").WithLocation(1, 8),
                // (1,8): error CS0106: The modifier 'readonly' is not valid for this item
                // using (readonly var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "readonly").WithArguments("readonly").WithLocation(1, 8),
                // (1,8): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // using (readonly var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "readonly var obj2 = new object()) ").WithLocation(1, 8),
                // (1,40): error CS1003: Syntax error, ',' expected
                // using (readonly var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 40),
                // (1,42): error CS1002: ; expected
                // using (readonly var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 42));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Static()
        {
            var source = """
class C
{
    void M()
    {
        using static var obj = new object();
    }
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,9): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                //         using static var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using static var obj = new object();").WithArguments("object").WithLocation(5, 9),
                // (5,15): error CS9229: Modifiers cannot be placed on using declarations
                //         using static var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "static").WithLocation(5, 15));
 
            source = """
using static var obj = new object();
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,1): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                // using static var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using static var obj = new object();").WithArguments("object").WithLocation(1, 1),
                // (1,7): error CS9229: Modifiers cannot be placed on using declarations
                // using static var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "static").WithLocation(1, 7));
 
            source = """
using (static var obj2 = new object()) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,8): error CS1525: Invalid expression term 'static'
                // using (static var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "static").WithArguments("static").WithLocation(1, 8),
                // (1,8): error CS1026: ) expected
                // using (static var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "static").WithLocation(1, 8),
                // (1,8): error CS0106: The modifier 'static' is not valid for this item
                // using (static var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "static").WithArguments("static").WithLocation(1, 8),
                // (1,8): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // using (static var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "static var obj2 = new object()) ").WithLocation(1, 8),
                // (1,38): error CS1003: Syntax error, ',' expected
                // using (static var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 38),
                // (1,40): error CS1002: ; expected
                // using (static var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 40));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Volatile()
        {
            var source = """
class C
{
    void M()
    {
        using volatile var obj = new object();
    }
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (5,9): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                //         using volatile var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using volatile var obj = new object();").WithArguments("object").WithLocation(5, 9),
                // (5,15): error CS9229: Modifiers cannot be placed on using declarations
                //         using volatile var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "volatile").WithLocation(5, 15));
 
            source = """
using volatile var obj = new object();
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,1): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                // using volatile var obj = new object();
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using volatile var obj = new object();").WithArguments("object").WithLocation(1, 1),
                // (1,7): error CS9229: Modifiers cannot be placed on using declarations
                // using volatile var obj = new object();
                Diagnostic(ErrorCode.ERR_NoModifiersOnUsing, "volatile").WithLocation(1, 7));
 
            source = """
using (volatile var obj2 = new object()) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (1,8): error CS1525: Invalid expression term 'volatile'
                // using (volatile var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_InvalidExprTerm, "volatile").WithArguments("volatile").WithLocation(1, 8),
                // (1,8): error CS1026: ) expected
                // using (volatile var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_CloseParenExpected, "volatile").WithLocation(1, 8),
                // (1,8): error CS0106: The modifier 'volatile' is not valid for this item
                // using (volatile var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "volatile").WithArguments("volatile").WithLocation(1, 8),
                // (1,8): error CS1023: Embedded statement cannot be a declaration or labeled statement
                // using (volatile var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_BadEmbeddedStmt, "volatile var obj2 = new object()) ").WithLocation(1, 8),
                // (1,40): error CS1003: Syntax error, ',' expected
                // using (volatile var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SyntaxError, ")").WithArguments(",").WithLocation(1, 40),
                // (1,42): error CS1002: ; expected
                // using (volatile var obj2 = new object()) { }
                Diagnostic(ErrorCode.ERR_SemicolonExpected, "{").WithLocation(1, 42));
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Scoped()
        {
            var source = """
class C
{
    void M()
    {
        using scoped var obj = new S();
    }
}
ref struct S { public void Dispose() { } }
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            source = """
using scoped var obj = new S();
ref struct S { public void Dispose() { } }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
 
            source = """
using (scoped var obj = new S()) { }
ref struct S { public void Dispose() { } }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics();
        }
 
        [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72496")]
        public void ModifiersInUsingLocalDeclarations_Ref()
        {
            var source = """
class C
{
    void M()
    {
        var x = new object();
        using ref object y = ref x;
    }
}
""";
            var comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (6,9): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                //         using ref object y = ref x;
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using ref object y = ref x;").WithArguments("object").WithLocation(6, 9),
                // (6,15): error CS1073: Unexpected token 'ref'
                //         using ref object y = ref x;
                Diagnostic(ErrorCode.ERR_UnexpectedToken, "ref").WithArguments("ref").WithLocation(6, 15));
 
            source = """
var x = new object();
using ref object y = ref x;
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (2,1): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                // using ref object y = ref x;
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using ref object y = ref x;").WithArguments("object").WithLocation(2, 1),
                // (2,7): error CS1073: Unexpected token 'ref'
                // using ref object y = ref x;
                Diagnostic(ErrorCode.ERR_UnexpectedToken, "ref").WithArguments("ref").WithLocation(2, 7));
 
            source = """
var x = new object();
using (ref object y = ref x) { }
""";
            comp = CreateCompilation(source);
            comp.VerifyEmitDiagnostics(
                // (2,8): error CS1073: Unexpected token 'ref'
                // using (ref object y = ref x) { }
                Diagnostic(ErrorCode.ERR_UnexpectedToken, "ref").WithArguments("ref").WithLocation(2, 8),
                // (2,8): error CS1674: 'object': type used in a using statement must implement 'System.IDisposable'.
                // using (ref object y = ref x) { }
                Diagnostic(ErrorCode.ERR_NoConvToIDisp, "ref object y = ref x").WithArguments("object").WithLocation(2, 8));
        }
    }
}