From 9894189962fcbdb55522befc675de92e187b62b0 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Thu, 29 Jul 2021 10:30:33 -0700 Subject: [PATCH 1/2] Revert "Revert "Infer delegate types with -langversion:preview only (#53241)" (#53466)" This reverts commit 7d461ed76ee41b2767e8b0d9b7d42008be5fcec0. --- .../Portable/Binder/Binder_Conversions.cs | 8 +-- .../Portable/Binder/Binder_Statements.cs | 3 +- .../Semantics/Conversions/Conversions.cs | 4 +- .../Semantics/Conversions/ConversionsBase.cs | 17 ++++- .../CSharpCompilationExtensions.cs | 9 ++- .../Emit/CodeGen/CodeGenTupleEqualityTests.cs | 60 ++++++++--------- .../Semantic/Semantics/DelegateTypeTests.cs | 65 +++++++++---------- .../Semantics/NullableReferenceTypesTests.cs | 8 +-- .../Symbol/Symbols/ExtensionMethodTests.cs | 4 +- 9 files changed, 91 insertions(+), 87 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs index 78f651d81c914..9d82d05b0054c 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Conversions.cs @@ -557,9 +557,9 @@ private BoundExpression CreateAnonymousFunctionConversion(SyntaxNode syntax, Bou // UNDONE: is converted to a delegate that does not match. What to surface then? var unboundLambda = (UnboundLambda)source; - if (destination.SpecialType == SpecialType.System_Delegate || destination.IsNonGenericExpressionType()) + if ((destination.SpecialType == SpecialType.System_Delegate || destination.IsNonGenericExpressionType()) && + syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType)) { - CheckFeatureAvailability(syntax, MessageID.IDS_FeatureInferredDelegateType, diagnostics); CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); var delegateType = unboundLambda.InferDelegateType(ref useSiteInfo); BoundLambda boundLambda; @@ -628,9 +628,9 @@ private BoundExpression CreateMethodGroupConversion(SyntaxNode syntax, BoundExpr hasErrors = true; } - if (destination.SpecialType == SpecialType.System_Delegate) + if (destination.SpecialType == SpecialType.System_Delegate && + syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType)) { - CheckFeatureAvailability(syntax, MessageID.IDS_FeatureInferredDelegateType, diagnostics); // https://github.com/dotnet/roslyn/issues/52869: Avoid calculating the delegate type multiple times during conversion. CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); var delegateType = GetMethodGroupDelegateType(group, ref useSiteInfo); diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs index 08cb704d851a2..34f2a42406241 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs @@ -2276,7 +2276,8 @@ void reportMethodGroupErrors(BoundMethodGroup methodGroup, bool fromAddressOf) { errorCode = ErrorCode.ERR_AddressOfToNonFunctionPointer; } - else if (targetType.SpecialType == SpecialType.System_Delegate) + else if (targetType.SpecialType == SpecialType.System_Delegate && + syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType)) { Error(diagnostics, ErrorCode.ERR_CannotInferDelegateType, location); return; diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs index 4d3ae007d3af5..e77a92d2c4623 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/Conversions.cs @@ -45,7 +45,7 @@ protected override ConversionsBase WithNullabilityCore(bool includeNullability) public override Conversion GetMethodGroupDelegateConversion(BoundMethodGroup source, TypeSymbol destination, ref CompoundUseSiteInfo useSiteInfo) { // Must be a bona fide delegate type, not an expression tree type. - if (!(destination.IsDelegateType() || destination.SpecialType == SpecialType.System_Delegate)) + if (!(destination.IsDelegateType() || (destination.SpecialType == SpecialType.System_Delegate && IsFeatureInferredDelegateTypeEnabled(source)))) { return Conversion.NoConversion; } @@ -132,7 +132,7 @@ private static MethodGroupResolution ResolveDelegateOrFunctionPointerMethodGroup return (signature, true, new CallingConventionInfo(signature.CallingConvention, signature.GetCallingConventionModifiers())); } - var delegateType = (type.SpecialType == SpecialType.System_Delegate) ? + var delegateType = (type.SpecialType == SpecialType.System_Delegate) && methodGroup.Syntax.IsFeatureEnabled(MessageID.IDS_FeatureNullableReferenceTypes) ? // https://github.com/dotnet/roslyn/issues/52869: Avoid calculating the delegate type multiple times during conversion. _binder.GetMethodGroupDelegateType(methodGroup, ref useSiteInfo) : type.GetDelegateType(); diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs index 88611390f4181..976518f8a9be2 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/Conversions/ConversionsBase.cs @@ -1407,20 +1407,31 @@ public static LambdaConversionResult IsAnonymousFunctionCompatibleWithType(Unbou if (type.SpecialType == SpecialType.System_Delegate) { - return LambdaConversionResult.Success; + if (IsFeatureInferredDelegateTypeEnabled(anonymousFunction)) + { + return LambdaConversionResult.Success; + } } else if (type.IsDelegateType()) { return IsAnonymousFunctionCompatibleWithDelegate(anonymousFunction, type, isTargetExpressionTree: false); } - else if (type.IsGenericOrNonGenericExpressionType(out bool _)) + else if (type.IsGenericOrNonGenericExpressionType(out bool isGenericType)) { - return IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type); + if (isGenericType || IsFeatureInferredDelegateTypeEnabled(anonymousFunction)) + { + return IsAnonymousFunctionCompatibleWithExpressionTree(anonymousFunction, (NamedTypeSymbol)type); + } } return LambdaConversionResult.BadTargetType; } + internal static bool IsFeatureInferredDelegateTypeEnabled(BoundExpression expr) + { + return expr.Syntax.IsFeatureEnabled(MessageID.IDS_FeatureInferredDelegateType); + } + private static bool HasAnonymousFunctionConversion(BoundExpression source, TypeSymbol destination) { Debug.Assert(source != null); diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilationExtensions.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilationExtensions.cs index 038bf728ef2ce..46437b25d17a0 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilationExtensions.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilationExtensions.cs @@ -2,8 +2,6 @@ // 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 System.Linq; namespace Microsoft.CodeAnalysis.CSharp @@ -12,7 +10,12 @@ internal static class CSharpCompilationExtensions { internal static bool IsFeatureEnabled(this CSharpCompilation compilation, MessageID feature) { - return ((CSharpParseOptions)compilation.SyntaxTrees.FirstOrDefault()?.Options)?.IsFeatureEnabled(feature) == true; + return ((CSharpParseOptions?)compilation.SyntaxTrees.FirstOrDefault()?.Options)?.IsFeatureEnabled(feature) == true; + } + + internal static bool IsFeatureEnabled(this SyntaxNode? syntax, MessageID feature) + { + return ((CSharpParseOptions?)syntax?.SyntaxTree.Options)?.IsFeatureEnabled(feature) == true; } } } diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs index 89ee7957084a1..ac0235239f112 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs @@ -1358,12 +1358,9 @@ static void Main() // (6,30): error CS0034: Operator '==' is ambiguous on operands of type '' and 'default' // System.Console.Write((null, () => 1) == (default, default)); Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "(null, () => 1) == (default, default)").WithArguments("==", "", "default").WithLocation(6, 30), - // (6,37): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (6,30): error CS0019: Operator '==' cannot be applied to operands of type 'lambda expression' and 'default' // System.Console.Write((null, () => 1) == (default, default)); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => 1").WithArguments("inferred delegate type", "10.0").WithLocation(6, 37), - // (6,37): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // System.Console.Write((null, () => 1) == (default, default)); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => 1").WithArguments("inferred delegate type", "10.0").WithLocation(6, 37), + Diagnostic(ErrorCode.ERR_BadBinaryOps, "(null, () => 1) == (default, default)").WithArguments("==", "lambda expression", "default").WithLocation(6, 30), // (7,30): error CS0034: Operator '==' is ambiguous on operands of type '(, lambda expression)' and 'default' // System.Console.Write((null, () => 2) == default); Diagnostic(ErrorCode.ERR_AmbigBinaryOps, "(null, () => 2) == default").WithArguments("==", "(, lambda expression)", "default").WithLocation(7, 30) @@ -1672,31 +1669,16 @@ static void Main() }"; var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (6,65): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x => x").WithArguments("inferred delegate type", "10.0").WithLocation(6, 65), - // (6,65): error CS8917: The delegate type could not be inferred. + // (6,30): error CS0019: Operator '==' cannot be applied to operands of type '' and 'lambda expression' // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(6, 65), - // (6,65): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_BadBinaryOps, "(null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })").WithArguments("==", "", "lambda expression").WithLocation(6, 30), + // (6,30): error CS0019: Operator '==' cannot be applied to operands of type '' and 'method group' // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x => x").WithArguments("inferred delegate type", "10.0").WithLocation(6, 65), - // (6,65): error CS8917: The delegate type could not be inferred. - // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(6, 65), - // (6,73): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_BadBinaryOps, "(null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })").WithArguments("==", "", "method group").WithLocation(6, 30), + // (6,30): error CS0019: Operator '==' cannot be applied to operands of type '' and 'lambda expression' // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "Main").WithArguments("inferred delegate type", "10.0").WithLocation(6, 73), - // (6,73): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "Main").WithArguments("inferred delegate type", "10.0").WithLocation(6, 73), - // (6,79): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "(int i) => { int j = 0; return i + j; }").WithArguments("inferred delegate type", "10.0").WithLocation(6, 79), - // (6,79): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "(int i) => { int j = 0; return i + j; }").WithArguments("inferred delegate type", "10.0").WithLocation(6, 79)); - verify(comp); + Diagnostic(ErrorCode.ERR_BadBinaryOps, "(null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })").WithArguments("==", "", "lambda expression").WithLocation(6, 30)); + verify(comp, inferDelegate: false); comp = CreateCompilation(source, parseOptions: TestOptions.RegularPreview); comp.VerifyDiagnostics( @@ -1706,9 +1688,9 @@ static void Main() // (6,65): error CS8917: The delegate type could not be inferred. // System.Console.Write((null, null, null, null) == (null, x => x, Main, (int i) => { int j = 0; return i + j; })); Diagnostic(ErrorCode.ERR_CannotInferDelegateType, "x => x").WithLocation(6, 65)); - verify(comp); + verify(comp, inferDelegate: true); - static void verify(CSharpCompilation comp) + static void verify(CSharpCompilation comp, bool inferDelegate) { var tree = comp.SyntaxTrees[0]; var model = comp.GetSemanticModel(tree); @@ -1732,19 +1714,19 @@ static void verify(CSharpCompilation comp) // ... its first lambda ... var firstLambda = tuple2.Arguments[1].Expression; Assert.Null(model.GetTypeInfo(firstLambda).Type); - Assert.Equal("System.Delegate", model.GetTypeInfo(firstLambda).ConvertedType.ToTestDisplayString()); + verifyType("System.Delegate", model.GetTypeInfo(firstLambda).ConvertedType, inferDelegate); // ... its method group ... var methodGroup = tuple2.Arguments[2].Expression; Assert.Null(model.GetTypeInfo(methodGroup).Type); - Assert.Equal("System.Delegate", model.GetTypeInfo(methodGroup).ConvertedType.ToTestDisplayString()); + verifyType("System.Delegate", model.GetTypeInfo(methodGroup).ConvertedType, inferDelegate); Assert.Null(model.GetSymbolInfo(methodGroup).Symbol); Assert.Equal(new[] { "void C.Main()" }, model.GetSymbolInfo(methodGroup).CandidateSymbols.Select(s => s.ToTestDisplayString())); // ... its second lambda and the symbols it uses var secondLambda = tuple2.Arguments[3].Expression; - Assert.Equal("System.Func", model.GetTypeInfo(secondLambda).Type.ToTestDisplayString()); - Assert.Equal("System.Delegate", model.GetTypeInfo(secondLambda).ConvertedType.ToTestDisplayString()); + verifyType("System.Func", model.GetTypeInfo(secondLambda).Type, inferDelegate); + verifyType("System.Delegate", model.GetTypeInfo(secondLambda).ConvertedType, inferDelegate); var addition = tree.GetCompilationUnitRoot().DescendantNodes().OfType().Last(); Assert.Equal("i + j", addition.ToString()); @@ -1755,6 +1737,18 @@ static void verify(CSharpCompilation comp) var j = addition.Right; Assert.Equal("System.Int32 j", model.GetSymbolInfo(j).Symbol.ToTestDisplayString()); } + + static void verifyType(string expectedType, ITypeSymbol type, bool inferDelegate) + { + if (inferDelegate) + { + Assert.Equal(expectedType, type.ToTestDisplayString()); + } + else + { + Assert.Null(type); + } + } } [Fact] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs index a7351eae5578f..9111005a144d9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/DelegateTypeTests.cs @@ -73,18 +73,18 @@ static void Main() var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (6,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (6,13): error CS0428: Cannot convert method group 'Main' to non-delegate type 'Delegate'. Did you intend to invoke the method? // d = Main; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "Main").WithArguments("inferred delegate type", "10.0").WithLocation(6, 13), - // (7,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_MethGrpToNonDel, "Main").WithArguments("Main", "System.Delegate").WithLocation(6, 13), + // (7,13): error CS1660: Cannot convert lambda expression to type 'Delegate' because it is not a delegate type // d = () => { }; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => { }").WithArguments("inferred delegate type", "10.0").WithLocation(7, 13), - // (8,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => { }").WithArguments("lambda expression", "System.Delegate").WithLocation(7, 13), + // (8,13): error CS1660: Cannot convert anonymous method to type 'Delegate' because it is not a delegate type // d = delegate () { }; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "delegate () { }").WithArguments("inferred delegate type", "10.0").WithLocation(8, 13), - // (9,48): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "delegate () { }").WithArguments("anonymous method", "System.Delegate").WithLocation(8, 13), + // (9,48): error CS1660: Cannot convert lambda expression to type 'Expression' because it is not a delegate type // System.Linq.Expressions.Expression e = () => 1; - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => 1").WithArguments("inferred delegate type", "10.0").WithLocation(9, 48)); + Diagnostic(ErrorCode.ERR_AnonMethToNonDel, "() => 1").WithArguments("lambda expression", "System.Linq.Expressions.Expression").WithLocation(9, 48)); comp = CreateCompilation(source, parseOptions: TestOptions.Regular10); comp.VerifyDiagnostics(); @@ -1821,14 +1821,10 @@ static class E public static void M(this object o, Action a) { Console.WriteLine(""E.M""); } }"; - var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); - comp.VerifyDiagnostics( - // (7,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // c.M(Main); // C#9: E.M(object x, Action y) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "Main").WithArguments("inferred delegate type", "10.0").WithLocation(7, 13), - // (8,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // c.M(() => { }); // C#9: E.M(object x, Action y) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => { }").WithArguments("inferred delegate type", "10.0").WithLocation(8, 13)); + CompileAndVerify(source, parseOptions: TestOptions.Regular9, expectedOutput: +@"E.M +E.M +"); // Breaking change from C#9 which binds to E.M. CompileAndVerify(source, parseOptions: TestOptions.Regular10, expectedOutput: @@ -1861,11 +1857,7 @@ static class E public static void M(this object o, Func a) { Console.WriteLine(""E.M""); } }"; - var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); - comp.VerifyDiagnostics( - // (8,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. - // c.M(() => 1); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => 1").WithArguments("inferred delegate type", "10.0").WithLocation(8, 13)); + CompileAndVerify(source, parseOptions: TestOptions.Regular9, expectedOutput: @"E.M"); // Breaking change from C#9 which binds to E.M. CompileAndVerify(source, parseOptions: TestOptions.Regular10, expectedOutput: @"C.M"); @@ -1904,24 +1896,24 @@ static void Main() var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (14,12): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (14,12): error CS1503: Argument 1: cannot convert from 'method group' to 'Delegate' // FA(F2); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "F2").WithArguments("inferred delegate type", "10.0").WithLocation(14, 12), - // (15,12): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_BadArgType, "F2").WithArguments("1", "method group", "System.Delegate").WithLocation(14, 12), + // (15,12): error CS1503: Argument 1: cannot convert from 'method group' to 'Delegate' // FB(F1); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "F1").WithArguments("inferred delegate type", "10.0").WithLocation(15, 12), - // (18,12): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_BadArgType, "F1").WithArguments("1", "method group", "System.Delegate").WithLocation(15, 12), + // (18,18): error CS0201: Only assignment, call, increment, decrement, await, and new object expressions can be used as a statement // FA(() => 0); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => 0").WithArguments("inferred delegate type", "10.0").WithLocation(18, 12), - // (19,12): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_IllegalStatement, "0").WithLocation(18, 18), + // (19,15): error CS1643: Not all code paths return a value in lambda expression of type 'Func' // FB(() => { }); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => { }").WithArguments("inferred delegate type", "10.0").WithLocation(19, 12), - // (22,12): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_AnonymousReturnExpected, "=>").WithArguments("lambda expression", "System.Func").WithLocation(19, 15), + // (22,26): error CS8030: Anonymous function converted to a void returning delegate cannot return a value // FA(delegate () { return 0; }); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "delegate () { return 0; }").WithArguments("inferred delegate type", "10.0").WithLocation(22, 12), - // (23,12): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + Diagnostic(ErrorCode.ERR_RetNoObjectRequiredLambda, "return").WithLocation(22, 26), + // (23,12): error CS1643: Not all code paths return a value in anonymous method of type 'Func' // FB(delegate () { }); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "delegate () { }").WithArguments("inferred delegate type", "10.0").WithLocation(23, 12)); + Diagnostic(ErrorCode.ERR_AnonymousReturnExpected, "delegate").WithArguments("anonymous method", "System.Func").WithLocation(23, 12)); CompileAndVerify(source, parseOptions: TestOptions.Regular10, expectedOutput: @"FA(Action) @@ -1959,9 +1951,12 @@ static void Main() var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); comp.VerifyDiagnostics( - // (11,11): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (11,17): error CS0029: Cannot implicitly convert type 'string' to 'int' + // F(() => string.Empty); + Diagnostic(ErrorCode.ERR_NoImplicitConv, "string.Empty").WithArguments("string", "int").WithLocation(11, 17), + // (11,17): error CS1662: Cannot convert lambda expression to intended delegate type because some of the return types in the block are not implicitly convertible to the delegate return type // F(() => string.Empty); - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "() => string.Empty").WithArguments("inferred delegate type", "10.0").WithLocation(11, 11)); + Diagnostic(ErrorCode.ERR_CantConvAnonMethReturns, "string.Empty").WithArguments("lambda expression").WithLocation(11, 17)); CompileAndVerify(source, parseOptions: TestOptions.Regular10, expectedOutput: @"F(Expression>): () => 0 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs index 005c61294515e..57194f1872599 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs @@ -1949,9 +1949,9 @@ static void M(A a) // (8,9): error CS1656: Cannot assign to 'E' because it is a 'method group' // a.E! += a.E!; // 1 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "a.E").WithArguments("E", "method group").WithLocation(8, 9), - // (9,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (9,13): error CS0019: Operator '!=' cannot be applied to operands of type 'method group' and '' // if (a.E! != null) // 2 - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "a.E").WithArguments("inferred delegate type", "10.0").WithLocation(9, 13), + Diagnostic(ErrorCode.ERR_BadBinaryOps, "a.E! != null").WithArguments("!=", "method group", "").WithLocation(9, 13), // (11,15): error CS1503: Argument 1: cannot convert from 'method group' to 'A' // M(a.E!); // 3 Diagnostic(ErrorCode.ERR_BadArgType, "a.E").WithArguments("1", "method group", "A").WithLocation(11, 15), @@ -1970,9 +1970,9 @@ static void M(A a) // (17,9): error CS1656: Cannot assign to 'F' because it is a 'method group' // a.F! += a.F!; // 8 Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "a.F").WithArguments("F", "method group").WithLocation(17, 9), - // (18,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (18,13): error CS0019: Operator '!=' cannot be applied to operands of type 'method group' and '' // if (a.F! != null) // 9 - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "a.F").WithArguments("inferred delegate type", "10.0").WithLocation(18, 13), + Diagnostic(ErrorCode.ERR_BadBinaryOps, "a.F! != null").WithArguments("!=", "method group", "").WithLocation(18, 13), // (20,15): error CS1503: Argument 1: cannot convert from 'method group' to 'A' // M(a.F!); // 10 Diagnostic(ErrorCode.ERR_BadArgType, "a.F").WithArguments("1", "method group", "A").WithLocation(20, 15), diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtensionMethodTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtensionMethodTests.cs index 14146f5916534..2a7eda482e594 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ExtensionMethodTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ExtensionMethodTests.cs @@ -1140,9 +1140,9 @@ static class S // (5,9): error CS1656: Cannot assign to 'E' because it is a 'method group' // o.E += o.E; Diagnostic(ErrorCode.ERR_AssgReadonlyLocalCause, "o.E").WithArguments("E", "method group").WithLocation(5, 9), - // (6,13): error CS8773: Feature 'inferred delegate type' is not available in C# 9.0. Please use language version 10.0 or greater. + // (6,13): error CS0019: Operator '!=' cannot be applied to operands of type 'method group' and '' // if (o.E != null) - Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "o.E").WithArguments("inferred delegate type", "10.0").WithLocation(6, 13), + Diagnostic(ErrorCode.ERR_BadBinaryOps, "o.E != null").WithArguments("!=", "method group", "").WithLocation(6, 13), // (8,15): error CS1503: Argument 1: cannot convert from 'method group' to 'object' // M(o.E); Diagnostic(ErrorCode.ERR_BadArgType, "o.E").WithArguments("1", "method group", "object").WithLocation(8, 15), From 6a8b813c0fd40ea3a17c5f36b87892cd3f3d90e2 Mon Sep 17 00:00:00 2001 From: Charles Stoner Date: Thu, 29 Jul 2021 12:23:05 -0700 Subject: [PATCH 2/2] Update existing test for -langversion:9 and -langversion:latest --- .../Emit/CodeGen/CodeGenTupleEqualityTests.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs index ac0235239f112..ff2fa54d329e5 100644 --- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs +++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleEqualityTests.cs @@ -2016,7 +2016,20 @@ public void M() if ("""" == 1) {} } }"; - var comp = CreateCompilation(source); + var comp = CreateCompilation(source, parseOptions: TestOptions.Regular9); + comp.VerifyDiagnostics( + // (6,13): error CS0815: Cannot assign (, ) to an implicitly-typed variable + // var t = (null, null); + Diagnostic(ErrorCode.ERR_ImplicitlyTypedVariableAssignedBadValue, "t = (null, null)").WithArguments("(, )").WithLocation(6, 13), + // (7,13): error CS0019: Operator '==' cannot be applied to operands of type '' and 'lambda expression' + // if (null == (() => {}) ) {} + Diagnostic(ErrorCode.ERR_BadBinaryOps, "null == (() => {})").WithArguments("==", "", "lambda expression").WithLocation(7, 13), + // (8,13): error CS0019: Operator '==' cannot be applied to operands of type 'string' and 'int' + // if ("" == 1) {} + Diagnostic(ErrorCode.ERR_BadBinaryOps, @""""" == 1").WithArguments("==", "string", "int").WithLocation(8, 13) + ); + + comp = CreateCompilation(source); comp.VerifyDiagnostics( // (6,13): error CS0815: Cannot assign (, ) to an implicitly-typed variable // var t = (null, null);