diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index f5392eafa669..275336b7e407 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -779,13 +779,6 @@ internal MethodSymbol TryFindDisposePatternMethod(BoundExpression expr, SyntaxNo else if ((!hasAwait && disposeMethod?.ReturnsVoid == false) || result == PatternLookupResult.NotAMethod) { - CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); - if (this.IsAccessible(disposeMethod, ref useSiteInfo)) - { - diagnostics.Add(ErrorCode.WRN_PatternBadSignature, syntaxNode.Location, expr.Type, MessageID.IDS_Disposable.Localize(), disposeMethod); - } - - diagnostics.Add(syntaxNode, useSiteInfo); disposeMethod = null; } diff --git a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs index 8bf71321ff48..9ccb48982189 100644 --- a/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/UsingStatementBinder.cs @@ -196,12 +196,11 @@ bool bindDisposable(bool fromExpression, out MethodArgumentInfo? patternDisposeI ? expressionOpt : new BoundLocal(syntax, declarationsOpt[0].LocalSymbol, null, type) { WasCompilerGenerated = true }; - BindingDiagnosticBag patternDiagnostics = originalBinder.Compilation.IsFeatureEnabled(MessageID.IDS_FeatureDisposalPattern) - ? diagnostics - : BindingDiagnosticBag.Discarded; + BindingDiagnosticBag patternDiagnostics = BindingDiagnosticBag.GetInstance(diagnostics); MethodSymbol disposeMethod = originalBinder.TryFindDisposePatternMethod(receiver, syntax, hasAwait, patternDiagnostics, out bool expanded); if (disposeMethod is object) { + diagnostics.AddRangeAndFree(patternDiagnostics); MessageID.IDS_FeatureDisposalPattern.CheckFeatureAvailability(diagnostics, originalBinder.Compilation, syntax.Location); var argumentsBuilder = ArrayBuilder.GetInstance(disposeMethod.ParameterCount); @@ -220,7 +219,7 @@ bool bindDisposable(bool fromExpression, out MethodArgumentInfo? patternDisposeI out BitVector defaultArguments, expanded, enableCallerInfo: true, - patternDiagnostics); + diagnostics); Debug.Assert(argsToParams.IsDefault); patternDisposeInfo = new MethodArgumentInfo(disposeMethod, argumentsBuilder.ToImmutableAndFree(), defaultArguments, expanded); @@ -228,8 +227,11 @@ bool bindDisposable(bool fromExpression, out MethodArgumentInfo? patternDisposeI { awaitableType = disposeMethod.ReturnType; } + return true; } + + patternDiagnostics.Free(); } // Interface binding diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs index 2dcb0b215b19..cfa5cd0b1d6c 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitForeachTests.cs @@ -9294,5 +9294,84 @@ public async ValueTask DisposeAsync() info.DisposeMethod.ToTestDisplayString()); Assert.Equal("(System.Int32, System.Int32)", info.ElementType.ToTestDisplayString()); } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72819")] + public void PatternBasedFails_AwaitForeach() + { + var src = """ +using System; +using System.Threading; +using System.Threading.Tasks; + +interface ICustomEnumerator +{ + public int Current {get;} + + public ValueTask MoveNextAsync(); +} + +interface IGetEnumerator where TEnumerator : ICustomEnumerator +{ + TEnumerator GetAsyncEnumerator(CancellationToken token = default); +} + +struct S1 : IGetEnumerator +{ + public S2 GetAsyncEnumerator(CancellationToken token = default) + { + return new S2(); + } +} + +interface IMyAsyncDisposable1 +{ + ValueTask DisposeAsync(); +} + +interface IMyAsyncDisposable2 +{ + ValueTask DisposeAsync(); +} + +struct S2 : ICustomEnumerator, IMyAsyncDisposable1, IMyAsyncDisposable2, IAsyncDisposable +{ + ValueTask IMyAsyncDisposable1.DisposeAsync() => throw null; + ValueTask IMyAsyncDisposable2.DisposeAsync() => throw null; + public ValueTask DisposeAsync() + { + System.Console.Write("D"); + return ValueTask.CompletedTask; + } + + public int Current => throw null; + public ValueTask MoveNextAsync() + { + return ValueTask.FromResult(false); + } +} + +class C +{ + static async Task Main() + { + await Test(); + } + + static async Task Test() + where TEnumerable : IGetEnumerator + where TEnumerator : ICustomEnumerator, IMyAsyncDisposable1, IMyAsyncDisposable2, IAsyncDisposable + { + await foreach (var i in default(TEnumerable)) + { + System.Console.Write(i); + } + } +} +"""; + var comp = CreateCompilation(src, targetFramework: TargetFramework.Net80, options: TestOptions.ReleaseExe); + CompileAndVerify(comp, + expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "D" : null, + verify: ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped).VerifyDiagnostics(); + } } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs index 7282e99ed475..f1511be7c6bb 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenAwaitUsingTests.cs @@ -324,6 +324,26 @@ public async System.Threading.Tasks.ValueTask DisposeAsync() // 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] @@ -2645,13 +2665,9 @@ private System.Threading.Tasks.ValueTask DisposeAsync() "; var comp = CreateCompilationWithTasksExtensions(new[] { source, IAsyncDisposableDefinition }); comp.VerifyDiagnostics( - // (6,22): error CS0122: 'C.DisposeAsync()' is inaccessible due to its protection level + // 0.cs(6,22): error CS8410: 'C': type used in an asynchronous using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. // await using (var x = new C()) - Diagnostic(ErrorCode.ERR_BadAccess, "var x = new C()").WithArguments("C.DisposeAsync()").WithLocation(6, 22), - // (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) - ); + Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "var x = new C()").WithArguments("C").WithLocation(6, 22)); } [ConditionalFact(typeof(WindowsOnly), Reason = ConditionalSkipReason.NativePdbRequiresDesktop)] @@ -3519,5 +3535,221 @@ public ValueTask DisposeAsync() 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 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 objects) + { + throw null; + } +} +"""; + var comp = CreateCompilationWithTasksExtensions([source, IAsyncDisposableDefinition]); + comp.VerifyEmitDiagnostics( + // (5,1): error CS8410: 'Class1': type used in an asynchronous using statement must be implicitly convertible to '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 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(); + } + + static async Task Test() 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(); + } } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenUsingStatementTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenUsingStatementTests.cs index 168fedc8068e..a0775de65acd 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenUsingStatementTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenUsingStatementTests.cs @@ -3113,9 +3113,6 @@ ref struct S if (modifier == "ref") { CreateCompilation(source).VerifyDiagnostics( - // (2,8): error CS7036: There is no argument given that corresponds to the required parameter 'x' of 'S.Dispose(ref int)' - // using (var s = new S()) - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "var s = new S()").WithArguments("x", "S.Dispose(ref int)").WithLocation(2, 8), // (2,8): error CS1674: 'S': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (var s = new S()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "var s = new S()").WithArguments("S").WithLocation(2, 8), diff --git a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs index 88487d7c94da..521247abdd5b 100644 --- a/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/RefStructInterfacesTests.cs @@ -13501,9 +13501,6 @@ static async Task Main() var comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, options: TestOptions.ReleaseExe); comp.VerifyDiagnostics( - // (32,22): error CS0121: The call is ambiguous between the following methods or properties: 'IMyAsyncDisposable1.DisposeAsync()' and 'IMyAsyncDisposable2.DisposeAsync()' - // await using (new T()) - Diagnostic(ErrorCode.ERR_AmbigCall, "new T()").WithArguments("IMyAsyncDisposable1.DisposeAsync()", "IMyAsyncDisposable2.DisposeAsync()").WithLocation(32, 22), // (32,22): error CS8410: 'T': type used in an asynchronous using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. // await using (new T()) Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "new T()").WithArguments("T").WithLocation(32, 22) @@ -13514,6 +13511,8 @@ static async Task Main() [WorkItem("https://github.com/dotnet/roslyn/issues/72819")] public void AwaitUsing_08() { + // 'System.Activator.CreateInstance' will be changed to include 'allows ref struct' constraint, + // see https://github.com/dotnet/runtime/issues/65112. var src = @" using System; using System.Threading.Tasks; @@ -13555,15 +13554,21 @@ static async Task Main() } } } + +namespace System +{ + public class Activator + { + public static T CreateInstance() where T : allows ref struct => default; + } +} "; var comp = CreateCompilation(src, targetFramework: s_targetFrameworkSupportingByRefLikeGenerics, options: TestOptions.ReleaseExe); - // https://github.com/dotnet/roslyn/issues/72819: The failure is likely unexpected, but is not specific to `allow ref struct` scenario. - comp.VerifyDiagnostics( - // (36,22): error CS0121: The call is ambiguous between the following methods or properties: 'IMyAsyncDisposable1.DisposeAsync()' and 'IMyAsyncDisposable2.DisposeAsync()' - // await using (new T()) - Diagnostic(ErrorCode.ERR_AmbigCall, "new T()").WithArguments("IMyAsyncDisposable1.DisposeAsync()", "IMyAsyncDisposable2.DisposeAsync()").WithLocation(36, 22) - ); + CompileAndVerify( + comp, + expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "123D" : null, + verify: ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped).VerifyDiagnostics(); } [ConditionalFact(typeof(NoUsedAssembliesValidation))] // https://github.com/dotnet/roslyn/issues/73563 diff --git a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs index 394f3007bd19..3eb38d6c2ba3 100644 --- a/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs +++ b/src/Compilers/CSharp/Test/IOperation/IOperation/IOperationTests_IUsingStatement.cs @@ -1939,9 +1939,6 @@ .maxstack 8 var expectedDiagnostics = new[] { - // (6,15): error CS7036: There is no argument given that corresponds to the required parameter 'extras' of 'S.Dispose(params int)' - // using(var s = new S()) - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "var s = new S()").WithArguments("extras", "S.Dispose(params int)").WithLocation(6, 15), // (6,15): error CS1674: 'S': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using(var s = new S()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "var s = new S()").WithArguments("S").WithLocation(6, 15), @@ -2076,9 +2073,6 @@ .maxstack 8 var expectedDiagnostics = new[] { - // (6,15): error CS7036: There is no argument given that corresponds to the required parameter 'extras' of 'S.Dispose(params int)' - // using(var s = new S()) - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "var s = new S()").WithArguments("extras", "S.Dispose(params int)").WithLocation(6, 15), // (6,15): error CS1674: 'S': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using(var s = new S()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "var s = new S()").WithArguments("S").WithLocation(6, 15), @@ -2213,9 +2207,6 @@ .maxstack 8 var expectedDiagnostics = new[] { - // (6,15): error CS7036: There is no argument given that corresponds to the required parameter 'extras' of 'S.Dispose(params int)' - // using(var s = new S()) - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "var s = new S()").WithArguments("extras", "S.Dispose(params int)").WithLocation(6, 15), // (6,15): error CS1674: 'S': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using(var s = new S()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "var s = new S()").WithArguments("S").WithLocation(6, 15), @@ -2351,9 +2342,6 @@ .maxstack 8 var expectedDiagnostics = new[] { - // (6,15): error CS7036: There is no argument given that corresponds to the required parameter 'extras' of 'S.Dispose(params object[], int)' - // using(var s = new S()) - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "var s = new S()").WithArguments("extras", "S.Dispose(params object[], int)").WithLocation(6, 15), // (6,15): error CS1674: 'S': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using(var s = new S()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "var s = new S()").WithArguments("S").WithLocation(6, 15), @@ -4755,9 +4743,6 @@ public async Task M() "; var expectedDiagnostics = new[] { - // file.cs(8,21): error CS7036: There is no argument given that corresponds to the required parameter 'extras' of 'C.DisposeAsync(int, params int[], bool)' - // await using(this){} - Diagnostic(ErrorCode.ERR_NoCorrespondingArgument, "this").WithArguments("extras", "C.DisposeAsync(int, params int[], bool)").WithLocation(8, 21), // file.cs(8,21): error CS8410: 'C': type used in an asynchronous using statement must be implicitly convertible to 'System.IAsyncDisposable' or implement a suitable 'DisposeAsync' method. // await using(this){} Diagnostic(ErrorCode.ERR_NoConvToIAsyncDisp, "this").WithArguments("C").WithLocation(8, 21), @@ -7573,12 +7558,9 @@ void M(bool b) "; var expectedDiagnostics = new[] { - // file.cs(8,13): warning CS0280: 'P' does not implement the 'disposable' pattern. 'P.Dispose()' has the wrong signature. - // using var x = new P(); - Diagnostic(ErrorCode.WRN_PatternBadSignature, "using var x = new P();").WithArguments("P", "disposable", "P.Dispose()").WithLocation(8, 13), - // file.cs(8,13): error CS1674: 'P': type used in a using statement must be implicitly convertible to 'System.IDisposable'. - // using var x = new P(); - Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using var x = new P();").WithArguments("P").WithLocation(8, 13) + // file.cs(8,13): error CS1674: 'P': type used in a using statement must be implicitly convertible to 'System.IDisposable'. + // using var x = new P(); + Diagnostic(ErrorCode.ERR_NoConvToIDisp, "using var x = new P();").WithArguments("P").WithLocation(8, 13) }; VerifyFlowGraphAndDiagnosticsForTest(source, expectedGraph, expectedDiagnostics); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs index 610897b83d56..847bb7496713 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/UsingStatementTests.cs @@ -165,9 +165,6 @@ static void Main() // (5,17): error CS0111: Type 'S1' already defines a member called 'Dispose' with the same parameter types // public void Dispose() { } Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Dispose").WithArguments("Dispose", "S1").WithLocation(5, 17), - // (12,16): error CS0121: The call is ambiguous between the following methods or properties: 'S1.Dispose()' and 'S1.Dispose()' - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_AmbigCall, "S1 s = new S1()").WithArguments("S1.Dispose()", "S1.Dispose()").WithLocation(12, 16), // (12,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(12, 16) @@ -199,15 +196,9 @@ static void Main() // (5,17): error CS0111: Type 'S1' already defines a member called 'Dispose' with the same parameter types // public bool Dispose() { return false; } Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Dispose").WithArguments("Dispose", "S1").WithLocation(5, 17), - // (12,16): error CS0121: The call is ambiguous between the following methods or properties: 'S1.Dispose()' and 'S1.Dispose()' - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_AmbigCall, "S1 s = new S1()").WithArguments("S1.Dispose()", "S1.Dispose()").WithLocation(12, 16), // (12,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(12, 16), - // (16,16): error CS0121: The call is ambiguous between the following methods or properties: 'S1.Dispose()' and 'S1.Dispose()' - // using (c1b) { } - Diagnostic(ErrorCode.ERR_AmbigCall, "s1b").WithArguments("S1.Dispose()", "S1.Dispose()").WithLocation(16, 16), // (16,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (c1b) { } Diagnostic(ErrorCode.ERR_NoConvToIDisp, "s1b").WithArguments("S1").WithLocation(16, 16) @@ -264,15 +255,9 @@ static void Main() // (5,19): error CS0111: Type 'S1' already defines a member called 'Dispose' with the same parameter types // internal void Dispose() { } Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Dispose").WithArguments("Dispose", "S1").WithLocation(5, 19), - // (12,16): error CS0121: The call is ambiguous between the following methods or properties: 'S1.Dispose()' and 'S1.Dispose()' - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_AmbigCall, "S1 s = new S1()").WithArguments("S1.Dispose()", "S1.Dispose()").WithLocation(12, 16), // (12,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(12, 16), - // (16,16): error CS0121: The call is ambiguous between the following methods or properties: 'S1.Dispose()' and 'S1.Dispose()' - // using (c1b) { } - Diagnostic(ErrorCode.ERR_AmbigCall, "s1b").WithArguments("S1.Dispose()", "S1.Dispose()").WithLocation(16, 16), // (16,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (c1b) { } Diagnostic(ErrorCode.ERR_NoConvToIDisp, "s1b").WithArguments("S1").WithLocation(16, 16) @@ -398,11 +383,8 @@ static void Main() } }"; CreateCompilation(source).VerifyDiagnostics( - // (11,16): error CS0176: Member 'S1.Dispose()' cannot be accessed with an instance reference; qualify it with a type name instead - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_ObjectProhibited, "S1 s = new S1()").WithArguments("S1.Dispose()").WithLocation(11, 16), // (11,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. - // using (S1 c = new S1()) + // using (S1 s = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(11, 16) ); } @@ -434,13 +416,10 @@ static void Main() } } }"; - // Extension methods should just be ignored, rather than rejected after-the-fact. So there should be no error about ambiguities + // Extension methods should just be ignored, rather than rejected after-the-fact. So there should be no error // Tracked by https://github.com/dotnet/roslyn/issues/32767 CreateCompilation(source).VerifyDiagnostics( - // (20,16): error CS0121: The call is ambiguous between the following methods or properties: 'C2.Dispose(S1)' and 'C3.Dispose(S1)' - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_AmbigCall, "S1 s = new S1()").WithArguments("C2.Dispose(S1)", "C3.Dispose(S1)").WithLocation(20, 16), // (20,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(20, 16) @@ -562,7 +541,7 @@ static void M6() } } }"; - // Extension methods should just be ignored, rather than rejected after-the-fact. So there should be no error about ambiguities + // Extension methods should just be ignored, rather than rejected after-the-fact. So there should be no error // Tracked by https://github.com/dotnet/roslyn/issues/32767 CreateCompilation(source).VerifyDiagnostics( @@ -575,9 +554,6 @@ static void M6() // (63,20): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 s = new S1()) // error 3 Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(63, 20), - // (77,20): error CS0121: The call is ambiguous between the following methods or properties: 'N1.C2.Dispose(S1)' and 'N3.C4.Dispose(S1)' - // using (S1 s = new S1()) // error 4 - Diagnostic(ErrorCode.ERR_AmbigCall, "S1 s = new S1()").WithArguments("N1.C2.Dispose(S1)", "N3.C4.Dispose(S1)").WithLocation(77, 20), // (77,20): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 s = new S1()) // error 4 Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(77, 20), @@ -671,13 +647,10 @@ static void Main() } } }"; - // Extension methods should just be ignored, rather than rejected after-the-fact. So there should be no error about ambiguities + // Extension methods should just be ignored, rather than rejected after-the-fact. So there should be no error // Tracked by https://github.com/dotnet/roslyn/issues/32767 CreateCompilation(source).VerifyDiagnostics( - // (21,15): error CS0121: The call is ambiguous between the following methods or properties: 'C2.Dispose(S1, int)' and 'C3.Dispose(S1, int)' - // using (S1 s = new S1()) - Diagnostic(ErrorCode.ERR_AmbigCall, "S1 s = new S1()").WithArguments("C2.Dispose(S1, int)", "C3.Dispose(S1, int)").WithLocation(21, 15), // (21,15): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 s = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(21, 15) @@ -745,9 +718,6 @@ static void Main() } }"; CreateCompilation(source).VerifyDiagnostics( - // (19,15): warning CS0280: 'S1' does not implement the 'disposable' pattern. 'S1.Dispose()' has the wrong signature. - // using (S1 s = new S1()) - Diagnostic(ErrorCode.WRN_PatternBadSignature, "S1 s = new S1()").WithArguments("S1", "disposable", "S1.Dispose()").WithLocation(19, 15), // (19,15): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 s = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(19, 15) @@ -873,10 +843,7 @@ static void Main() var compilation = CreateCompilation(source).VerifyDiagnostics( // (15,15): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 s = new S1()) - Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(15, 15), - // (15,18): error CS1657: Cannot use 's' as a ref or out value because it is a 'using variable' - // using (S1 s = new S1()) - Diagnostic(ErrorCode.ERR_RefReadonlyLocalCause, "S1 s = new S1()").WithArguments("s", "using variable").WithLocation(15, 15) + Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(15, 15) ); } @@ -947,15 +914,9 @@ static void Main() } }"; CreateCompilation(source).VerifyDiagnostics( - // (11,16): warning CS0280: 'S1' does not implement the 'disposable' pattern. 'S1.Dispose()' has the wrong signature. - // using (S1 c = new S1()) - Diagnostic(ErrorCode.WRN_PatternBadSignature, "S1 c = new S1()").WithArguments("S1", "disposable", "S1.Dispose()").WithLocation(11, 16), // (11,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 c = new S1()").WithArguments("S1").WithLocation(11, 16), - // (15,16): warning CS0280: 'S1' does not implement the 'disposable' pattern. 'S1.Dispose()' has the wrong signature. - // using (c1b) { } - Diagnostic(ErrorCode.WRN_PatternBadSignature, "c1b").WithArguments("S1", "disposable", "S1.Dispose()").WithLocation(15, 16), // (15,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (c1b) { } Diagnostic(ErrorCode.ERR_NoConvToIDisp, "c1b").WithArguments("S1").WithLocation(15, 16) @@ -983,15 +944,9 @@ static void Main() } }"; CreateCompilation(source).VerifyDiagnostics( - // (11,16): error CS0122: 'S1.Dispose()' is inaccessible due to its protection level - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_BadAccess, "S1 c = new S1()").WithArguments("S1.Dispose()").WithLocation(11, 16), // (11,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 c = new S1()").WithArguments("S1").WithLocation(11, 16), - // (15,16): error CS0122: 'S1.Dispose()' is inaccessible due to its protection level - // using (c1b) { } - Diagnostic(ErrorCode.ERR_BadAccess, "c1b").WithArguments("S1.Dispose()").WithLocation(15, 16), // (15,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (c1b) { } Diagnostic(ErrorCode.ERR_NoConvToIDisp, "c1b").WithArguments("S1").WithLocation(15, 16) @@ -1041,9 +996,6 @@ static void Main() } "; CreateCompilation(source).VerifyDiagnostics( - // (11,16): error CS0176: Member 'S1.Dispose()' cannot be accessed with an instance reference; qualify it with a type name instead - // using (S1 c1 = new S1()) - Diagnostic(ErrorCode.ERR_ObjectProhibited, "S1 c1 = new S1()").WithArguments("S1.Dispose()").WithLocation(11, 16), // (11,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c1 = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 c1 = new S1()").WithArguments("S1").WithLocation(11, 16) @@ -1069,9 +1021,6 @@ static void Main() } }"; CreateCompilation(source).VerifyDiagnostics( - // (11,16): error CS0411: The type arguments for method 'S1.Dispose()' cannot be inferred from the usage. Try specifying the type arguments explicitly. - // using (S1 c = new S1()) - Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "S1 c = new S1()").WithArguments("S1.Dispose()").WithLocation(11, 16), // (11,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable'. // using (S1 c = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 c = new S1()").WithArguments("S1").WithLocation(11, 16) @@ -1247,9 +1196,6 @@ static void Main() ); CreateCompilation(source, parseOptions: TestOptions.Regular8).VerifyDiagnostics( - // (11,16): warning CS0280: 'S1' does not implement the 'disposable' pattern. 'S1.Dispose()' has the wrong signature. - // using (S1 s = new S1()) - Diagnostic(ErrorCode.WRN_PatternBadSignature, "S1 s = new S1()").WithArguments("S1", "disposable", "S1.Dispose()").WithLocation(11, 16), // (11,16): error CS1674: 'S1': type used in a using statement must be implicitly convertible to 'System.IDisposable' or implement a suitable 'Dispose' method. // using (S1 s = new S1()) Diagnostic(ErrorCode.ERR_NoConvToIDisp, "S1 s = new S1()").WithArguments("S1").WithLocation(11, 16)