From ecfc6e2cdd585554be13692c6d6aef7291313aa9 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Thu, 16 May 2024 11:00:44 -0700
Subject: [PATCH 01/15] Report diagnostic for field and value identifiers in
property accessors where the meaning would change as contextual keywords
---
.../CSharp/Portable/CSharpResources.resx | 9 +
.../Portable/Compiler/MethodCompiler.cs | 118 ++-
.../CSharp/Portable/Errors/ErrorCode.cs | 1 +
.../CSharp/Portable/Errors/ErrorFacts.cs | 1 +
.../CSharp/Portable/Errors/MessageID.cs | 2 +
.../Generated/ErrorFacts.Generated.cs | 1 +
.../Portable/xlf/CSharpResources.cs.xlf | 15 +
.../Portable/xlf/CSharpResources.de.xlf | 15 +
.../Portable/xlf/CSharpResources.es.xlf | 15 +
.../Portable/xlf/CSharpResources.fr.xlf | 15 +
.../Portable/xlf/CSharpResources.it.xlf | 15 +
.../Portable/xlf/CSharpResources.ja.xlf | 15 +
.../Portable/xlf/CSharpResources.ko.xlf | 15 +
.../Portable/xlf/CSharpResources.pl.xlf | 15 +
.../Portable/xlf/CSharpResources.pt-BR.xlf | 15 +
.../Portable/xlf/CSharpResources.ru.xlf | 15 +
.../Portable/xlf/CSharpResources.tr.xlf | 15 +
.../Portable/xlf/CSharpResources.zh-Hans.xlf | 15 +
.../Portable/xlf/CSharpResources.zh-Hant.xlf | 15 +
.../Test/Emit/CodeGen/CodeGenTupleTest.cs | 2 +-
.../Semantics/RefReadonlyParameterTests.cs | 6 +-
.../Semantic/Semantics/InitOnlyMemberTests.cs | 112 +--
.../Semantics/NullableReferenceTypesTests.cs | 2 +-
.../Semantic/Semantics/SemanticErrorTests.cs | 6 +
.../Test/Syntax/Diagnostics/DiagnosticTest.cs | 1 +
.../Syntax/FieldAndValueKeywordTests.cs | 792 ++++++++++++++++++
26 files changed, 1186 insertions(+), 62 deletions(-)
create mode 100644 src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index 4c09a80debc1a..72d10e94c6cfb 100644
--- a/src/Compilers/CSharp/Portable/CSharpResources.resx
+++ b/src/Compilers/CSharp/Portable/CSharpResources.resx
@@ -6865,6 +6865,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
Compiling requires binding the lambda expression many times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
Record equality contract property '{0}' must have a get accessor.
@@ -7920,6 +7926,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
ref and unsafe in async and iterator methods
+
+ field and value keywords
+
A 'ref' local cannot be preserved across 'await' or 'yield' boundary.
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index 7e2ecb2809f45..0d9fa10b758ff 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -1782,10 +1782,20 @@ syntaxNode is ConstructorDeclarationSyntax constructorSyntax &&
assertBindIdentifierTargets(inMethodBinder, identifierMap, methodBody, diagnostics);
#endif
+ var compilation = bodyBinder.Compilation;
+
+ if (method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet)
+ {
+ var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
+ if (requiredVersion > compilation.LanguageVersion)
+ {
+ ReportFieldOrValueContextualKeywordConflicts(method, methodBody, diagnostics);
+ }
+ }
+
BoundNode methodBodyForSemanticModel = methodBody;
NullableWalker.SnapshotManager? snapshotManager = null;
ImmutableDictionary? remappedSymbols = null;
- var compilation = bodyBinder.Compilation;
nullableInitialState = getInitializerState(methodBody);
@@ -2149,6 +2159,112 @@ static void assertBindIdentifierTargets(InMethodBinder? inMethodBinder, Concurre
#endif
}
+ ///
+ /// Report a diagnostic for any 'field' or 'value' identifier in the bound tree where the
+ /// meaning will change when the identifier is considered a contextual keyword.
+ ///
+ private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol method, BoundNode node, BindingDiagnosticBag diagnostics)
+ {
+ Debug.Assert(method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet);
+ Debug.Assert(method.AssociatedSymbol is PropertySymbol);
+
+ PooledHashSet? valueIdentifiers = null;
+
+ foreach (var syntax in node.Syntax.DescendantNodesAndSelf())
+ {
+ // PROTOTYPE: Handle all syntax fields with from syntax.xml.
+ switch (syntax)
+ {
+ case IdentifierNameSyntax identifierName:
+ if (isFieldOrValueInKeywordContext(method, identifierName.Identifier, out bool isValue))
+ {
+ if (isValue)
+ {
+ // Report conflicts with "value" later, after collecting all references and
+ // dropping any that refer to the implicit parameter.
+ valueIdentifiers ??= PooledHashSet.GetInstance();
+ valueIdentifiers.Add(identifierName);
+ }
+ else
+ {
+ reportConflict(identifierName, identifierName.Identifier, diagnostics);
+ }
+ }
+ break;
+ case VariableDeclaratorSyntax variableDeclarator:
+ reportConflictIfAny(method, variableDeclarator, variableDeclarator.Identifier, diagnostics);
+ break;
+ case ParameterSyntax parameter:
+ reportConflictIfAny(method, parameter, parameter.Identifier, diagnostics);
+ break;
+ }
+ }
+
+ if (valueIdentifiers is { })
+ {
+ // Remove references to the implicit "value" parameter.
+ var checker = new ValueIdentifierChecker(valueIdentifiers);
+ checker.Visit(node);
+ foreach (var identifierName in valueIdentifiers)
+ {
+ reportConflict(identifierName, identifierName.Identifier, diagnostics);
+ }
+ valueIdentifiers.Free();
+ }
+
+ static bool isFieldOrValueInKeywordContext(MethodSymbol method, SyntaxToken identifierToken, out bool isValue)
+ {
+ switch (identifierToken.Text)
+ {
+ case "field":
+ isValue = false;
+ return method.AssociatedSymbol is PropertySymbol { IsIndexer: false };
+ case "value":
+ isValue = true;
+ return method.MethodKind == MethodKind.PropertySet;
+ default:
+ isValue = false;
+ return false;
+ }
+ }
+
+ static void reportConflictIfAny(MethodSymbol method, SyntaxNode syntax, SyntaxToken identifierToken, BindingDiagnosticBag diagnostics)
+ {
+ if (isFieldOrValueInKeywordContext(method, identifierToken, out _))
+ {
+ reportConflict(syntax, identifierToken, diagnostics);
+ }
+ }
+
+ static void reportConflict(SyntaxNode syntax, SyntaxToken identifierToken, BindingDiagnosticBag diagnostics)
+ {
+ var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
+ diagnostics.Add(ErrorCode.INF_IdentifierConflictWithContextualKeyword, syntax, identifierToken.Text, requiredVersion.ToDisplayString());
+ }
+ }
+
+ private sealed class ValueIdentifierChecker : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
+ {
+ private readonly HashSet _valueIdentifiers;
+
+ public ValueIdentifierChecker(HashSet valueIdentifiers)
+ {
+ _valueIdentifiers = valueIdentifiers;
+ }
+
+ public override BoundNode? VisitParameter(BoundParameter node)
+ {
+ Debug.Assert(node.Syntax is IdentifierNameSyntax);
+
+ if (node.ParameterSymbol is SynthesizedPropertyAccessorValueParameterSymbol { Name: "value" })
+ {
+ _valueIdentifiers.Remove((IdentifierNameSyntax)node.Syntax);
+ }
+
+ return base.VisitParameter(node);
+ }
+ }
+
#if DEBUG
private static bool IsEmptyRewritePossible(BoundNode node)
{
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 4f8a380ef0913..8daaf458da47b 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -2324,6 +2324,7 @@ internal enum ErrorCode
ERR_RefStructDoesNotSupportDefaultInterfaceImplementationForMember = 9245,
ERR_BadNonVirtualInterfaceMemberAccessOnAllowsRefLike = 9246,
ERR_BadAllowByRefLikeEnumerator = 9247,
+ INF_IdentifierConflictWithContextualKeyword = 9248,
// Note: you will need to do the following after adding errors:
// 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
index 03a75fda22f79..9713ba0eb0c66 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
@@ -2450,6 +2450,7 @@ or ErrorCode.ERR_NotRefStructConstraintNotSatisfied
or ErrorCode.ERR_RefStructDoesNotSupportDefaultInterfaceImplementationForMember
or ErrorCode.ERR_BadNonVirtualInterfaceMemberAccessOnAllowsRefLike
or ErrorCode.ERR_BadAllowByRefLikeEnumerator
+ or ErrorCode.INF_IdentifierConflictWithContextualKeyword
=> false,
};
#pragma warning restore CS8524 // The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value.
diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
index 18fa9dbb51d6e..b3099660645db 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs
@@ -286,6 +286,7 @@ internal enum MessageID
IDS_FeatureRefUnsafeInIteratorAsync = MessageBase + 12843,
IDS_FeatureRefStructInterfaces = MessageBase + 12844,
+ IDS_FeatureFieldAndValueKeywords = MessageBase + 12845,
}
// Message IDs may refer to strings that need to be localized.
@@ -472,6 +473,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
case MessageID.IDS_FeatureParamsCollections:
case MessageID.IDS_FeatureRefUnsafeInIteratorAsync:
case MessageID.IDS_FeatureRefStructInterfaces:
+ case MessageID.IDS_FeatureFieldAndValueKeywords:
return LanguageVersion.Preview;
// C# 12.0 features.
diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs
index ac6ebf95db21f..e10144fe3f074 100644
--- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs
+++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs
@@ -371,6 +371,7 @@ public static bool IsInfo(ErrorCode code)
{
case ErrorCode.INF_UnableToLoadSomeTypesInAnalyzer:
case ErrorCode.INF_TooManyBoundLambdas:
+ case ErrorCode.INF_IdentifierConflictWithContextualKeyword:
return true;
default:
return false;
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
index 482f74b8c1b7e..c9348a2c287ad 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf
@@ -2307,6 +2307,11 @@
vzory rozšířených vlastností
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
obor názvů pro celý soubor
@@ -2532,6 +2537,16 @@
ukazatel
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
index 458820646f0bd..ed826a4ca94a6 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf
@@ -2307,6 +2307,11 @@
Muster für erweiterte Eigenschaften
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
Dateibereichsnamespace
@@ -2532,6 +2537,16 @@
Zeiger
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
index de96942b43ca1..48356b3a04f4f 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf
@@ -2307,6 +2307,11 @@
patrones de propiedad extendidos
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
espacio de nombres con ámbito de archivo
@@ -2532,6 +2537,16 @@
puntero
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
index cd8e3b4571564..2770ff7ea285e 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf
@@ -2307,6 +2307,11 @@
modèles de propriétés étendues
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
espace de noms inclus dans l'étendue de fichier
@@ -2532,6 +2537,16 @@
aiguille
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
index ee6c972ccf03d..c5f084d6d0099 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf
@@ -2307,6 +2307,11 @@
criteri di proprietà estesa
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
spazio dei nomi con ambito file
@@ -2532,6 +2537,16 @@
indicatore di misura
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
index 049964d81ce3a..b681c9a895d3f 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf
@@ -2307,6 +2307,11 @@
拡張プロパティ パターン
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
ファイルスコープの名前空間
@@ -2532,6 +2537,16 @@
ポインター
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
index dd8ef848b9a66..25054ed493fc4 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf
@@ -2307,6 +2307,11 @@
확장 속성 패턴
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
파일 범위 네임스페이스
@@ -2532,6 +2537,16 @@
포인터
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
index 871593fc5cad5..43d9efb1c2a46 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf
@@ -2307,6 +2307,11 @@
wzorce właściwości rozszerzonych
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
przestrzeń nazw z określonym zakresem plików
@@ -2532,6 +2537,16 @@
wskaźnik
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
index a4f21ff34b491..83d2a64901975 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf
@@ -2307,6 +2307,11 @@
padrões de propriedade estendida
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
namespace de escopo de arquivo
@@ -2532,6 +2537,16 @@
ponteiro
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
index 7bc750767181d..74554ad134ed4 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf
@@ -2307,6 +2307,11 @@
шаблоны расширенных свойств
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
пространство имен с файловой областью
@@ -2532,6 +2537,16 @@
указатель
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
index 61a78dded475d..5190b4fd27b50 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf
@@ -2307,6 +2307,11 @@
genişletilmiş özellik desenleri
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
dosya kapsamlı ad alanı
@@ -2532,6 +2537,16 @@
işaretçi
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
index b0175426fa302..c79689a06316e 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf
@@ -2307,6 +2307,11 @@
扩展的属性模式
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
文件范围内的命名空间
@@ -2532,6 +2537,16 @@
指针
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
index 59932f5945760..1c4006927d78c 100644
--- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
+++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf
@@ -2307,6 +2307,11 @@
擴充屬性模式
+
+ field and value keywords
+ field and value keywords
+
+
file-scoped namespace
以檔案為範圍的命名空間
@@ -2532,6 +2537,16 @@
指標
+
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+ '{0}' is a contextual keyword, with a specific meaning, starting in language version {1}. Use '@{0}' to avoid a breaking change when compiling with language version {1} or later.
+
+
+
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+ Identifier is a contextual keyword, with a specific meaning, in a later language version.
+
+
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
Compiling requires binding the lambda expression at least {0} times. Consider declaring the lambda expression with explicit parameter types, or if the containing method call is generic, consider using explicit type arguments.
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
index 7f3182aab7847..539832e7e1a82 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
@@ -3918,7 +3918,7 @@ int P
set
{
var t = (M(), value);
- System.Console.Write(t.value);
+ System.Console.Write(t.@value);
}
}
}
diff --git a/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs b/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs
index 444acde22d8ec..de5623dc4d134 100644
--- a/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs
+++ b/src/Compilers/CSharp/Test/Emit2/Semantics/RefReadonlyParameterTests.cs
@@ -176,7 +176,7 @@ void M4([RequiresLocation] int p) { }
[return: RequiresLocation] ref readonly int M7() => throw null;
[RequiresLocation] void M8() { }
[RequiresLocation] public int field;
- [RequiresLocation] int Property { get => field; set => field = value; }
+ [RequiresLocation] int Property { get => @field; set => @field = value; }
}
""";
@@ -215,7 +215,7 @@ [RequiresLocation] void M8() { }
// [RequiresLocation] public int field;
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(12, 6),
// 0.cs(13,6): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage.
- // [RequiresLocation] int Property { get => field; set => field = value; }
+ // [RequiresLocation] int Property { get => @field; set => @field = value; }
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(13, 6));
var expectedDiagnostics = new[]
@@ -251,7 +251,7 @@ [RequiresLocation] void M8() { }
// [RequiresLocation] public int field;
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(12, 6),
// 0.cs(13,6): error CS8335: Do not use 'System.Runtime.CompilerServices.RequiresLocationAttribute'. This is reserved for compiler usage.
- // [RequiresLocation] int Property { get => field; set => field = value; }
+ // [RequiresLocation] int Property { get => @field; set => @field = value; }
Diagnostic(ErrorCode.ERR_ExplicitReservedAttr, "RequiresLocation").WithArguments("System.Runtime.CompilerServices.RequiresLocationAttribute").WithLocation(13, 6)
};
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs
index a361c72286cc8..2b262e99295e7 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/InitOnlyMemberTests.cs
@@ -2638,19 +2638,19 @@ public int InitOnlyProperty1
{
init
{
- field = null;
+ @field = null;
}
}
public int RegularProperty
{
get
{
- field = null; // 3
+ @field = null; // 3
throw null;
}
set
{
- field = null; // 4
+ @field = null; // 4
}
}
}
@@ -2668,34 +2668,34 @@ public int InitOnlyProperty2
{
init
{
- field = null; // 7
+ @field = null; // 7
}
}
}
";
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics(
- // (11,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the class in which the field is defined or a variable initializer))
+ // 0.cs(11,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// field = null; // 1
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(11, 9),
- // (12,23): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // 0.cs(12,23): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// _ = new C() { field = null }; // 2
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(12, 23),
- // (25,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
- // field = null; // 3
- Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(25, 13),
- // (30,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
- // field = null; // 4
- Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(30, 13),
- // (38,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // 0.cs(25,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // @field = null; // 3
+ Diagnostic(ErrorCode.ERR_AssgReadonly, "@field").WithLocation(25, 13),
+ // 0.cs(30,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // @field = null; // 4
+ Diagnostic(ErrorCode.ERR_AssgReadonly, "@field").WithLocation(30, 13),
+ // 0.cs(38,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// field = null; // 5
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(38, 9),
- // (42,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // 0.cs(42,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// field = null; // 6
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(42, 9),
- // (48,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
- // field = null; // 7
- Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(48, 13)
+ // 0.cs(48,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // @field = null; // 7
+ Diagnostic(ErrorCode.ERR_AssgReadonly, "@field").WithLocation(48, 13)
);
}
@@ -2724,7 +2724,7 @@ public int Property
{
init
{
- field = value;
+ @field = value;
}
}
}
@@ -2838,7 +2838,7 @@ public string InitOnlyProperty
{
init
{
- c.field = null; // 2
+ c.@field = null; // 2
}
}
}
@@ -2853,7 +2853,7 @@ public string InitOnlyProperty2
{
init
{
- c.field = null; // 4
+ c.@field = null; // 4
}
}
}
@@ -2871,22 +2871,22 @@ void M(C c)
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics(
- // (9,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the class in which the field is defined or a variable initializer))
+ // 0.cs(9,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// c.field = null; // 1
Diagnostic(ErrorCode.ERR_AssgReadonly, "c.field").WithLocation(9, 9),
- // (16,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
- // c.field = null; // 2
- Diagnostic(ErrorCode.ERR_AssgReadonly, "c.field").WithLocation(16, 13),
- // (24,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // 0.cs(16,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // c.@field = null; // 2
+ Diagnostic(ErrorCode.ERR_AssgReadonly, "c.@field").WithLocation(16, 13),
+ // 0.cs(24,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// c.field = null; // 3
Diagnostic(ErrorCode.ERR_AssgReadonly, "c.field").WithLocation(24, 9),
- // (31,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
- // c.field = null; // 4
- Diagnostic(ErrorCode.ERR_AssgReadonly, "c.field").WithLocation(31, 13),
- // (40,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // 0.cs(31,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // c.@field = null; // 4
+ Diagnostic(ErrorCode.ERR_AssgReadonly, "c.@field").WithLocation(31, 13),
+ // 0.cs(40,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// field = // 5
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(40, 13),
- // (41,18): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
+ // 0.cs(41,18): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// (c.field = null) // 6
Diagnostic(ErrorCode.ERR_AssgReadonly, "c.field").WithLocation(41, 18)
);
@@ -2915,19 +2915,19 @@ public int InitOnlyProperty1
{
init
{
- field.content = null;
+ @field.content = null;
}
}
public int RegularProperty
{
get
{
- field.content = null; // 2
+ @field.content = null; // 2
throw null;
}
set
{
- field.content = null; // 3
+ @field.content = null; // 3
}
}
}
@@ -2945,31 +2945,31 @@ public int InitOnlyProperty2
{
init
{
- field.content = null; // 6
+ @field.content = null; // 6
}
}
}
";
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics(
- // (15,9): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor, an init-only member or a variable initializer)
+ // 0.cs(15,9): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor or a variable initializer)
// field.content = null; // 1
Diagnostic(ErrorCode.ERR_AssgReadonly2, "field.content").WithArguments("C.field").WithLocation(15, 9),
- // (28,13): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor, an init-only member or a variable initializer)
- // field.content = null; // 2
- Diagnostic(ErrorCode.ERR_AssgReadonly2, "field.content").WithArguments("C.field").WithLocation(28, 13),
- // (33,13): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor, an init-only member or a variable initializer)
- // field.content = null; // 3
- Diagnostic(ErrorCode.ERR_AssgReadonly2, "field.content").WithArguments("C.field").WithLocation(33, 13),
- // (41,9): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor, an init-only member or a variable initializer)
+ // 0.cs(28,13): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor or a variable initializer)
+ // @field.content = null; // 2
+ Diagnostic(ErrorCode.ERR_AssgReadonly2, "@field.content").WithArguments("C.field").WithLocation(28, 13),
+ // 0.cs(33,13): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor or a variable initializer)
+ // @field.content = null; // 3
+ Diagnostic(ErrorCode.ERR_AssgReadonly2, "@field.content").WithArguments("C.field").WithLocation(33, 13),
+ // 0.cs(41,9): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor or a variable initializer)
// field.content = null; // 4
Diagnostic(ErrorCode.ERR_AssgReadonly2, "field.content").WithArguments("C.field").WithLocation(41, 9),
- // (45,9): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor, an init-only member or a variable initializer)
+ // 0.cs(45,9): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor or a variable initializer)
// field.content = null; // 5
Diagnostic(ErrorCode.ERR_AssgReadonly2, "field.content").WithArguments("C.field").WithLocation(45, 9),
- // (51,13): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor, an init-only member or a variable initializer)
- // field.content = null; // 6
- Diagnostic(ErrorCode.ERR_AssgReadonly2, "field.content").WithArguments("C.field").WithLocation(51, 13)
+ // 0.cs(51,13): error CS1648: Members of readonly field 'C.field' cannot be modified (except in a constructor or a variable initializer)
+ // @field.content = null; // 6
+ Diagnostic(ErrorCode.ERR_AssgReadonly2, "@field.content").WithArguments("C.field").WithLocation(51, 13)
);
}
@@ -2990,7 +2990,7 @@ public int InitOnlyProperty1
{
init
{
- field.content = value;
+ @field.content = value;
System.Console.Write(""RAN "");
}
}
@@ -3024,19 +3024,19 @@ public static int InitOnlyProperty1
{
init
{
- field.content = value;
+ @field.content = value;
}
}
}
";
var comp = CreateCompilation(new[] { source, IsExternalInitTypeDefinition }, parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics(
- // (13,9): error CS8856: The 'init' accessor is not valid on static members
+ // 0.cs(13,9): error CS8856: The 'init' accessor is not valid on static members
// init
Diagnostic(ErrorCode.ERR_BadInitAccessor, "init").WithLocation(13, 9),
- // (15,13): error CS1650: Fields of static readonly field 'C.field' cannot be assigned to (except in a static constructor or a variable initializer)
- // field.content = value;
- Diagnostic(ErrorCode.ERR_AssgReadonlyStatic2, "field.content").WithArguments("C.field").WithLocation(15, 13)
+ // 0.cs(15,13): error CS1650: Fields of static readonly field 'C.field' cannot be assigned to (except in a static constructor or a variable initializer)
+ // @field.content = value;
+ Diagnostic(ErrorCode.ERR_AssgReadonlyStatic2, "@field.content").WithArguments("C.field").WithLocation(15, 13)
);
}
@@ -3072,7 +3072,7 @@ public int InitOnlyProperty2
{
init
{
- field = null; // 5
+ @field = null; // 5
}
}
}
@@ -3081,7 +3081,7 @@ public int InitOnlyProperty2
references: new[] { emitAsImage ? libComp.EmitToImageReference() : libComp.ToMetadataReference() },
parseOptions: TestOptions.Regular9);
comp.VerifyEmitDiagnostics(
- // (6,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the class in which the field is defined or a variable initializer))
+ // (6,9): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
// field = null; // 1
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(6, 9),
// (7,23): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
@@ -3094,8 +3094,8 @@ public int InitOnlyProperty2
// _ = new C() { field = null }; // 4
Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(13, 23),
// (20,13): error CS0191: A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initializer)
- // field = null; // 5
- Diagnostic(ErrorCode.ERR_AssgReadonly, "field").WithLocation(20, 13)
+ // @field = null; // 5
+ Diagnostic(ErrorCode.ERR_AssgReadonly, "@field").WithLocation(20, 13)
);
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
index 11f632233060e..acc45c67ba330 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NullableReferenceTypesTests.cs
@@ -21666,7 +21666,7 @@ public override int Init
{
get
{
- field = """";
+ @field = """";
return 0;
}
}
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs
index d361b612ede78..6ed56ad462451 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs
@@ -4010,6 +4010,12 @@ static void N(int q)
// (24,17): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// int value = 0; // CS0136
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(24, 17),
+ // (24,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // int value = 0; // CS0136
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 0").WithArguments("value", "preview").WithLocation(24, 17),
+ // (25,15): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // M(value);
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(25, 15),
// (30,35): error CS0136: A local or parameter named 'q' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// System.Func f = q=>q; // 0136
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "q").WithArguments("q").WithLocation(30, 35));
diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs
index 9f5490d05adac..b0970fc5add62 100644
--- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs
@@ -434,6 +434,7 @@ public void WarningLevel_2()
case ErrorCode.WRN_DynamicDispatchToParamsCollectionIndexer:
case ErrorCode.WRN_DynamicDispatchToParamsCollectionConstructor:
case ErrorCode.INF_TooManyBoundLambdas:
+ case ErrorCode.INF_IdentifierConflictWithContextualKeyword:
Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode));
break;
case ErrorCode.WRN_InvalidVersionFormat:
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
new file mode 100644
index 0000000000000..d0e0cde881d39
--- /dev/null
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -0,0 +1,792 @@
+// 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
+{
+ public class FieldAndValueKeywordTests : CSharpTestBase
+ {
+ [Theory]
+ [CombinatorialData]
+ public void Field_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@field" : "field";
+ string source = $$"""
+ class A { public static int field; }
+ class B1 : A { int _f = {{identifier}}; }
+ class B2 : A { object F() => {{identifier}}; }
+ class C1 : A { object P => {{identifier}}; }
+ class C2 : A { object P { get => {{identifier}}; } }
+ class C3 : A { object P { get { return {{identifier}}; } } }
+ class C4 : A { object P { set { {{identifier}} = 0; } } }
+ class C5 : A { object P { get; set; } = {{identifier}}; }
+ class D1 : A { object this[int i] => {{identifier}}; }
+ class D2 : A { object this[int i] { get => {{identifier}}; } }
+ class D3 : A { object this[int i] { get { return {{identifier}}; } } }
+ class D4 : A { object this[int i] { set { {{identifier}} = 0; } } }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,28): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // class C1 : A { object P => field; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 28),
+ // (5,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // class C2 : A { object P { get => field; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(5, 34),
+ // (6,40): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // class C3 : A { object P { get { return field; } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(6, 40),
+ // (7,33): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // class C4 : A { object P { set { field = 0; } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(7, 33));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Value_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ #pragma warning disable 649
+ class A { public static int value; }
+ class B1 : A { int _f = {{identifier}}; }
+ class B2 : A { object F() => {{identifier}}; }
+ class C1 : A { object P => {{identifier}}; }
+ class C2 : A { object P { get => {{identifier}}; } }
+ class C3 : A { object P { get { return {{identifier}}; } } }
+ class C4 : A { object P { set { {{identifier}} = 0; } } }
+ class C5 : A { object P { get; set; } = {{identifier}}; }
+ class D1 : A { object this[int i] => {{identifier}}; }
+ class D2 : A { object this[int i] { get => {{identifier}}; } }
+ class D3 : A { object this[int i] { get { return {{identifier}}; } } }
+ class D4 : A { object this[int i] { set { {{identifier}} = 0; } } }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ comp.VerifyEmitDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Value_02(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ #pragma warning disable 649
+ class A { public int value; }
+ class C1 : A { object P => this.{{identifier}}; }
+ class C2 : A { object P { get => this.{{identifier}}; } }
+ class C3 : A { object P { get { return this.{{identifier}}; } } }
+ class C4 : A { object P { set { this.{{identifier}} = 0; } } }
+ class D1 : A { object this[int i] => this.{{identifier}}; }
+ class D2 : A { object this[int i] { get => this.{{identifier}}; } }
+ class D3 : A { object this[int i] { get { return this.{{identifier}}; } } }
+ class D4 : A { object this[int i] { set { this.{{identifier}} = 0; } } }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,38): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // class C4 : A { object P { set { this.value = 0; } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 38),
+ // (10,48): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // class D4 : A { object this[int i] { set { this.value = 0; } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(10, 48));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Value_03(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ class A
+ {
+ object P { get { return null; } set { _ = {{identifier}}; } }
+ object this[int i] { get { return null; } set { _ = {{identifier}}; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ comp.VerifyEmitDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Keyword_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ [CombinatorialValues("field", "value")] string identifier,
+ bool escapeIdentifier)
+ {
+ string source = $$"""
+ namespace A.{{identifier}}.B
+ {
+ class C { }
+ }
+ class D
+ {
+ object P { set { _ = new A.{{(escapeIdentifier ? "@" : "") + identifier}}.B.C(); } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (7,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P { set { _ = new A.field.B.C(); } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, identifier).WithArguments(identifier, "preview").WithLocation(7, 32));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Keyword_02(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ [CombinatorialValues("field", "value")] string identifier,
+ bool escapeIdentifier)
+ {
+ string source = $$"""
+ #pragma warning disable 649
+ class C
+ {
+ static object {{identifier}};
+ static object P1 { set { _ = C.{{(escapeIdentifier ? "@" : "") + identifier}}; } }
+ object P2 { init { _ = C.{{(escapeIdentifier ? "@" : "") + identifier}}; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), targetFramework: TargetFramework.Net70);
+ if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,36): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // static object P1 { set { _ = C.field; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, identifier).WithArguments(identifier, "preview").WithLocation(5, 36),
+ // (6,30): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P2 { init { _ = C.field; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, identifier).WithArguments(identifier, "preview").WithLocation(6, 30));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Keyword_03(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 649
+ class C
+ {
+ object field;
+ object value;
+ object P
+ {
+ set
+ {
+ _ = nameof(field);
+ _ = nameof(@field);
+ _ = nameof(this.value);
+ _ = nameof(this.@value);
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (10,24): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // _ = nameof(field);
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 24),
+ // (12,29): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // _ = nameof(this.value);
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(12, 29));
+ }
+ }
+
+ [Fact]
+ public void Parameter_01()
+ {
+ string source = """
+ class A
+ {
+ object this[int field]
+ {
+ get { return field; }
+ set { _ = field; }
+ }
+ }
+ class B
+ {
+ object this[int @field]
+ {
+ get { return @field; }
+ set { _ = @field; }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ // No diagnostics expected for field in indexers.
+ comp.VerifyEmitDiagnostics();
+ }
+
+ [Fact]
+ public void Parameter_02()
+ {
+ string source = """
+ class A
+ {
+ object this[int value]
+ {
+ get { return value; }
+ set { _ = value; }
+ }
+ }
+ class B
+ {
+ object this[int @value]
+ {
+ get { return @value; }
+ set { _ = @value; }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (3,21): error CS0316: The parameter name 'value' conflicts with an automatically-generated parameter name
+ // object this[int value]
+ Diagnostic(ErrorCode.ERR_DuplicateGeneratedName, "value").WithArguments("value").WithLocation(3, 21),
+ // (6,19): error CS0229: Ambiguity between 'int value' and 'object value'
+ // set { _ = value; }
+ Diagnostic(ErrorCode.ERR_AmbigMember, "value").WithArguments("int value", "object value").WithLocation(6, 19),
+ // (6,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // set { _ = value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 19),
+ // (11,21): error CS0316: The parameter name 'value' conflicts with an automatically-generated parameter name
+ // object this[int @value]
+ Diagnostic(ErrorCode.ERR_DuplicateGeneratedName, "@value").WithArguments("value").WithLocation(11, 21),
+ // (14,19): error CS0229: Ambiguity between 'int value' and 'object value'
+ // set { _ = @value; }
+ Diagnostic(ErrorCode.ERR_AmbigMember, "@value").WithArguments("int value", "object value").WithLocation(14, 19));
+ }
+
+ [Fact]
+ public void Local_01()
+ {
+ string source = """
+ class C
+ {
+ static object P
+ {
+ get { int field = 1; return field; }
+ }
+ static object Q
+ {
+ get { int @field = 3; return @field; }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (5,19): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // get { int field = 1; return field; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(5, 19),
+ // (5,37): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // get { int field = 1; return field; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(5, 37));
+ }
+
+ [Fact]
+ public void Local_02()
+ {
+ string source = """
+ class C
+ {
+ static object P
+ {
+ set { int value = 2; _ = value; }
+ }
+ static object Q
+ {
+ set { int @value = 4; _ = @value; }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (5,19): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // set { int value = 2; _ = value; }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(5, 19),
+ // (5,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // set { int value = 2; _ = value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 2").WithArguments("value", "preview").WithLocation(5, 19),
+ // (5,34): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // set { int value = 2; _ = value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(5, 34),
+ // (9,19): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // set { int @value = 4; _ = @value; }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(9, 19));
+ }
+
+ // PROTOTYPE: Confirm field and value should not be contextual keywords in event accessors.
+ [Theory]
+ [CombinatorialData]
+ public void Event_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = $$"""
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ static object field;
+ static object value;
+ event EventHandler E1
+ {
+ add { _ = field ?? @field; }
+ remove { _ = @field ?? field; }
+ }
+ event EventHandler E2
+ {
+ add { _ = C.value ?? C.@value; }
+ remove { _ = C.@value ?? C.value; }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ comp.VerifyEmitDiagnostics();
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Lambda_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ static object field;
+ static object value;
+ object P
+ {
+ set
+ {
+ Func f;
+ f = () => field;
+ f = () => @field;
+ f = () => C.field;
+ f = () => C.@field;
+ f = () => value;
+ f = () => C.value;
+ f = () => @value;
+ f = () => C.@value;
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (12,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(12, 23),
+ // (14,25): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => C.field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(14, 25),
+ // (17,25): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => C.value;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 25));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void LocalFunction_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 649, 8321
+ class C
+ {
+ static object field;
+ static object value;
+ object P
+ {
+ set
+ {
+ object F1() => field;
+ object F2() => @field;
+ object F3() => C.field;
+ object F4() => C.@field;
+ object G1() { return value; }
+ object G2() { return C.value; }
+ object G3() { return @value; }
+ object G4() { return C.@value; }
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (10,28): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1() => field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 28),
+ // (12,30): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F3() => C.field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(12, 30),
+ // (15,36): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object G2() { return C.value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(15, 36));
+ }
+ }
+
+ [Fact]
+ public void Lambda_Local_01()
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ object P
+ {
+ get
+ {
+ Func f;
+ f = () => { object field = 1; return field; };
+ f = () => { object @field = 2; return @field; };
+ return null;
+ }
+ set
+ {
+ Func f;
+ f = () => { object value = 1; return value; };
+ f = () => { object @value = 2; return @value; };
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (10,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => { object field = 1; return field; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(10, 32),
+ // (10,50): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => { object field = 1; return field; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 50),
+ // (17,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => { object value = 1; return value; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(17, 32),
+ // (17,50): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // f = () => { object value = 1; return value; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 50));
+ }
+
+ [Fact]
+ public void Lambda_Local_02()
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ object P
+ {
+ get
+ {
+ Action a;
+ a = () => { object field = 1; };
+ a = () => { object @field = 2; };
+ return null;
+ }
+ set
+ {
+ Action a;
+ a = () => { object value = 1; };
+ a = () => { object @value = 2; };
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (10,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // a = () => { object field = 1; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(10, 32),
+ // (17,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // a = () => { object value = 1; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(17, 32));
+ }
+
+ [Fact]
+ public void Lambda_Parameter_01()
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ object P
+ {
+ get
+ {
+ Func f;
+ f = field => field;
+ f = @field => @field;
+ return null;
+ }
+ set
+ {
+ Func f;
+ f = value => value;
+ f = @value => @value;
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (10,17): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // f = field => field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 17),
+ // (10,26): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // f = field => field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 26),
+ // (17,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // f = value => value;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 17),
+ // (17,26): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // f = value => value;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 26));
+ }
+
+ [Fact]
+ public void Lambda_Parameter_02()
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ object P
+ {
+ get
+ {
+ Action a;
+ a = field => { };
+ a = @field => { };
+ return null;
+ }
+ set
+ {
+ Action a;
+ a = value => { };
+ a = @value => { };
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (10,17): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // a = field => { };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 17),
+ // (17,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // a = value => { };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 17));
+ }
+
+ [Fact]
+ public void LocalFunction_Local_01()
+ {
+ string source = """
+ #pragma warning disable 649, 8321
+ class C
+ {
+ object P
+ {
+ get
+ {
+ object F1() { object field = 1; return field; };
+ object F2() { object @field = 2; return @field; };
+ return null;
+ }
+ set
+ {
+ object G1() { object value = 1; return value; };
+ object G2() { object @value = 2; return @value; };
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (8,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1() { object field = 1; return field; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(8, 34),
+ // (8,52): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1() { object field = 1; return field; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(8, 52),
+ // (14,34): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object G1() { object value = 1; return value; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(14, 34),
+ // (14,52): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object G1() { object value = 1; return value; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(14, 52));
+ }
+
+ [Fact]
+ public void LocalFunction_Local_02()
+ {
+ string source = """
+ #pragma warning disable 649, 8321
+ class C
+ {
+ object P
+ {
+ get
+ {
+ void F1() { object field = 1; }
+ void F2() { object @field = 1; }
+ return null;
+ }
+ set
+ {
+ void G1() { object value = 1; }
+ void G2() { object @value = 1; }
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (8,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // void F1() { object field = 1; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(8, 32),
+ // (14,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // void G1() { object value = 1; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(14, 32));
+ }
+
+ [Fact]
+ public void LocalFunction_Parameter_01()
+ {
+ string source = """
+ #pragma warning disable 649, 8321
+ class C
+ {
+ object P
+ {
+ get
+ {
+ object F1(object field) => field;
+ object F2(object @field) => @field;
+ return null;
+ }
+ set
+ {
+ object G1(object value) => value;
+ object G2(object @value) => @value;
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (8,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1(object field) => field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(8, 23),
+ // (8,40): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1(object field) => field;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(8, 40),
+ // (14,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object G1(object value) => value;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(14, 23),
+ // (14,40): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object G1(object value) => value;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(14, 40));
+ }
+
+ [Fact]
+ public void LocalFunction_Parameter_02()
+ {
+ string source = """
+ #pragma warning disable 649, 8321
+ class C
+ {
+ object P
+ {
+ get
+ {
+ void F1(object field) { }
+ void F2(object @field) { }
+ return null;
+ }
+ set
+ {
+ void G1(object value) { }
+ void G2(object @value) { }
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (8,21): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // void F1(object field) { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(8, 21),
+ // (14,21): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // void G1(object value) { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(14, 21));
+ }
+ }
+}
From b5be7dcd9aa147dfd22226c4eed72f612f25b2e7 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Mon, 20 May 2024 22:05:49 -0700
Subject: [PATCH 02/15] Handle other identifiers
---
.../Portable/Compiler/MethodCompiler.cs | 103 +-
.../Syntax/FieldAndValueKeywordTests.cs | 929 +++++++++++++-----
2 files changed, 740 insertions(+), 292 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index 0d9fa10b758ff..4e0f321f22103 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -2168,34 +2168,58 @@ private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol me
Debug.Assert(method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet);
Debug.Assert(method.AssociatedSymbol is PropertySymbol);
- PooledHashSet? valueIdentifiers = null;
+ PooledDictionary? valueIdentifiers = null;
- foreach (var syntax in node.Syntax.DescendantNodesAndSelf())
+ foreach (var token in node.Syntax.DescendantTokens())
{
- // PROTOTYPE: Handle all syntax fields with from syntax.xml.
+ Debug.Assert(token.Parent is { });
+ if (token.Kind() != SyntaxKind.IdentifierToken)
+ {
+ continue;
+ }
+ var syntax = token.Parent;
switch (syntax)
{
- case IdentifierNameSyntax identifierName:
- if (isFieldOrValueInKeywordContext(method, identifierName.Identifier, out bool isValue))
+ case IdentifierNameSyntax identifierName when identifierName.Identifier == token:
+ case GenericNameSyntax genericName when genericName.Identifier == token:
+ case TupleElementSyntax tupleElement when tupleElement.Identifier == token:
+ case FromClauseSyntax fromClause when fromClause.Identifier == token:
+ case LetClauseSyntax letClause when letClause.Identifier == token:
+ case JoinClauseSyntax joinClause when joinClause.Identifier == token:
+ case JoinIntoClauseSyntax joinIntoClause when joinIntoClause.Identifier == token:
+ case QueryContinuationSyntax queryContinuation when queryContinuation.Identifier == token:
+ case LocalFunctionStatementSyntax localFunctionStatement when localFunctionStatement.Identifier == token:
+ case VariableDeclaratorSyntax variableDeclarator when variableDeclarator.Identifier == token:
+ case SingleVariableDesignationSyntax singleVariable when singleVariable.Identifier == token:
+ case LabeledStatementSyntax labeledStatement when labeledStatement.Identifier == token:
+ case ForEachStatementSyntax forEachStatement when forEachStatement.Identifier == token:
+ case CatchDeclarationSyntax catchDeclaration when catchDeclaration.Identifier == token:
+ case TypeParameterSyntax typeParameter when typeParameter.Identifier == token:
+ case ParameterSyntax parameter when parameter.Identifier == token:
+ switch (token.Text)
{
- if (isValue)
- {
- // Report conflicts with "value" later, after collecting all references and
- // dropping any that refer to the implicit parameter.
- valueIdentifiers ??= PooledHashSet.GetInstance();
- valueIdentifiers.Add(identifierName);
- }
- else
- {
- reportConflict(identifierName, identifierName.Identifier, diagnostics);
- }
+ case "field":
+ if (method.AssociatedSymbol is PropertySymbol { IsIndexer: false })
+ {
+ // Report "field" conflict with keyword.
+ reportConflict(syntax, token, diagnostics);
+ }
+ break;
+ case "value":
+ if (method.MethodKind == MethodKind.PropertySet)
+ {
+ // Record the potential "value" conflict, and report conflicts later,
+ // after dropping any that refer to the implicit parameter.
+ valueIdentifiers ??= PooledDictionary.GetInstance();
+ valueIdentifiers.Add(syntax, token);
+ }
+ break;
}
break;
- case VariableDeclaratorSyntax variableDeclarator:
- reportConflictIfAny(method, variableDeclarator, variableDeclarator.Identifier, diagnostics);
- break;
- case ParameterSyntax parameter:
- reportConflictIfAny(method, parameter, parameter.Identifier, diagnostics);
+ default:
+ // If we reach here, add the unhandled identifier case to the
+ // switch cases above (and test in FieldAndValueKeywordTests).
+ Debug.Assert(false, $"Unhandled identifier: parent {syntax.Kind()}, token {token}");
break;
}
}
@@ -2205,37 +2229,14 @@ private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol me
// Remove references to the implicit "value" parameter.
var checker = new ValueIdentifierChecker(valueIdentifiers);
checker.Visit(node);
- foreach (var identifierName in valueIdentifiers)
+ // Report "value" conflicts.
+ foreach (var pair in valueIdentifiers)
{
- reportConflict(identifierName, identifierName.Identifier, diagnostics);
+ reportConflict(pair.Key, pair.Value, diagnostics);
}
valueIdentifiers.Free();
}
- static bool isFieldOrValueInKeywordContext(MethodSymbol method, SyntaxToken identifierToken, out bool isValue)
- {
- switch (identifierToken.Text)
- {
- case "field":
- isValue = false;
- return method.AssociatedSymbol is PropertySymbol { IsIndexer: false };
- case "value":
- isValue = true;
- return method.MethodKind == MethodKind.PropertySet;
- default:
- isValue = false;
- return false;
- }
- }
-
- static void reportConflictIfAny(MethodSymbol method, SyntaxNode syntax, SyntaxToken identifierToken, BindingDiagnosticBag diagnostics)
- {
- if (isFieldOrValueInKeywordContext(method, identifierToken, out _))
- {
- reportConflict(syntax, identifierToken, diagnostics);
- }
- }
-
static void reportConflict(SyntaxNode syntax, SyntaxToken identifierToken, BindingDiagnosticBag diagnostics)
{
var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
@@ -2245,20 +2246,18 @@ static void reportConflict(SyntaxNode syntax, SyntaxToken identifierToken, Bindi
private sealed class ValueIdentifierChecker : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
{
- private readonly HashSet _valueIdentifiers;
+ private readonly Dictionary _valueIdentifiers;
- public ValueIdentifierChecker(HashSet valueIdentifiers)
+ public ValueIdentifierChecker(Dictionary valueIdentifiers)
{
_valueIdentifiers = valueIdentifiers;
}
public override BoundNode? VisitParameter(BoundParameter node)
{
- Debug.Assert(node.Syntax is IdentifierNameSyntax);
-
if (node.ParameterSymbol is SynthesizedPropertyAccessorValueParameterSymbol { Name: "value" })
{
- _valueIdentifiers.Remove((IdentifierNameSyntax)node.Syntax);
+ _valueIdentifiers.Remove(node.Syntax);
}
return base.VisitParameter(node);
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index d0e0cde881d39..1c8a150b23602 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -306,91 +306,702 @@ object this[int @value]
Diagnostic(ErrorCode.ERR_AmbigMember, "@value").WithArguments("int value", "object value").WithLocation(14, 19));
}
- [Fact]
- public void Local_01()
+ [Theory]
+ [CombinatorialData]
+ public void Event_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
{
- string source = """
+ string source = $$"""
+ #pragma warning disable 649
+ using System;
class C
{
- static object P
+ static object field;
+ static object value;
+ event EventHandler E1
{
- get { int field = 1; return field; }
+ add { _ = field ?? @field; }
+ remove { _ = @field ?? field; }
}
- static object Q
+ event EventHandler E2
{
- get { int @field = 3; return @field; }
+ add { _ = C.value ?? C.@value; }
+ remove { _ = C.@value ?? C.value; }
}
}
""";
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
- comp.VerifyEmitDiagnostics(
- // (5,19): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // get { int field = 1; return field; }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(5, 19),
- // (5,37): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // get { int field = 1; return field; }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(5, 37));
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ comp.VerifyEmitDiagnostics();
}
- [Fact]
- public void Local_02()
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_IdentifierNameSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
{
string source = """
+ #pragma warning disable 8981
+ class field { }
+ class value { }
class C
{
- static object P
- {
- set { int value = 2; _ = value; }
- }
- static object Q
- {
- set { int @value = 4; _ = @value; }
- }
+ object P1 { get { return new field(); } }
+ object P2 { get { return new @field(); } }
+ object P3 { set { _ = new value(); } }
+ object P4 { set { _ = new @value(); } }
}
""";
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
- comp.VerifyEmitDiagnostics(
- // (5,19): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
- // set { int value = 2; _ = value; }
- Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(5, 19),
- // (5,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // set { int value = 2; _ = value; }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 2").WithArguments("value", "preview").WithLocation(5, 19),
- // (5,34): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // set { int value = 2; _ = value; }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(5, 34),
- // (9,19): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
- // set { int @value = 4; _ = @value; }
- Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(9, 19));
- }
-
- // PROTOTYPE: Confirm field and value should not be contextual keywords in event accessors.
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { return new field(); } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(6, 34),
+ // (8,31): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = new value(); } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(8, 31));
+ }
+ }
+
[Theory]
[CombinatorialData]
- public void Event_01(
+ public void IdentifierToken_GenericNameSyntax(
[CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
{
- string source = $$"""
- #pragma warning disable 649
+ string source = """
+ #pragma warning disable 8981
+ class field { }
+ class value { }
+ class C
+ {
+ object P1 { get { return new field(); } }
+ object P2 { get { return new @field(); } }
+ object P3 { set { _ = new value(); } }
+ object P4 { set { _ = new @value(); } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { return new field(); } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(6, 34),
+ // (8,31): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = new value(); } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(8, 31));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_TupleElementSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 219
+ class C
+ {
+ object P3 { set { (int field, int value) t = default; } }
+ object P4 { set { (int @field, int @value) t = default; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,24): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { (int field, int value) t = default; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int field").WithArguments("field", "preview").WithLocation(4, 24),
+ // (4,35): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { (int field, int value) t = default; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int value").WithArguments("value", "preview").WithLocation(4, 35));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_FromClauseSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ using System.Linq;
+ class C
+ {
+ object P1 { get { _ = from field in new int[0] select field; return null; } }
+ object P2 { get { _ = from @field in new int[0] select @field; return null; } }
+ object P3 { set { _ = from value in new int[0] select value; } }
+ object P4 { set { _ = from @value in new int[0] select @value; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,32): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from value in new int[0] select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 32),
+ // (7,32): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from @value in new int[0] select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 32));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,27): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from field in new int[0] select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "from field in new int[0]").WithArguments("field", "preview").WithLocation(4, 27),
+ // (4,59): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from field in new int[0] select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 59),
+ // (6,27): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from value in new int[0] select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "from value in new int[0]").WithArguments("value", "preview").WithLocation(6, 27),
+ // (6,32): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from value in new int[0] select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 32),
+ // (6,59): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from value in new int[0] select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 59),
+ // (7,32): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from @value in new int[0] select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 32));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_LetClauseSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ using System.Linq;
+ class C
+ {
+ object P1 { get { _ = from i in new int[0] let field = i select field; return null; } }
+ object P2 { get { _ = from i in new int[0] let @field = i select @field; return null; } }
+ object P3 { set { _ = from i in new int[0] let value = i select value; } }
+ object P4 { set { _ = from i in new int[0] let @value = i select @value; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,52): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from i in new int[0] let value = i select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 52),
+ // (7,52): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from i in new int[0] let @value = i select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 52));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,48): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from i in new int[0] let field = i select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "let field = i").WithArguments("field", "preview").WithLocation(4, 48),
+ // (4,69): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from i in new int[0] let field = i select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 69),
+ // (6,48): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from i in new int[0] let value = i select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "let value = i").WithArguments("value", "preview").WithLocation(6, 48),
+ // (6,52): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from i in new int[0] let value = i select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 52),
+ // (6,69): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from i in new int[0] let value = i select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 69),
+ // (7,52): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from i in new int[0] let @value = i select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 52));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_JoinClauseSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ using System.Linq;
+ class C
+ {
+ object P1 { get { _ = from x in new int[0] join field in new int[0] on x equals field select x; return null; } }
+ object P2 { get { _ = from x in new int[0] join @field in new int[0] on x equals @field select x; return null; } }
+ object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
+ object P4 { set { _ = from x in new int[0] join @value in new int[0] on x equals @value select x; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,53): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 53),
+ // (7,53): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from x in new int[0] join @value in new int[0] on x equals @value select x; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 53));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,48): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from x in new int[0] join field in new int[0] on x equals field select x; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "join field in new int[0] on x equals field").WithArguments("field", "preview").WithLocation(4, 48),
+ // (4,85): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from x in new int[0] join field in new int[0] on x equals field select x; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 85),
+ // (6,48): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "join value in new int[0] on x equals value").WithArguments("value", "preview").WithLocation(6, 48),
+ // (6,53): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 53),
+ // (6,85): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 85),
+ // (7,53): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from x in new int[0] join @value in new int[0] on x equals @value select x; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 53));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_JoinIntoClauseSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ using System.Linq;
+ class C
+ {
+ object P1 { get { _ = from x in new int[0] join y in new int[0] on x equals y into field select field; return null; } }
+ object P2 { get { _ = from x in new int[0] join y in new int[0] on x equals y into @field select @field; return null; } }
+ object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
+ object P4 { set { _ = from x in new int[0] join y in new int[0] on x equals y into @value select @value; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,88): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 88),
+ // (7,88): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from x in new int[0] join y in new int[0] on x equals y into @value select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 88));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,83): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from x in new int[0] join y in new int[0] on x equals y into field select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into field").WithArguments("field", "preview").WithLocation(4, 83),
+ // (4,101): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from x in new int[0] join y in new int[0] on x equals y into field select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 101),
+ // (6,83): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into value").WithArguments("value", "preview").WithLocation(6, 83),
+ // (6,88): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 88),
+ // (6,101): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 101),
+ // (7,88): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from x in new int[0] join y in new int[0] on x equals y into @value select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 88));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_QueryContinuationSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ using System.Linq;
+ class C
+ {
+ object P1 { get { _ = from x in new int[0] select x into field select field; return null; } }
+ object P2 { get { _ = from x in new int[0] select x into @field select @field; return null; } }
+ object P3 { set { _ = from x in new int[0] select x into value select value; } }
+ object P4 { set { _ = from x in new int[0] select x into @value select @value; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,62): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from x in new int[0] select x into value select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 62),
+ // (7,62): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from x in new int[0] select x into @value select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 62));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,57): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from x in new int[0] select x into field select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into field select field").WithArguments("field", "preview").WithLocation(4, 57),
+ // (4,75): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { _ = from x in new int[0] select x into field select field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 75),
+ // (6,57): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from x in new int[0] select x into value select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into value select value").WithArguments("value", "preview").WithLocation(6, 57),
+ // (6,62): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P3 { set { _ = from x in new int[0] select x into value select value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 62),
+ // (6,75): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { _ = from x in new int[0] select x into value select value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 75),
+ // (7,62): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
+ // object P4 { set { _ = from x in new int[0] select x into @value select @value; } }
+ Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "@value").WithArguments("value").WithLocation(7, 62));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_LocalFunctionStatementSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 8321
+ class C
+ {
+ object P1 { get { object field() => null; return null; } }
+ object P2 { get { object @field() => null; return null; } }
+ object P3 { set { void value() { } } }
+ object P4 { set { void @value() { } } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,28): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { void value() { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 28),
+ // (7,28): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { void @value() { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(7, 28));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { object field() => null; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field() => null;").WithArguments("field", "preview").WithLocation(4, 23),
+ // (6,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { void value() { } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "void value() { }").WithArguments("value", "preview").WithLocation(6, 23),
+ // (6,28): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { void value() { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 28),
+ // (7,28): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { void @value() { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(7, 28));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_VariableDeclaratorSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 219
+ class C
+ {
+ object P1 { get { int field = 0; return null; } }
+ object P2 { get { int @field = 0; return null; } }
+ object P3 { set { int value = 0; } }
+ object P4 { set { int @value = 0; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,27): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { int value = 0; } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 27),
+ // (7,27): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { int @value = 0; } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(7, 27));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,27): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { int field = 0; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 0").WithArguments("field", "preview").WithLocation(4, 27),
+ // (6,27): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { int value = 0; } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 27),
+ // (6,27): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { int value = 0; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 0").WithArguments("value", "preview").WithLocation(6, 27),
+ // (7,27): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { int @value = 0; } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(7, 27));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_SingleVariableDesignationSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ class C
+ {
+ static void F(out object value) { value = null; }
+ object P1 { get { F(out var field); return null; } }
+ object P2 { get { F(out var @field); return null; } }
+ object P3 { set { F(out var value); } }
+ object P4 { set { F(out var @value); } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (6,33): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { F(out var value); } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 33),
+ // (7,33): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { F(out var @value); } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(7, 33));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,33): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { F(out var field); return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 33),
+ // (6,33): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { F(out var value); } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 33),
+ // (6,33): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { F(out var value); } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 33),
+ // (7,33): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { F(out var @value); } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(7, 33));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_LabeledStatementSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 164
+ class C
+ {
+ object P1 { get { field: return null; } }
+ object P2 { get { @field: return null; } }
+ object P3 { set { value: return; } }
+ object P4 { set { @value: return; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { field: return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field: return null;").WithArguments("field", "preview").WithLocation(4, 23),
+ // (6,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { value: return; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value: return;").WithArguments("value", "preview").WithLocation(6, 23));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_ForEachStatementSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ class C
+ {
+ object P1 { get { foreach (var field in new int[0]) { } return null; } }
+ object P2 { get { foreach (var @field in new int[0]) { } return null; } }
+ object P3 { set { foreach (var value in new int[0]) { } } }
+ object P4 { set { foreach (var @value in new int[0]) { } } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,36): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { foreach (var value in new int[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(5, 36),
+ // (6,36): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { foreach (var @value in new int[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(6, 36));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (3,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { foreach (var field in new int[0]) { } return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "foreach (var field in new int[0]) { }").WithArguments("field", "preview").WithLocation(3, 23),
+ // (5,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { foreach (var value in new int[0]) { } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "foreach (var value in new int[0]) { }").WithArguments("value", "preview").WithLocation(5, 23),
+ // (5,36): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { foreach (var value in new int[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(5, 36),
+ // (6,36): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { foreach (var @value in new int[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(6, 36));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_CatchDeclarationSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 168
using System;
class C
{
- static object field;
- static object value;
- event EventHandler E1
- {
- add { _ = field ?? @field; }
- remove { _ = @field ?? field; }
- }
- event EventHandler E2
- {
- add { _ = C.value ?? C.@value; }
- remove { _ = C.@value ?? C.value; }
- }
+ object P1 { get { try { } catch (Exception field) { } return null; } }
+ object P2 { get { try { } catch (Exception @field) { } return null; } }
+ object P3 { set { try { } catch (Exception value) { } } }
+ object P4 { set { try { } catch (Exception @value) { } } }
}
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
- comp.VerifyEmitDiagnostics();
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (7,48): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { try { } catch (Exception value) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(7, 48),
+ // (8,48): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { try { } catch (Exception @value) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(8, 48));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (5,37): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { try { } catch (Exception field) { } return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "(Exception field)").WithArguments("field", "preview").WithLocation(5, 37),
+ // (7,37): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { try { } catch (Exception value) { } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "(Exception value)").WithArguments("value", "preview").WithLocation(7, 37),
+ // (7,48): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P3 { set { try { } catch (Exception value) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(7, 48),
+ // (8,48): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P4 { set { try { } catch (Exception @value) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(8, 48));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_TypeParameterSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 8321, 8981
+ class C
+ {
+ object P1 { get { void F1() { } return null; } }
+ object P2 { get { void F2<@field>() { } return null; } }
+ object P3 { set { void F3() { } } }
+ object P4 { set { void F4<@value>() { } } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,31): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { void F1() { } return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 31),
+ // (6,31): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { void F3() { } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 31));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_ParameterSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ #pragma warning disable 8321
+ class C
+ {
+ object P1 { get { object F1(object field) => field; return null; } }
+ object P2 { get { object F2(object @field) => @field; return null; } }
+ object P3 { set { object F3(object value) { return value; } } }
+ object P4 { set { object F4(object @value) { return @value; } } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (4,33): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { object F1(object field) => field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(4, 33),
+ // (4,50): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { get { object F1(object field) => field; return null; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 50),
+ // (6,33): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { object F3(object value) { return value; } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(6, 33),
+ // (6,56): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P3 { set { object F3(object value) { return value; } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 56));
+ }
}
[Theory]
@@ -490,7 +1101,7 @@ object P
}
[Fact]
- public void Lambda_Local_01()
+ public void Lambda_Local()
{
string source = """
#pragma warning disable 649
@@ -502,50 +1113,8 @@ object P
get
{
Func f;
- f = () => { object field = 1; return field; };
- f = () => { object @field = 2; return @field; };
- return null;
- }
- set
- {
- Func f;
- f = () => { object value = 1; return value; };
- f = () => { object @value = 2; return @value; };
- }
- }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
- comp.VerifyEmitDiagnostics(
- // (10,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // f = () => { object field = 1; return field; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(10, 32),
- // (10,50): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // f = () => { object field = 1; return field; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 50),
- // (17,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // f = () => { object value = 1; return value; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(17, 32),
- // (17,50): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // f = () => { object value = 1; return value; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 50));
- }
-
- [Fact]
- public void Lambda_Local_02()
- {
- string source = """
- #pragma warning disable 649
- using System;
- class C
- {
- object P
- {
- get
- {
- Action a;
- a = () => { object field = 1; };
- a = () => { object @field = 2; };
+ f = () => { object field = 1; return null; };
+ f = () => { object @field = 2; return null; };
return null;
}
set
@@ -560,7 +1129,7 @@ object P
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
// (10,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // a = () => { object field = 1; };
+ // f = () => { object field = 1; return null; };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(10, 32),
// (17,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// a = () => { object value = 1; };
@@ -568,7 +1137,7 @@ object P
}
[Fact]
- public void Lambda_Parameter_01()
+ public void Lambda_Parameter()
{
string source = """
#pragma warning disable 649
@@ -580,50 +1149,8 @@ object P
get
{
Func f;
- f = field => field;
- f = @field => @field;
- return null;
- }
- set
- {
- Func f;
- f = value => value;
- f = @value => @value;
- }
- }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
- comp.VerifyEmitDiagnostics(
- // (10,17): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // f = field => field;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 17),
- // (10,26): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // f = field => field;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 26),
- // (17,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // f = value => value;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 17),
- // (17,26): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // f = value => value;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 26));
- }
-
- [Fact]
- public void Lambda_Parameter_02()
- {
- string source = """
- #pragma warning disable 649
- using System;
- class C
- {
- object P
- {
- get
- {
- Action a;
- a = field => { };
- a = @field => { };
+ f = field => null;
+ f = @field => null;
return null;
}
set
@@ -638,7 +1165,7 @@ object P
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
// (10,17): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // a = field => { };
+ // f = field => null;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 17),
// (17,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// a = value => { };
@@ -646,46 +1173,7 @@ object P
}
[Fact]
- public void LocalFunction_Local_01()
- {
- string source = """
- #pragma warning disable 649, 8321
- class C
- {
- object P
- {
- get
- {
- object F1() { object field = 1; return field; };
- object F2() { object @field = 2; return @field; };
- return null;
- }
- set
- {
- object G1() { object value = 1; return value; };
- object G2() { object @value = 2; return @value; };
- }
- }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
- comp.VerifyEmitDiagnostics(
- // (8,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // object F1() { object field = 1; return field; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(8, 34),
- // (8,52): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // object F1() { object field = 1; return field; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(8, 52),
- // (14,34): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // object G1() { object value = 1; return value; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(14, 34),
- // (14,52): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // object G1() { object value = 1; return value; };
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(14, 52));
- }
-
- [Fact]
- public void LocalFunction_Local_02()
+ public void LocalFunction_Local()
{
string source = """
#pragma warning disable 649, 8321
@@ -695,8 +1183,8 @@ object P
{
get
{
- void F1() { object field = 1; }
- void F2() { object @field = 1; }
+ object F1() { object field = 1; return null; };
+ object F2() { object @field = 2; return null; };
return null;
}
set
@@ -709,55 +1197,16 @@ object P
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (8,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // void F1() { object field = 1; }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(8, 32),
+ // (8,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1() { object field = 1; return null; };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(8, 34),
// (14,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// void G1() { object value = 1; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(14, 32));
}
[Fact]
- public void LocalFunction_Parameter_01()
- {
- string source = """
- #pragma warning disable 649, 8321
- class C
- {
- object P
- {
- get
- {
- object F1(object field) => field;
- object F2(object @field) => @field;
- return null;
- }
- set
- {
- object G1(object value) => value;
- object G2(object @value) => @value;
- }
- }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
- comp.VerifyEmitDiagnostics(
- // (8,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // object F1(object field) => field;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(8, 23),
- // (8,40): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // object F1(object field) => field;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(8, 40),
- // (14,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // object G1(object value) => value;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(14, 23),
- // (14,40): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // object G1(object value) => value;
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(14, 40));
- }
-
- [Fact]
- public void LocalFunction_Parameter_02()
+ public void LocalFunction_Parameter()
{
string source = """
#pragma warning disable 649, 8321
@@ -767,8 +1216,8 @@ object P
{
get
{
- void F1(object field) { }
- void F2(object @field) { }
+ object F1(object field) => null;
+ object F2(object @field) => null;
return null;
}
set
@@ -781,9 +1230,9 @@ void G2(object @value) { }
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (8,21): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // void F1(object field) { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(8, 21),
+ // (8,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object F1(object field) => null;
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(8, 23),
// (14,21): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// void G1(object value) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(14, 21));
From 4f1a7ad2cfda093f18c5df571bb23cdf191b4d1f Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Fri, 24 May 2024 16:29:58 -0700
Subject: [PATCH 03/15] Include event accessors
---
.../Portable/Compiler/MethodCompiler.cs | 16 +++++++--------
.../Syntax/FieldAndValueKeywordTests.cs | 20 ++++++++++++++++++-
2 files changed, 27 insertions(+), 9 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index 4e0f321f22103..fd41fb09f1aa2 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -1784,7 +1784,7 @@ syntaxNode is ConstructorDeclarationSyntax constructorSyntax &&
var compilation = bodyBinder.Compilation;
- if (method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet)
+ if (method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove)
{
var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
if (requiredVersion > compilation.LanguageVersion)
@@ -2165,8 +2165,8 @@ static void assertBindIdentifierTargets(InMethodBinder? inMethodBinder, Concurre
///
private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol method, BoundNode node, BindingDiagnosticBag diagnostics)
{
- Debug.Assert(method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet);
- Debug.Assert(method.AssociatedSymbol is PropertySymbol);
+ Debug.Assert(method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove);
+ Debug.Assert(method.AssociatedSymbol is PropertySymbol or EventSymbol);
PooledDictionary? valueIdentifiers = null;
@@ -2206,7 +2206,7 @@ private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol me
}
break;
case "value":
- if (method.MethodKind == MethodKind.PropertySet)
+ if (method.MethodKind is MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove)
{
// Record the potential "value" conflict, and report conflicts later,
// after dropping any that refer to the implicit parameter.
@@ -2217,9 +2217,9 @@ private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol me
}
break;
default:
- // If we reach here, add the unhandled identifier case to the
- // switch cases above (and test in FieldAndValueKeywordTests).
- Debug.Assert(false, $"Unhandled identifier: parent {syntax.Kind()}, token {token}");
+ // The cases above should be the complete set of identifiers
+ // expected in an accessor with -langversion:12 or earlier.
+ Debug.Assert(false);
break;
}
}
@@ -2255,7 +2255,7 @@ public ValueIdentifierChecker(Dictionary valueIdentifie
public override BoundNode? VisitParameter(BoundParameter node)
{
- if (node.ParameterSymbol is SynthesizedPropertyAccessorValueParameterSymbol { Name: "value" })
+ if (node.ParameterSymbol is SynthesizedAccessorValueParameterSymbol { Name: "value" })
{
_valueIdentifiers.Remove(node.Syntax);
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 1c8a150b23602..15cca54d29a45 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -328,10 +328,28 @@ event EventHandler E2
add { _ = C.value ?? C.@value; }
remove { _ = C.@value ?? C.value; }
}
+ event EventHandler E3
+ {
+ add { _ = value ?? @value; }
+ remove { _ = @value ?? value; }
+ }
}
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
- comp.VerifyEmitDiagnostics();
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (14,21): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // add { _ = C.value ?? C.@value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(14, 21),
+ // (15,36): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // remove { _ = C.@value ?? C.value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(15, 36));
+ }
}
[Theory]
From 9e573b202cb568c5465520a09ad626a491710077 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Sat, 25 May 2024 11:03:37 -0700
Subject: [PATCH 04/15] Attribute tests
---
.../Portable/Compiler/MethodCompiler.cs | 1 +
.../Syntax/FieldAndValueKeywordTests.cs | 186 ++++++++++++++++++
2 files changed, 187 insertions(+)
diff --git a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
index fd41fb09f1aa2..84e99526a069a 100644
--- a/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
+++ b/src/Compilers/CSharp/Portable/Compiler/MethodCompiler.cs
@@ -2196,6 +2196,7 @@ private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol me
case CatchDeclarationSyntax catchDeclaration when catchDeclaration.Identifier == token:
case TypeParameterSyntax typeParameter when typeParameter.Identifier == token:
case ParameterSyntax parameter when parameter.Identifier == token:
+ case AttributeTargetSpecifierSyntax targetSpecifier when targetSpecifier.Identifier == token:
switch (token.Text)
{
case "field":
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 15cca54d29a45..d8828249442d9 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -1022,6 +1022,31 @@ class C
}
}
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_AttributeTargetSpecifierSyntax(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = $$"""
+ #pragma warning disable 657
+ using System;
+ class A : Attribute
+ {
+ }
+ class C
+ {
+ [field: A] object P1 { get; set; }
+ object P2 { [field: A] get; set; }
+ object P3 { [@field: A] get; set; }
+ [field: A] event EventHandler E1 { add { } remove { } }
+ event EventHandler E2 { [field: A] add { } remove { } }
+ event EventHandler E3 { [@field: A] add { } remove { } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ comp.VerifyEmitDiagnostics();
+ }
+
[Theory]
[CombinatorialData]
public void Lambda_01(
@@ -1255,5 +1280,166 @@ void G2(object @value) { }
// void G1(object value) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(14, 21));
}
+
+ [Theory]
+ [CombinatorialData]
+ public void Attribute_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion, bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@field" : "field";
+ string source = $$"""
+ using System;
+ class A : Attribute
+ {
+ public A(string s) { }
+ }
+ class C
+ {
+ const int field = 0;
+ [A(nameof({{identifier}}))]
+ object P
+ {
+ [A(nameof({{identifier}}))] get { return null; }
+ [A(nameof({{identifier}}))] set { }
+ }
+ [A(nameof({{identifier}}))]
+ event EventHandler E
+ {
+ [A(nameof({{identifier}}))] add { }
+ [A(nameof({{identifier}}))] remove { }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12 || escapeIdentifier)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (12,19): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(field))] get { return null; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(12, 19),
+ // (13,19): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(field))] set { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(13, 19));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Attribute_02(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion, bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ using System;
+ class A : Attribute
+ {
+ public A(string s) { }
+ }
+ class C
+ {
+ const int value = 0;
+ [A(nameof({{identifier}}))]
+ object P
+ {
+ [A(nameof({{identifier}}))] get { return null; }
+ [A(nameof({{identifier}}))] set { }
+ }
+ [A(nameof({{identifier}}))]
+ event EventHandler E
+ {
+ [A(nameof({{identifier}}))] add { }
+ [A(nameof({{identifier}}))] remove { }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12 || escapeIdentifier)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (13,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(value))] set { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(13, 19),
+ // (18,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(value))] add { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(18, 19),
+ // (19,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(value))] remove { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(19, 19));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void Attribute_LocalFunction(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion, bool escapeIdentifier)
+ {
+ string fieldIdentifier = escapeIdentifier ? "@field" : "field";
+ string valueIdentifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ #pragma warning disable 649, 8321
+ using System;
+ class A : Attribute
+ {
+ public A(string s) { }
+ }
+ class C
+ {
+ object P1
+ {
+ get
+ {
+ [A(nameof({{fieldIdentifier}}))] void F1(int {{fieldIdentifier}}) { }
+ return null;
+ }
+ }
+ object P2
+ {
+ set
+ {
+ [A(nameof({{valueIdentifier}}))] void F2(int {{valueIdentifier}}) { }
+ }
+ }
+ object P3
+ {
+ set
+ {
+ [A(nameof({{valueIdentifier}}))] void F3() { }
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12 || escapeIdentifier)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (13,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(field))] void F1(int field) { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(13, 23),
+ // (13,40): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(field))] void F1(int field) { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int field").WithArguments("field", "preview").WithLocation(13, 40),
+ // (21,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(value))] void F2(int value) { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(21, 23),
+ // (21,40): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(value))] void F2(int value) { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int value").WithArguments("value", "preview").WithLocation(21, 40),
+ // (28,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // [A(nameof(value))] void F3() { }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(28, 23));
+ }
+ }
}
}
From 5d56677df11740f6549aedec52ce0112c6df354a Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Mon, 27 May 2024 12:18:24 -0700
Subject: [PATCH 05/15] Add test; remove redundant tests
---
.../Syntax/FieldAndValueKeywordTests.cs | 134 ++++--------------
1 file changed, 30 insertions(+), 104 deletions(-)
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index d8828249442d9..8ff1f0108fcb7 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -136,110 +136,6 @@ class A
comp.VerifyEmitDiagnostics();
}
- [Theory]
- [CombinatorialData]
- public void Keyword_01(
- [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
- [CombinatorialValues("field", "value")] string identifier,
- bool escapeIdentifier)
- {
- string source = $$"""
- namespace A.{{identifier}}.B
- {
- class C { }
- }
- class D
- {
- object P { set { _ = new A.{{(escapeIdentifier ? "@" : "") + identifier}}.B.C(); } }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
- if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
- {
- comp.VerifyEmitDiagnostics();
- }
- else
- {
- comp.VerifyEmitDiagnostics(
- // (7,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // object P { set { _ = new A.field.B.C(); } }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, identifier).WithArguments(identifier, "preview").WithLocation(7, 32));
- }
- }
-
- [Theory]
- [CombinatorialData]
- public void Keyword_02(
- [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
- [CombinatorialValues("field", "value")] string identifier,
- bool escapeIdentifier)
- {
- string source = $$"""
- #pragma warning disable 649
- class C
- {
- static object {{identifier}};
- static object P1 { set { _ = C.{{(escapeIdentifier ? "@" : "") + identifier}}; } }
- object P2 { init { _ = C.{{(escapeIdentifier ? "@" : "") + identifier}}; } }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion), targetFramework: TargetFramework.Net70);
- if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
- {
- comp.VerifyEmitDiagnostics();
- }
- else
- {
- comp.VerifyEmitDiagnostics(
- // (5,36): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // static object P1 { set { _ = C.field; } }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, identifier).WithArguments(identifier, "preview").WithLocation(5, 36),
- // (6,30): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // object P2 { init { _ = C.field; } }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, identifier).WithArguments(identifier, "preview").WithLocation(6, 30));
- }
- }
-
- [Theory]
- [CombinatorialData]
- public void Keyword_03(
- [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
- {
- string source = """
- #pragma warning disable 649
- class C
- {
- object field;
- object value;
- object P
- {
- set
- {
- _ = nameof(field);
- _ = nameof(@field);
- _ = nameof(this.value);
- _ = nameof(this.@value);
- }
- }
- }
- """;
- var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
- if (languageVersion > LanguageVersion.CSharp12)
- {
- comp.VerifyEmitDiagnostics();
- }
- else
- {
- comp.VerifyEmitDiagnostics(
- // (10,24): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // _ = nameof(field);
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 24),
- // (12,29): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // _ = nameof(this.value);
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(12, 29));
- }
- }
-
[Fact]
public void Parameter_01()
{
@@ -1376,6 +1272,36 @@ event EventHandler E
}
}
+ [Theory]
+ [CombinatorialData]
+ public void Attribute_03(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion, bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ using System;
+ class A : Attribute
+ {
+ public A(string s) { }
+ }
+ class C
+ {
+ const int value = 0;
+ object P
+ {
+ [param: A(nameof({{identifier}}))] set { }
+ }
+ event EventHandler E
+ {
+ [param: A(nameof({{identifier}}))] add { }
+ [param: A(nameof({{identifier}}))] remove { }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ comp.VerifyEmitDiagnostics();
+ }
+
[Theory]
[CombinatorialData]
public void Attribute_LocalFunction(
From 56cb218bc8a48e6467b95dad2404d9fca012b8d9 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Mon, 27 May 2024 12:21:34 -0700
Subject: [PATCH 06/15] Report diagnostics in binding
---
.../Portable/Binder/Binder_Deconstruct.cs | 1 +
.../Portable/Binder/Binder_Expressions.cs | 31 +++++
.../CSharp/Portable/Binder/Binder_Lambda.cs | 14 ++-
.../CSharp/Portable/Binder/Binder_Query.cs | 11 ++
.../Portable/Binder/Binder_Statements.cs | 8 ++
.../CSharp/Portable/Binder/Binder_Symbols.cs | 9 +-
.../Portable/Binder/ForEachLoopBinder.cs | 5 +
.../Portable/Compiler/MethodCompiler.cs | 118 +-----------------
.../CSharp/Portable/Errors/ErrorFacts.cs | 2 +-
.../Symbols/Source/LocalFunctionSymbol.cs | 9 +-
.../Syntax/FieldAndValueKeywordTests.cs | 112 +++++++++++------
11 files changed, 157 insertions(+), 163 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
index 5341638741f87..99f781fd38fb6 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
@@ -904,6 +904,7 @@ private BoundExpression BindDeconstructionVariable(
// Use the binder that owns the scope for the local because this (the current) binder
// might own nested scope.
var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
+ ReportFieldOrValueContextualKeywordConflicts(designation, designation.Identifier.Text, symbol: null, diagnostics);
if (declTypeWithAnnotations.HasType)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index fbd07fc353ef3..9ffc54fd3cdfb 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -1595,6 +1595,8 @@ private BoundExpression BindIdentifier(
// Note, this call can clear and reuse lookupResult and members
reportPrimaryConstructorParameterShadowing(node, symbol ?? members[0], name, invoked, lookupResult, members, diagnostics);
members.Free();
+
+ ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol, diagnostics);
}
else
{
@@ -1731,6 +1733,31 @@ void reportPrimaryConstructorParameterShadowing(SimpleNameSyntax node, Symbol sy
}
}
+#nullable enable
+ internal void ReportFieldOrValueContextualKeywordConflicts(SyntaxNode syntax, string name, Symbol? symbol, BindingDiagnosticBag diagnostics)
+ {
+ switch (name)
+ {
+ case "field" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertyGet or MethodKind.PropertySet, AssociatedSymbol: PropertySymbol { IsIndexer: false } }:
+ break;
+ case "value" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove }:
+ if (symbol is SynthesizedAccessorValueParameterSymbol { Name: "value" })
+ {
+ return;
+ }
+ break;
+ default:
+ return;
+ }
+
+ var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
+ if (Compilation.LanguageVersion < requiredVersion)
+ {
+ diagnostics.Add(ErrorCode.INF_IdentifierConflictWithContextualKeyword, syntax, name, requiredVersion.ToDisplayString());
+ }
+ }
+#nullable disable
+
private void LookupIdentifier(LookupResult lookupResult, SimpleNameSyntax node, bool invoked, ref CompoundUseSiteInfo useSiteInfo)
{
LookupOptions options = LookupOptions.AllMethodsOnArityZero;
@@ -3090,6 +3117,8 @@ private BoundExpression BindOutVariableDeclarationArgument(
var designation = (SingleVariableDesignationSyntax)declarationExpression.Designation;
TypeSyntax typeSyntax = declarationExpression.Type;
+ ReportFieldOrValueContextualKeywordConflicts(designation, designation.Identifier.Text, symbol: null, diagnostics);
+
// Is this a local?
SourceLocalSymbol localSymbol = this.LookupLocal(designation.Identifier);
if ((object)localSymbol != null)
@@ -7524,6 +7553,8 @@ private BoundExpression BindMemberAccessWithBoundLeft(
boundLeft = MakeMemberAccessValue(boundLeft, diagnostics);
+ ReportFieldOrValueContextualKeywordConflicts(right, right.Identifier.Text, symbol: null, diagnostics);
+
TypeSymbol leftType = boundLeft.Type;
if ((object)leftType != null && leftType.IsDynamic())
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
index fd65a700503d9..ff332d5ff7071 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
@@ -69,6 +69,7 @@ private UnboundLambda AnalyzeAnonymousFunction(
// x => ...
hasSignature = true;
var simple = (SimpleLambdaExpressionSyntax)syntax;
+ ReportFieldOrValueContextualKeywordConflicts(simple.Parameter, simple.Parameter.Identifier.Text, symbol: null, diagnostics);
namesBuilder.Add(simple.Parameter.Identifier.ValueText);
break;
case SyntaxKind.ParenthesizedLambdaExpression:
@@ -303,14 +304,14 @@ static void checkAttributes(AnonymousFunctionExpressionSyntax syntax, SyntaxList
return (refKind, returnType);
}
- private static void CheckParenthesizedLambdaParameters(
+ private void CheckParenthesizedLambdaParameters(
SeparatedSyntaxList parameterSyntaxList, BindingDiagnosticBag diagnostics)
{
if (parameterSyntaxList.Count > 0)
{
var hasTypes = parameterSyntaxList[0].Type != null;
- checkForImplicitDefault(hasTypes, parameterSyntaxList[0], diagnostics);
+ checkParameter(hasTypes, parameterSyntaxList[0], diagnostics);
for (int i = 1, n = parameterSyntaxList.Count; i < n; i++)
{
@@ -328,17 +329,20 @@ private static void CheckParenthesizedLambdaParameters(
parameter.Type?.GetLocation() ?? parameter.Identifier.GetLocation());
}
- checkForImplicitDefault(thisParameterHasType, parameter, diagnostics);
+ checkParameter(thisParameterHasType, parameter, diagnostics);
}
}
}
- static void checkForImplicitDefault(bool hasType, ParameterSyntax param, BindingDiagnosticBag diagnostics)
+ void checkParameter(bool hasType, ParameterSyntax param, BindingDiagnosticBag diagnostics)
{
+ var text = param.Identifier.Text;
+ ReportFieldOrValueContextualKeywordConflicts(param, text, symbol: null, diagnostics);
+
if (!hasType && param.Default != null)
{
diagnostics.Add(ErrorCode.ERR_ImplicitlyTypedDefaultParameter,
- param.Identifier.GetLocation(), param.Identifier.Text);
+ param.Identifier.GetLocation(), text);
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
index 491a87033364c..abf4f2600b9d0 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
@@ -28,6 +28,8 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
var fromClause = node.FromClause;
var boundFromExpression = BindLeftOfPotentialColorColorMemberAccess(fromClause.Expression, diagnostics);
+ ReportFieldOrValueContextualKeywordConflicts(fromClause, fromClause.Identifier.Text, symbol: null, diagnostics);
+
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
// Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
if (boundFromExpression.HasDynamicType())
@@ -73,6 +75,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
// from ... into x ...
// is translated into
// from x in ( from ... ) ...
+ ReportFieldOrValueContextualKeywordConflicts(continuation, continuation.Identifier.Text, symbol: null, diagnostics);
x = PrepareQueryTranslationStateForContinuation(state, continuation, diagnostics);
state.fromExpression = result;
@@ -379,6 +382,12 @@ private void ReduceJoin(JoinClauseSyntax join, QueryTranslationState state, Bind
{
var inExpression = BindRValueWithoutTargetType(join.InExpression, diagnostics);
+ ReportFieldOrValueContextualKeywordConflicts(join, join.Identifier.Text, symbol: null, diagnostics);
+ if (join.Into is { })
+ {
+ ReportFieldOrValueContextualKeywordConflicts(join.Into, join.Into.Identifier.Text, symbol: null, diagnostics);
+ }
+
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
// Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
if (inExpression.HasDynamicType())
@@ -749,6 +758,8 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Binding
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(let.Expression, construction, d);
};
+ ReportFieldOrValueContextualKeywordConflicts(let, let.Identifier.Text, symbol: null, diagnostics);
+
var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory, diagnostics.AccumulatesDependencies);
state.rangeVariable = state.TransparentRangeVariable(this);
state.AddTransparentIdentifier(x.Name);
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index f5392eafa6697..fb7cc90cd5a22 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -507,6 +507,8 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, BindingDi
diagnostics.Add(node, useSiteInfo);
result.Free();
+ ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol: null, diagnostics);
+
var body = BindStatement(node.Statement, diagnostics);
return new BoundLabeledStatement(node, symbol, body, hasError);
}
@@ -559,6 +561,8 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n
{
MessageID.IDS_FeatureLocalFunctions.CheckFeatureAvailability(diagnostics, node.Identifier);
+ ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol: null, diagnostics);
+
// already defined symbol in containing block
var localSymbol = this.LookupLocalFunction(node.Identifier);
@@ -1006,6 +1010,8 @@ protected BoundLocalDeclaration BindVariableDeclaration(
bool nameConflict = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
bool hasErrors = false;
+ ReportFieldOrValueContextualKeywordConflicts(declarator, declarator.Identifier.Text, symbol: null, diagnostics);
+
if (localSymbol.RefKind != RefKind.None)
{
CheckRefLocalInAsyncOrIteratorMethod(localSymbol.IdentifierToken, diagnostics);
@@ -3158,6 +3164,8 @@ private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder compilation.LanguageVersion)
- {
- ReportFieldOrValueContextualKeywordConflicts(method, methodBody, diagnostics);
- }
- }
-
BoundNode methodBodyForSemanticModel = methodBody;
NullableWalker.SnapshotManager? snapshotManager = null;
ImmutableDictionary? remappedSymbols = null;
+ var compilation = bodyBinder.Compilation;
nullableInitialState = getInitializerState(methodBody);
@@ -2159,112 +2149,6 @@ static void assertBindIdentifierTargets(InMethodBinder? inMethodBinder, Concurre
#endif
}
- ///
- /// Report a diagnostic for any 'field' or 'value' identifier in the bound tree where the
- /// meaning will change when the identifier is considered a contextual keyword.
- ///
- private static void ReportFieldOrValueContextualKeywordConflicts(MethodSymbol method, BoundNode node, BindingDiagnosticBag diagnostics)
- {
- Debug.Assert(method.MethodKind is MethodKind.PropertyGet or MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove);
- Debug.Assert(method.AssociatedSymbol is PropertySymbol or EventSymbol);
-
- PooledDictionary? valueIdentifiers = null;
-
- foreach (var token in node.Syntax.DescendantTokens())
- {
- Debug.Assert(token.Parent is { });
- if (token.Kind() != SyntaxKind.IdentifierToken)
- {
- continue;
- }
- var syntax = token.Parent;
- switch (syntax)
- {
- case IdentifierNameSyntax identifierName when identifierName.Identifier == token:
- case GenericNameSyntax genericName when genericName.Identifier == token:
- case TupleElementSyntax tupleElement when tupleElement.Identifier == token:
- case FromClauseSyntax fromClause when fromClause.Identifier == token:
- case LetClauseSyntax letClause when letClause.Identifier == token:
- case JoinClauseSyntax joinClause when joinClause.Identifier == token:
- case JoinIntoClauseSyntax joinIntoClause when joinIntoClause.Identifier == token:
- case QueryContinuationSyntax queryContinuation when queryContinuation.Identifier == token:
- case LocalFunctionStatementSyntax localFunctionStatement when localFunctionStatement.Identifier == token:
- case VariableDeclaratorSyntax variableDeclarator when variableDeclarator.Identifier == token:
- case SingleVariableDesignationSyntax singleVariable when singleVariable.Identifier == token:
- case LabeledStatementSyntax labeledStatement when labeledStatement.Identifier == token:
- case ForEachStatementSyntax forEachStatement when forEachStatement.Identifier == token:
- case CatchDeclarationSyntax catchDeclaration when catchDeclaration.Identifier == token:
- case TypeParameterSyntax typeParameter when typeParameter.Identifier == token:
- case ParameterSyntax parameter when parameter.Identifier == token:
- case AttributeTargetSpecifierSyntax targetSpecifier when targetSpecifier.Identifier == token:
- switch (token.Text)
- {
- case "field":
- if (method.AssociatedSymbol is PropertySymbol { IsIndexer: false })
- {
- // Report "field" conflict with keyword.
- reportConflict(syntax, token, diagnostics);
- }
- break;
- case "value":
- if (method.MethodKind is MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove)
- {
- // Record the potential "value" conflict, and report conflicts later,
- // after dropping any that refer to the implicit parameter.
- valueIdentifiers ??= PooledDictionary.GetInstance();
- valueIdentifiers.Add(syntax, token);
- }
- break;
- }
- break;
- default:
- // The cases above should be the complete set of identifiers
- // expected in an accessor with -langversion:12 or earlier.
- Debug.Assert(false);
- break;
- }
- }
-
- if (valueIdentifiers is { })
- {
- // Remove references to the implicit "value" parameter.
- var checker = new ValueIdentifierChecker(valueIdentifiers);
- checker.Visit(node);
- // Report "value" conflicts.
- foreach (var pair in valueIdentifiers)
- {
- reportConflict(pair.Key, pair.Value, diagnostics);
- }
- valueIdentifiers.Free();
- }
-
- static void reportConflict(SyntaxNode syntax, SyntaxToken identifierToken, BindingDiagnosticBag diagnostics)
- {
- var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
- diagnostics.Add(ErrorCode.INF_IdentifierConflictWithContextualKeyword, syntax, identifierToken.Text, requiredVersion.ToDisplayString());
- }
- }
-
- private sealed class ValueIdentifierChecker : BoundTreeWalkerWithStackGuardWithoutRecursionOnTheLeftOfBinaryOperator
- {
- private readonly Dictionary _valueIdentifiers;
-
- public ValueIdentifierChecker(Dictionary valueIdentifiers)
- {
- _valueIdentifiers = valueIdentifiers;
- }
-
- public override BoundNode? VisitParameter(BoundParameter node)
- {
- if (node.ParameterSymbol is SynthesizedAccessorValueParameterSymbol { Name: "value" })
- {
- _valueIdentifiers.Remove(node.Syntax);
- }
-
- return base.VisitParameter(node);
- }
- }
-
#if DEBUG
private static bool IsEmptyRewritePossible(BoundNode node)
{
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
index 9713ba0eb0c66..2e22b437b49ad 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs
@@ -2472,7 +2472,7 @@ internal static bool PreventsSuccessfulDelegateConversion(ErrorCode code)
return false;
}
- if (IsWarning(code))
+ if (IsWarning(code) || IsInfo(code) || IsHidden(code))
{
return false;
}
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
index d502a7080b83c..3b441a598cfc9 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
@@ -59,6 +59,7 @@ public LocalFunctionSymbol(
ScopeBinder = binder;
binder = binder.SetOrClearUnsafeRegionIfNecessary(syntax.Modifiers);
+ _binder = binder;
if (syntax.TypeParameterList != null)
{
@@ -85,8 +86,6 @@ public LocalFunctionSymbol(
_declarationDiagnostics.AddRange(diagnostics.DiagnosticBag);
_declarationDependencies.AddAll(diagnostics.DependenciesBag);
diagnostics.Free();
-
- _binder = binder;
}
///
@@ -202,6 +201,11 @@ private void ComputeParameters()
addRefReadOnlyModifier: false,
diagnostics: diagnostics).Cast();
+ foreach (var parameter in this.Syntax.ParameterList.Parameters)
+ {
+ WithTypeParametersBinder.ReportFieldOrValueContextualKeywordConflicts(parameter, parameter.Identifier.Text, symbol: null, diagnostics);
+ }
+
// Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already
var isVararg = arglistToken.Kind() == SyntaxKind.ArgListKeyword;
@@ -433,6 +437,7 @@ private ImmutableArray MakeTypeParameters(Bindi
}
SourceMemberContainerTypeSymbol.ReportReservedTypeName(identifier.Text, this.DeclaringCompilation, diagnostics.DiagnosticBag, location);
+ _binder.ReportFieldOrValueContextualKeywordConflicts(parameter, identifier.Text, symbol: null, diagnostics);
var tpEnclosing = ContainingSymbol.FindEnclosingTypeParameter(name);
if ((object?)tpEnclosing != null)
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 8ff1f0108fcb7..07e41bca08549 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -762,7 +762,7 @@ class C
[Theory]
[CombinatorialData]
- public void IdentifierToken_ForEachStatementSyntax(
+ public void IdentifierToken_ForEachStatementSyntax_01(
[CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
{
string source = """
@@ -803,6 +803,47 @@ class C
}
}
+ [Theory]
+ [CombinatorialData]
+ public void IdentifierToken_ForEachStatementSyntax_02(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ class C
+ {
+ object P1 { set { foreach (var (field, @value) in new (int, int)[0]) { } } }
+ object P2 { set { foreach (var (@field, value) in new (int, int)[0]) { } } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (3,44): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P1 { set { foreach (var (field, @value) in new (int, int)[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(3, 44),
+ // (4,45): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P2 { set { foreach (var (@field, value) in new (int, int)[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(4, 45));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (3,37): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object P1 { set { foreach (var (field, @value) in new (int, int)[0]) { } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(3, 37),
+ // (3,44): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P1 { set { foreach (var (field, @value) in new (int, int)[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(3, 44),
+ // (4,45): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object P2 { set { foreach (var (@field, value) in new (int, int)[0]) { } } }
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(4, 45),
+ // (4,45): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object P2 { set { foreach (var (@field, value) in new (int, int)[0]) { } } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(4, 45));
+ }
+ }
+
[Theory]
[CombinatorialData]
public void IdentifierToken_CatchDeclarationSyntax(
@@ -1076,7 +1117,7 @@ object P
}
[Fact]
- public void Lambda_Parameter()
+ public void Lambda_Parameter_01()
{
string source = """
#pragma warning disable 649
@@ -1111,6 +1152,35 @@ object P
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 17));
}
+ [Fact]
+ public void Lambda_Parameter_02()
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ object P
+ {
+ set
+ {
+ Action a;
+ a = (field, @value) => { };
+ a = (@field, value) => { };
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (10,18): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // a = (field, @value) => { };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 18),
+ // (11,26): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // a = (@field, value) => { };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(11, 26));
+ }
+
[Fact]
public void LocalFunction_Local()
{
@@ -1207,20 +1277,7 @@ event EventHandler E
}
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
- if (languageVersion > LanguageVersion.CSharp12 || escapeIdentifier)
- {
- comp.VerifyEmitDiagnostics();
- }
- else
- {
- comp.VerifyEmitDiagnostics(
- // (12,19): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // [A(nameof(field))] get { return null; }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(12, 19),
- // (13,19): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
- // [A(nameof(field))] set { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(13, 19));
- }
+ comp.VerifyEmitDiagnostics();
}
[Theory]
@@ -1253,23 +1310,7 @@ event EventHandler E
}
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
- if (languageVersion > LanguageVersion.CSharp12 || escapeIdentifier)
- {
- comp.VerifyEmitDiagnostics();
- }
- else
- {
- comp.VerifyEmitDiagnostics(
- // (13,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // [A(nameof(value))] set { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(13, 19),
- // (18,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // [A(nameof(value))] add { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(18, 19),
- // (19,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // [A(nameof(value))] remove { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(19, 19));
- }
+ comp.VerifyEmitDiagnostics();
}
[Theory]
@@ -1361,10 +1402,7 @@ object P3
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(21, 23),
// (21,40): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// [A(nameof(value))] void F2(int value) { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int value").WithArguments("value", "preview").WithLocation(21, 40),
- // (28,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
- // [A(nameof(value))] void F3() { }
- Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(28, 23));
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int value").WithArguments("value", "preview").WithLocation(21, 40));
}
}
}
From f07918ee26382e7ef41b54c07a0e1f863163a2a4 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Wed, 29 May 2024 16:04:10 -0700
Subject: [PATCH 07/15] Address feedback
---
.../Portable/Binder/Binder_Deconstruct.cs | 2 +-
.../Portable/Binder/Binder_Expressions.cs | 17 +++++++++--------
.../CSharp/Portable/Binder/Binder_Lambda.cs | 4 ++--
.../CSharp/Portable/Binder/Binder_Query.cs | 10 +++++-----
.../CSharp/Portable/Binder/Binder_Statements.cs | 8 ++++----
.../CSharp/Portable/Binder/Binder_Symbols.cs | 12 +++++-------
.../CSharp/Portable/Binder/ForEachLoopBinder.cs | 2 +-
.../Symbols/Source/LocalFunctionSymbol.cs | 4 ++--
8 files changed, 29 insertions(+), 30 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
index 99f781fd38fb6..665007f322edd 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
@@ -904,7 +904,7 @@ private BoundExpression BindDeconstructionVariable(
// Use the binder that owns the scope for the local because this (the current) binder
// might own nested scope.
var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
- ReportFieldOrValueContextualKeywordConflicts(designation, designation.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier.Text, diagnostics);
if (declTypeWithAnnotations.HasType)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index 9ffc54fd3cdfb..f4c77dfeb3993 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -1596,7 +1596,12 @@ private BoundExpression BindIdentifier(
reportPrimaryConstructorParameterShadowing(node, symbol ?? members[0], name, invoked, lookupResult, members, diagnostics);
members.Free();
- ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol, diagnostics);
+ string text = node.Identifier.Text;
+ if (text != "value" ||
+ symbol is not SynthesizedAccessorValueParameterSymbol { Name: "value" })
+ {
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, text, diagnostics);
+ }
}
else
{
@@ -1734,17 +1739,13 @@ void reportPrimaryConstructorParameterShadowing(SimpleNameSyntax node, Symbol sy
}
#nullable enable
- internal void ReportFieldOrValueContextualKeywordConflicts(SyntaxNode syntax, string name, Symbol? symbol, BindingDiagnosticBag diagnostics)
+ internal void ReportFieldOrValueContextualKeywordConflictIfAny(SyntaxNode syntax, string name, BindingDiagnosticBag diagnostics)
{
switch (name)
{
case "field" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertyGet or MethodKind.PropertySet, AssociatedSymbol: PropertySymbol { IsIndexer: false } }:
break;
case "value" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove }:
- if (symbol is SynthesizedAccessorValueParameterSymbol { Name: "value" })
- {
- return;
- }
break;
default:
return;
@@ -3117,7 +3118,7 @@ private BoundExpression BindOutVariableDeclarationArgument(
var designation = (SingleVariableDesignationSyntax)declarationExpression.Designation;
TypeSyntax typeSyntax = declarationExpression.Type;
- ReportFieldOrValueContextualKeywordConflicts(designation, designation.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier.Text, diagnostics);
// Is this a local?
SourceLocalSymbol localSymbol = this.LookupLocal(designation.Identifier);
@@ -7553,7 +7554,7 @@ private BoundExpression BindMemberAccessWithBoundLeft(
boundLeft = MakeMemberAccessValue(boundLeft, diagnostics);
- ReportFieldOrValueContextualKeywordConflicts(right, right.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(right, right.Identifier.Text, diagnostics);
TypeSymbol leftType = boundLeft.Type;
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
index ff332d5ff7071..9673fe71a09f4 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
@@ -69,7 +69,7 @@ private UnboundLambda AnalyzeAnonymousFunction(
// x => ...
hasSignature = true;
var simple = (SimpleLambdaExpressionSyntax)syntax;
- ReportFieldOrValueContextualKeywordConflicts(simple.Parameter, simple.Parameter.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(simple.Parameter, simple.Parameter.Identifier.Text, diagnostics);
namesBuilder.Add(simple.Parameter.Identifier.ValueText);
break;
case SyntaxKind.ParenthesizedLambdaExpression:
@@ -337,7 +337,7 @@ private void CheckParenthesizedLambdaParameters(
void checkParameter(bool hasType, ParameterSyntax param, BindingDiagnosticBag diagnostics)
{
var text = param.Identifier.Text;
- ReportFieldOrValueContextualKeywordConflicts(param, text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(param, text, diagnostics);
if (!hasType && param.Default != null)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
index abf4f2600b9d0..e69f22c6b0e3c 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
@@ -28,7 +28,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
var fromClause = node.FromClause;
var boundFromExpression = BindLeftOfPotentialColorColorMemberAccess(fromClause.Expression, diagnostics);
- ReportFieldOrValueContextualKeywordConflicts(fromClause, fromClause.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(fromClause, fromClause.Identifier.Text, diagnostics);
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
// Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
@@ -75,7 +75,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
// from ... into x ...
// is translated into
// from x in ( from ... ) ...
- ReportFieldOrValueContextualKeywordConflicts(continuation, continuation.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(continuation, continuation.Identifier.Text, diagnostics);
x = PrepareQueryTranslationStateForContinuation(state, continuation, diagnostics);
state.fromExpression = result;
@@ -382,10 +382,10 @@ private void ReduceJoin(JoinClauseSyntax join, QueryTranslationState state, Bind
{
var inExpression = BindRValueWithoutTargetType(join.InExpression, diagnostics);
- ReportFieldOrValueContextualKeywordConflicts(join, join.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(join, join.Identifier.Text, diagnostics);
if (join.Into is { })
{
- ReportFieldOrValueContextualKeywordConflicts(join.Into, join.Into.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(join.Into, join.Into.Identifier.Text, diagnostics);
}
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
@@ -758,7 +758,7 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Binding
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(let.Expression, construction, d);
};
- ReportFieldOrValueContextualKeywordConflicts(let, let.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(let, let.Identifier.Text, diagnostics);
var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory, diagnostics.AccumulatesDependencies);
state.rangeVariable = state.TransparentRangeVariable(this);
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index fb7cc90cd5a22..fe952fe1b15b2 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -507,7 +507,7 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, BindingDi
diagnostics.Add(node, useSiteInfo);
result.Free();
- ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
var body = BindStatement(node.Statement, diagnostics);
return new BoundLabeledStatement(node, symbol, body, hasError);
@@ -561,7 +561,7 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n
{
MessageID.IDS_FeatureLocalFunctions.CheckFeatureAvailability(diagnostics, node.Identifier);
- ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
// already defined symbol in containing block
var localSymbol = this.LookupLocalFunction(node.Identifier);
@@ -1010,7 +1010,7 @@ protected BoundLocalDeclaration BindVariableDeclaration(
bool nameConflict = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
bool hasErrors = false;
- ReportFieldOrValueContextualKeywordConflicts(declarator, declarator.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(declarator, declarator.Identifier.Text, diagnostics);
if (localSymbol.RefKind != RefKind.None)
{
@@ -3164,7 +3164,7 @@ private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
this.LookupSymbolsSimpleName(result, qualifierOpt, identifierValueText, 0, basesBeingResolved, options, diagnose: true, useSiteInfo: ref useSiteInfo);
diagnostics.Add(node, useSiteInfo);
@@ -925,11 +927,7 @@ protected NamespaceOrTypeOrAliasSymbolWithAnnotations BindNonGenericSimpleNamesp
}
result.Free();
-
- var namespaceOrTypeOrAlias = NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(AreNullableAnnotationsEnabled(node.Identifier), bindingResult);
- ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, namespaceOrTypeOrAlias.Symbol, diagnostics);
-
- return namespaceOrTypeOrAlias;
+ return NamespaceOrTypeOrAliasSymbolWithAnnotations.CreateUnannotated(AreNullableAnnotationsEnabled(node.Identifier), bindingResult);
bool dynamicAllowed()
{
@@ -1258,7 +1256,7 @@ private TypeWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol(
diagnostics);
}
- ReportFieldOrValueContextualKeywordConflicts(node, node.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
return TypeWithAnnotations.Create(AreNullableAnnotationsEnabled(node.TypeArgumentList.GreaterThanToken), resultType);
}
diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
index 8e6bd440a44cc..a469fed5cc94c 100644
--- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
@@ -222,7 +222,7 @@ private BoundForEachStatement BindForEachPartsWorker(BindingDiagnosticBag diagno
if (_syntax is ForEachStatementSyntax forEachStatement)
{
- ReportFieldOrValueContextualKeywordConflicts(forEachStatement, forEachStatement.Identifier.Text, symbol: null, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(forEachStatement, forEachStatement.Identifier.Text, diagnostics);
}
// Use the right binder to avoid seeing iteration variable
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
index 3b441a598cfc9..c42e5fce411a0 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
@@ -203,7 +203,7 @@ private void ComputeParameters()
foreach (var parameter in this.Syntax.ParameterList.Parameters)
{
- WithTypeParametersBinder.ReportFieldOrValueContextualKeywordConflicts(parameter, parameter.Identifier.Text, symbol: null, diagnostics);
+ WithTypeParametersBinder.ReportFieldOrValueContextualKeywordConflictIfAny(parameter, parameter.Identifier.Text, diagnostics);
}
// Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already
@@ -437,7 +437,7 @@ private ImmutableArray MakeTypeParameters(Bindi
}
SourceMemberContainerTypeSymbol.ReportReservedTypeName(identifier.Text, this.DeclaringCompilation, diagnostics.DiagnosticBag, location);
- _binder.ReportFieldOrValueContextualKeywordConflicts(parameter, identifier.Text, symbol: null, diagnostics);
+ _binder.ReportFieldOrValueContextualKeywordConflictIfAny(parameter, identifier.Text, diagnostics);
var tpEnclosing = ContainingSymbol.FindEnclosingTypeParameter(name);
if ((object?)tpEnclosing != null)
From 98026774863124f7234c8d97cd6296b6d252eca4 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Wed, 29 May 2024 16:39:02 -0700
Subject: [PATCH 08/15] Add test
---
.../Portable/Binder/Binder_Expressions.cs | 16 +++---
.../Syntax/FieldAndValueKeywordTests.cs | 53 +++++++++++++++++++
2 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index f4c77dfeb3993..1dd6f7fb569a5 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -1744,17 +1744,15 @@ internal void ReportFieldOrValueContextualKeywordConflictIfAny(SyntaxNode syntax
switch (name)
{
case "field" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertyGet or MethodKind.PropertySet, AssociatedSymbol: PropertySymbol { IsIndexer: false } }:
- break;
case "value" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertySet or MethodKind.EventAdd or MethodKind.EventRemove }:
+ {
+ var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
+ if (Compilation.LanguageVersion < requiredVersion)
+ {
+ diagnostics.Add(ErrorCode.INF_IdentifierConflictWithContextualKeyword, syntax, name, requiredVersion.ToDisplayString());
+ }
+ }
break;
- default:
- return;
- }
-
- var requiredVersion = MessageID.IDS_FeatureFieldAndValueKeywords.RequiredVersion();
- if (Compilation.LanguageVersion < requiredVersion)
- {
- diagnostics.Add(ErrorCode.INF_IdentifierConflictWithContextualKeyword, syntax, name, requiredVersion.ToDisplayString());
}
}
#nullable disable
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 07e41bca08549..5adc70d01d885 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -697,6 +697,8 @@ class C
object P2 { get { F(out var @field); return null; } }
object P3 { set { F(out var value); } }
object P4 { set { F(out var @value); } }
+ object P5 { set { F(out value); } }
+ object P6 { set { F(out @value); } }
}
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
@@ -984,6 +986,57 @@ class C
comp.VerifyEmitDiagnostics();
}
+ [Theory]
+ [CombinatorialData]
+ public void Deconstruction(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion)
+ {
+ string source = """
+ class C
+ {
+ void Deconstruct(out object x, out object y) => throw null;
+ static object P1
+ {
+ set
+ {
+ object @field;
+ object @value;
+ (field, @value) = new C();
+ (@field, value) = new C();
+ }
+ }
+ static object P2
+ {
+ set
+ {
+ (value, @value) = new C();
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics(
+ // (9,20): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object @value;
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(9, 20));
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (9,20): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
+ // object @value;
+ Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(9, 20),
+ // (10,14): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (field, @value) = new C();
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 14),
+ // (11,22): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (@field, value) = new C();
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(11, 22));
+ }
+ }
+
[Theory]
[CombinatorialData]
public void Lambda_01(
From e8613d536a60353e9bfd3122b459e0ab9a15f3fb Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Wed, 29 May 2024 21:57:43 -0700
Subject: [PATCH 09/15] Remove unnecessary check
---
src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index 1dd6f7fb569a5..8e17bfe3287f2 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -1596,11 +1596,9 @@ private BoundExpression BindIdentifier(
reportPrimaryConstructorParameterShadowing(node, symbol ?? members[0], name, invoked, lookupResult, members, diagnostics);
members.Free();
- string text = node.Identifier.Text;
- if (text != "value" ||
- symbol is not SynthesizedAccessorValueParameterSymbol { Name: "value" })
+ if (symbol is not SynthesizedAccessorValueParameterSymbol { Name: "value" })
{
- ReportFieldOrValueContextualKeywordConflictIfAny(node, text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
}
}
else
From 564a13efd1dcd8197e095d1dca527348045ce9d4 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Fri, 31 May 2024 15:34:12 -0700
Subject: [PATCH 10/15] Modify ErrorCode value
---
.../CSharp/Portable/Errors/ErrorCode.cs | 3 +-
.../Semantic/Semantics/SemanticErrorTests.cs | 4 +-
.../Syntax/FieldAndValueKeywordTests.cs | 154 +++++++++---------
3 files changed, 81 insertions(+), 80 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 674efcc14836f..ffbcd5ca6982e 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -2324,7 +2324,6 @@ internal enum ErrorCode
ERR_RefStructDoesNotSupportDefaultInterfaceImplementationForMember = 9245,
ERR_BadNonVirtualInterfaceMemberAccessOnAllowsRefLike = 9246,
ERR_BadAllowByRefLikeEnumerator = 9247,
- INF_IdentifierConflictWithContextualKeyword = 9248,
ERR_PartialPropertyMissingImplementation = 9248,
ERR_PartialPropertyMissingDefinition = 9249,
@@ -2337,6 +2336,8 @@ internal enum ErrorCode
WRN_PartialPropertySignatureDifference = 9256,
ERR_PartialPropertyRequiredDifference = 9257,
+ INF_IdentifierConflictWithContextualKeyword = 9258,
+
// Note: you will need to do the following after adding errors:
// 1) Update ErrorFacts.IsBuildOnlyDiagnostic (src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs)
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs
index 6ed56ad462451..780a3ed6dcbb2 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/SemanticErrorTests.cs
@@ -4010,10 +4010,10 @@ static void N(int q)
// (24,17): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// int value = 0; // CS0136
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(24, 17),
- // (24,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (24,17): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// int value = 0; // CS0136
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 0").WithArguments("value", "preview").WithLocation(24, 17),
- // (25,15): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (25,15): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// M(value);
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(25, 15),
// (30,35): error CS0136: A local or parameter named 'q' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 5adc70d01d885..27a3d33913cb3 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -41,16 +41,16 @@ class D4 : A { object this[int i] { set { {{identifier}} = 0; } } }
else
{
comp.VerifyEmitDiagnostics(
- // (4,28): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,28): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// class C1 : A { object P => field; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 28),
- // (5,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (5,34): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// class C2 : A { object P { get => field; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(5, 34),
- // (6,40): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (6,40): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// class C3 : A { object P { get { return field; } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(6, 40),
- // (7,33): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (7,33): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// class C4 : A { object P { set { field = 0; } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(7, 33));
}
@@ -109,10 +109,10 @@ class D4 : A { object this[int i] { set { this.{{identifier}} = 0; } } }
else
{
comp.VerifyEmitDiagnostics(
- // (6,38): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,38): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// class C4 : A { object P { set { this.value = 0; } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 38),
- // (10,48): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (10,48): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// class D4 : A { object this[int i] { set { this.value = 0; } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(10, 48));
}
@@ -191,7 +191,7 @@ object this[int @value]
// (6,19): error CS0229: Ambiguity between 'int value' and 'object value'
// set { _ = value; }
Diagnostic(ErrorCode.ERR_AmbigMember, "value").WithArguments("int value", "object value").WithLocation(6, 19),
- // (6,19): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,19): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// set { _ = value; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 19),
// (11,21): error CS0316: The parameter name 'value' conflicts with an automatically-generated parameter name
@@ -239,10 +239,10 @@ event EventHandler E3
else
{
comp.VerifyEmitDiagnostics(
- // (14,21): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (14,21): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// add { _ = C.value ?? C.@value; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(14, 21),
- // (15,36): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (15,36): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// remove { _ = C.@value ?? C.value; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(15, 36));
}
@@ -273,10 +273,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (6,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (6,34): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { return new field(); } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(6, 34),
- // (8,31): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (8,31): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = new value(); } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(8, 31));
}
@@ -307,10 +307,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (6,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (6,34): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { return new field(); } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(6, 34),
- // (8,31): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (8,31): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = new value(); } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(8, 31));
}
@@ -337,10 +337,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,24): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,24): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { (int field, int value) t = default; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int field").WithArguments("field", "preview").WithLocation(4, 24),
- // (4,35): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (4,35): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { (int field, int value) t = default; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int value").WithArguments("value", "preview").WithLocation(4, 35));
}
@@ -375,19 +375,19 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,27): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,27): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from field in new int[0] select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "from field in new int[0]").WithArguments("field", "preview").WithLocation(4, 27),
- // (4,59): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,59): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from field in new int[0] select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 59),
- // (6,27): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,27): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from value in new int[0] select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "from value in new int[0]").WithArguments("value", "preview").WithLocation(6, 27),
// (6,32): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
// object P3 { set { _ = from value in new int[0] select value; } }
Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 32),
- // (6,59): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,59): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from value in new int[0] select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 59),
// (7,32): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
@@ -425,19 +425,19 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,48): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,48): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from i in new int[0] let field = i select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "let field = i").WithArguments("field", "preview").WithLocation(4, 48),
- // (4,69): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,69): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from i in new int[0] let field = i select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 69),
- // (6,48): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,48): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from i in new int[0] let value = i select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "let value = i").WithArguments("value", "preview").WithLocation(6, 48),
// (6,52): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
// object P3 { set { _ = from i in new int[0] let value = i select value; } }
Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 52),
- // (6,69): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,69): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from i in new int[0] let value = i select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 69),
// (7,52): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
@@ -475,19 +475,19 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,48): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,48): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from x in new int[0] join field in new int[0] on x equals field select x; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "join field in new int[0] on x equals field").WithArguments("field", "preview").WithLocation(4, 48),
- // (4,85): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,85): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from x in new int[0] join field in new int[0] on x equals field select x; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 85),
- // (6,48): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,48): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "join value in new int[0] on x equals value").WithArguments("value", "preview").WithLocation(6, 48),
// (6,53): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
// object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 53),
- // (6,85): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,85): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from x in new int[0] join value in new int[0] on x equals value select x; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 85),
// (7,53): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
@@ -525,19 +525,19 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,83): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,83): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from x in new int[0] join y in new int[0] on x equals y into field select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into field").WithArguments("field", "preview").WithLocation(4, 83),
- // (4,101): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,101): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from x in new int[0] join y in new int[0] on x equals y into field select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 101),
- // (6,83): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,83): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into value").WithArguments("value", "preview").WithLocation(6, 83),
// (6,88): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
// object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 88),
- // (6,101): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,101): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from x in new int[0] join y in new int[0] on x equals y into value select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 101),
// (7,88): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
@@ -575,19 +575,19 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,57): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,57): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from x in new int[0] select x into field select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into field select field").WithArguments("field", "preview").WithLocation(4, 57),
- // (4,75): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,75): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { _ = from x in new int[0] select x into field select field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 75),
- // (6,57): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,57): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from x in new int[0] select x into value select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "into value select value").WithArguments("value", "preview").WithLocation(6, 57),
// (6,62): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
// object P3 { set { _ = from x in new int[0] select x into value select value; } }
Diagnostic(ErrorCode.ERR_QueryRangeVariableOverrides, "value").WithArguments("value").WithLocation(6, 62),
- // (6,75): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,75): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { _ = from x in new int[0] select x into value select value; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 75),
// (7,62): error CS1931: The range variable 'value' conflicts with a previous declaration of 'value'
@@ -625,10 +625,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,23): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { object field() => null; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field() => null;").WithArguments("field", "preview").WithLocation(4, 23),
- // (6,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,23): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { void value() { } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "void value() { }").WithArguments("value", "preview").WithLocation(6, 23),
// (6,28): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
@@ -669,13 +669,13 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,27): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,27): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { int field = 0; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 0").WithArguments("field", "preview").WithLocation(4, 27),
// (6,27): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// object P3 { set { int value = 0; } }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 27),
- // (6,27): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,27): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { int value = 0; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 0").WithArguments("value", "preview").WithLocation(6, 27),
// (7,27): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
@@ -715,13 +715,13 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,33): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,33): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { F(out var field); return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 33),
// (6,33): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// object P3 { set { F(out var value); } }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(6, 33),
- // (6,33): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,33): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { F(out var value); } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 33),
// (7,33): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
@@ -753,10 +753,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,23): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { field: return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field: return null;").WithArguments("field", "preview").WithLocation(4, 23),
- // (6,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,23): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { value: return; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value: return;").WithArguments("value", "preview").WithLocation(6, 23));
}
@@ -790,10 +790,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (3,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (3,23): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { foreach (var field in new int[0]) { } return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "foreach (var field in new int[0]) { }").WithArguments("field", "preview").WithLocation(3, 23),
- // (5,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (5,23): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { foreach (var value in new int[0]) { } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "foreach (var value in new int[0]) { }").WithArguments("value", "preview").WithLocation(5, 23),
// (5,36): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
@@ -831,7 +831,7 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (3,37): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (3,37): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { set { foreach (var (field, @value) in new (int, int)[0]) { } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(3, 37),
// (3,44): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
@@ -840,7 +840,7 @@ class C
// (4,45): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// object P2 { set { foreach (var (@field, value) in new (int, int)[0]) { } } }
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "value").WithArguments("value").WithLocation(4, 45),
- // (4,45): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (4,45): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P2 { set { foreach (var (@field, value) in new (int, int)[0]) { } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(4, 45));
}
@@ -876,10 +876,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (5,37): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (5,37): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { try { } catch (Exception field) { } return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "(Exception field)").WithArguments("field", "preview").WithLocation(5, 37),
- // (7,37): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (7,37): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { try { } catch (Exception value) { } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "(Exception value)").WithArguments("value", "preview").WithLocation(7, 37),
// (7,48): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
@@ -914,10 +914,10 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,31): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,31): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { void F1() { } return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 31),
- // (6,31): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,31): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { void F3() { } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 31));
}
@@ -946,16 +946,16 @@ class C
else
{
comp.VerifyEmitDiagnostics(
- // (4,33): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,33): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { object F1(object field) => field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(4, 33),
- // (4,50): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (4,50): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object P1 { get { object F1(object field) => field; return null; } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(4, 50),
- // (6,33): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,33): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { object F3(object value) { return value; } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(6, 33),
- // (6,56): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (6,56): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object P3 { set { object F3(object value) { return value; } } }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(6, 56));
}
@@ -1028,10 +1028,10 @@ static object P2
// (9,20): error CS0136: A local or parameter named 'value' cannot be declared in this scope because that name is used in an enclosing local scope to define a local or parameter
// object @value;
Diagnostic(ErrorCode.ERR_LocalIllegallyOverrides, "@value").WithArguments("value").WithLocation(9, 20),
- // (10,14): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (10,14): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// (field, @value) = new C();
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 14),
- // (11,22): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (11,22): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// (@field, value) = new C();
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(11, 22));
}
@@ -1074,13 +1074,13 @@ object P
else
{
comp.VerifyEmitDiagnostics(
- // (12,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (12,23): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// f = () => field;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(12, 23),
- // (14,25): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (14,25): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// f = () => C.field;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(14, 25),
- // (17,25): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (17,25): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// f = () => C.value;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 25));
}
@@ -1121,13 +1121,13 @@ object P
else
{
comp.VerifyEmitDiagnostics(
- // (10,28): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (10,28): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object F1() => field;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 28),
- // (12,30): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (12,30): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object F3() => C.field;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(12, 30),
- // (15,36): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (15,36): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// object G2() { return C.value; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(15, 36));
}
@@ -1161,10 +1161,10 @@ object P
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (10,32): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (10,32): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// f = () => { object field = 1; return null; };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(10, 32),
- // (17,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (17,32): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// a = () => { object value = 1; };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(17, 32));
}
@@ -1197,10 +1197,10 @@ object P
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (10,17): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (10,17): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// f = field => null;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 17),
- // (17,17): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (17,17): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// a = value => { };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(17, 17));
}
@@ -1226,10 +1226,10 @@ object P
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (10,18): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (10,18): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// a = (field, @value) => { };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 18),
- // (11,26): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (11,26): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// a = (@field, value) => { };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(11, 26));
}
@@ -1259,10 +1259,10 @@ object P
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (8,34): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (8,34): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object F1() { object field = 1; return null; };
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field = 1").WithArguments("field", "preview").WithLocation(8, 34),
- // (14,32): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (14,32): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// void G1() { object value = 1; }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value = 1").WithArguments("value", "preview").WithLocation(14, 32));
}
@@ -1292,10 +1292,10 @@ void G2(object @value) { }
""";
var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
comp.VerifyEmitDiagnostics(
- // (8,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (8,23): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// object F1(object field) => null;
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(8, 23),
- // (14,21): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (14,21): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// void G1(object value) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(14, 21));
}
@@ -1444,16 +1444,16 @@ object P3
else
{
comp.VerifyEmitDiagnostics(
- // (13,23): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (13,23): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// [A(nameof(field))] void F1(int field) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(13, 23),
- // (13,40): info CS9248: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // (13,40): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
// [A(nameof(field))] void F1(int field) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int field").WithArguments("field", "preview").WithLocation(13, 40),
- // (21,23): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (21,23): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// [A(nameof(value))] void F2(int value) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(21, 23),
- // (21,40): info CS9248: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // (21,40): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
// [A(nameof(value))] void F2(int value) { }
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "int value").WithArguments("value", "preview").WithLocation(21, 40));
}
From 48a1fd0d4ae34aebae9a2234e74d25ff5fcedf24 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Fri, 31 May 2024 16:17:04 -0700
Subject: [PATCH 11/15] Use SyntaxToken rather than string
---
.../CSharp/Portable/Binder/Binder_Deconstruct.cs | 2 +-
.../CSharp/Portable/Binder/Binder_Expressions.cs | 13 +++++++++----
.../CSharp/Portable/Binder/Binder_Lambda.cs | 7 +++----
.../CSharp/Portable/Binder/Binder_Query.cs | 10 +++++-----
.../CSharp/Portable/Binder/Binder_Statements.cs | 8 ++++----
.../CSharp/Portable/Binder/Binder_Symbols.cs | 6 +++---
.../CSharp/Portable/Binder/ForEachLoopBinder.cs | 2 +-
.../Portable/Symbols/Source/LocalFunctionSymbol.cs | 4 ++--
8 files changed, 28 insertions(+), 24 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
index 665007f322edd..b622249501fab 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
@@ -904,7 +904,7 @@ private BoundExpression BindDeconstructionVariable(
// Use the binder that owns the scope for the local because this (the current) binder
// might own nested scope.
var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier, diagnostics);
if (declTypeWithAnnotations.HasType)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index 8e17bfe3287f2..c45ccb9cd6e6b 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -1598,7 +1598,7 @@ private BoundExpression BindIdentifier(
if (symbol is not SynthesizedAccessorValueParameterSymbol { Name: "value" })
{
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
}
}
else
@@ -1737,8 +1737,13 @@ void reportPrimaryConstructorParameterShadowing(SimpleNameSyntax node, Symbol sy
}
#nullable enable
- internal void ReportFieldOrValueContextualKeywordConflictIfAny(SyntaxNode syntax, string name, BindingDiagnosticBag diagnostics)
+ ///
+ /// Report a diagnostic for a 'field' or 'value' identifier that the meaning will
+ /// change when the identifier is considered a contextual keyword.
+ ///
+ internal void ReportFieldOrValueContextualKeywordConflictIfAny(SyntaxNode syntax, SyntaxToken identifier, BindingDiagnosticBag diagnostics)
{
+ string name = identifier.Text;
switch (name)
{
case "field" when ContainingMember() is MethodSymbol { MethodKind: MethodKind.PropertyGet or MethodKind.PropertySet, AssociatedSymbol: PropertySymbol { IsIndexer: false } }:
@@ -3114,7 +3119,7 @@ private BoundExpression BindOutVariableDeclarationArgument(
var designation = (SingleVariableDesignationSyntax)declarationExpression.Designation;
TypeSyntax typeSyntax = declarationExpression.Type;
- ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier, diagnostics);
// Is this a local?
SourceLocalSymbol localSymbol = this.LookupLocal(designation.Identifier);
@@ -7550,7 +7555,7 @@ private BoundExpression BindMemberAccessWithBoundLeft(
boundLeft = MakeMemberAccessValue(boundLeft, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(right, right.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(right, right.Identifier, diagnostics);
TypeSymbol leftType = boundLeft.Type;
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
index 9673fe71a09f4..fa9dd6aacadbd 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
@@ -69,7 +69,7 @@ private UnboundLambda AnalyzeAnonymousFunction(
// x => ...
hasSignature = true;
var simple = (SimpleLambdaExpressionSyntax)syntax;
- ReportFieldOrValueContextualKeywordConflictIfAny(simple.Parameter, simple.Parameter.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(simple.Parameter, simple.Parameter.Identifier, diagnostics);
namesBuilder.Add(simple.Parameter.Identifier.ValueText);
break;
case SyntaxKind.ParenthesizedLambdaExpression:
@@ -336,13 +336,12 @@ private void CheckParenthesizedLambdaParameters(
void checkParameter(bool hasType, ParameterSyntax param, BindingDiagnosticBag diagnostics)
{
- var text = param.Identifier.Text;
- ReportFieldOrValueContextualKeywordConflictIfAny(param, text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(param, param.Identifier, diagnostics);
if (!hasType && param.Default != null)
{
diagnostics.Add(ErrorCode.ERR_ImplicitlyTypedDefaultParameter,
- param.Identifier.GetLocation(), text);
+ param.Identifier.GetLocation(), param.Identifier.Text);
}
}
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
index e69f22c6b0e3c..e8ee3f804093c 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
@@ -28,7 +28,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
var fromClause = node.FromClause;
var boundFromExpression = BindLeftOfPotentialColorColorMemberAccess(fromClause.Expression, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(fromClause, fromClause.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(fromClause, fromClause.Identifier, diagnostics);
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
// Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
@@ -75,7 +75,7 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
// from ... into x ...
// is translated into
// from x in ( from ... ) ...
- ReportFieldOrValueContextualKeywordConflictIfAny(continuation, continuation.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(continuation, continuation.Identifier, diagnostics);
x = PrepareQueryTranslationStateForContinuation(state, continuation, diagnostics);
state.fromExpression = result;
@@ -382,10 +382,10 @@ private void ReduceJoin(JoinClauseSyntax join, QueryTranslationState state, Bind
{
var inExpression = BindRValueWithoutTargetType(join.InExpression, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(join, join.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(join, join.Identifier, diagnostics);
if (join.Into is { })
{
- ReportFieldOrValueContextualKeywordConflictIfAny(join.Into, join.Into.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(join.Into, join.Into.Identifier, diagnostics);
}
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
@@ -758,7 +758,7 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Binding
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(let.Expression, construction, d);
};
- ReportFieldOrValueContextualKeywordConflictIfAny(let, let.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(let, let.Identifier, diagnostics);
var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory, diagnostics.AccumulatesDependencies);
state.rangeVariable = state.TransparentRangeVariable(this);
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index fe952fe1b15b2..c4a771e1704ef 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -507,7 +507,7 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, BindingDi
diagnostics.Add(node, useSiteInfo);
result.Free();
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
var body = BindStatement(node.Statement, diagnostics);
return new BoundLabeledStatement(node, symbol, body, hasError);
@@ -561,7 +561,7 @@ private BoundStatement BindLocalFunctionStatement(LocalFunctionStatementSyntax n
{
MessageID.IDS_FeatureLocalFunctions.CheckFeatureAvailability(diagnostics, node.Identifier);
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
// already defined symbol in containing block
var localSymbol = this.LookupLocalFunction(node.Identifier);
@@ -1010,7 +1010,7 @@ protected BoundLocalDeclaration BindVariableDeclaration(
bool nameConflict = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
bool hasErrors = false;
- ReportFieldOrValueContextualKeywordConflictIfAny(declarator, declarator.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(declarator, declarator.Identifier, diagnostics);
if (localSymbol.RefKind != RefKind.None)
{
@@ -3164,7 +3164,7 @@ private BoundCatchBlock BindCatchBlock(CatchClauseSyntax node, ArrayBuilder useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
this.LookupSymbolsSimpleName(result, qualifierOpt, identifierValueText, 0, basesBeingResolved, options, diagnose: true, useSiteInfo: ref useSiteInfo);
@@ -1256,7 +1256,7 @@ private TypeWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol(
diagnostics);
}
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
return TypeWithAnnotations.Create(AreNullableAnnotationsEnabled(node.TypeArgumentList.GreaterThanToken), resultType);
}
diff --git a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
index 1012f178e4bc3..8a60227881fd5 100644
--- a/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
+++ b/src/Compilers/CSharp/Portable/Binder/ForEachLoopBinder.cs
@@ -222,7 +222,7 @@ private BoundForEachStatement BindForEachPartsWorker(BindingDiagnosticBag diagno
if (_syntax is ForEachStatementSyntax forEachStatement)
{
- ReportFieldOrValueContextualKeywordConflictIfAny(forEachStatement, forEachStatement.Identifier.Text, diagnostics);
+ ReportFieldOrValueContextualKeywordConflictIfAny(forEachStatement, forEachStatement.Identifier, diagnostics);
}
// Use the right binder to avoid seeing iteration variable
diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
index c42e5fce411a0..135b21292c1a7 100644
--- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
+++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs
@@ -203,7 +203,7 @@ private void ComputeParameters()
foreach (var parameter in this.Syntax.ParameterList.Parameters)
{
- WithTypeParametersBinder.ReportFieldOrValueContextualKeywordConflictIfAny(parameter, parameter.Identifier.Text, diagnostics);
+ WithTypeParametersBinder.ReportFieldOrValueContextualKeywordConflictIfAny(parameter, parameter.Identifier, diagnostics);
}
// Note: we don't need to warn on annotations used in #nullable disable context for local functions, as this is handled in binding already
@@ -437,7 +437,7 @@ private ImmutableArray MakeTypeParameters(Bindi
}
SourceMemberContainerTypeSymbol.ReportReservedTypeName(identifier.Text, this.DeclaringCompilation, diagnostics.DiagnosticBag, location);
- _binder.ReportFieldOrValueContextualKeywordConflictIfAny(parameter, identifier.Text, diagnostics);
+ _binder.ReportFieldOrValueContextualKeywordConflictIfAny(parameter, identifier, diagnostics);
var tpEnclosing = ContainingSymbol.FindEnclosingTypeParameter(name);
if ((object?)tpEnclosing != null)
From d418943a964bed13cebdbb21110821de1fcd0c13 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Mon, 3 Jun 2024 14:21:33 -0700
Subject: [PATCH 12/15] More langversion tests
---
.../Syntax/FieldAndValueKeywordTests.cs | 118 ++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 27a3d33913cb3..4e5e9809476fb 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -248,6 +248,124 @@ event EventHandler E3
}
}
+ [Theory]
+ [CombinatorialData]
+ public void ExplicitImplementation_01(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@field" : "field";
+ string source = $$"""
+ #pragma warning disable 649
+ interface I
+ {
+ object P { get; set; }
+ object this[int i] { get; set; }
+ }
+ class C : I
+ {
+ int field;
+ object I.P { get => {{identifier}}; set { _ = {{identifier}}; } }
+ object I.this[int i] { get => {{identifier}}; set { _ = {{identifier}}; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (10,25): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object I.P { get => field; set { _ = field; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 25),
+ // (10,42): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // object I.P { get => field; set { _ = field; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "field").WithArguments("field", "preview").WithLocation(10, 42));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void ExplicitImplementation_02(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ bool escapeIdentifier)
+ {
+ string identifier = escapeIdentifier ? "@value" : "value";
+ string source = $$"""
+ #pragma warning disable 649
+ interface I
+ {
+ object P { get; set; }
+ object this[int i] { get; set; }
+ }
+ class C : I
+ {
+ int value;
+ object I.P { get => this.{{identifier}}; set { _ = this.{{identifier}}; } }
+ object I.this[int i] { get => this.{{identifier}}; set { _ = this.{{identifier}}; } }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (escapeIdentifier || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (10,52): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object I.P { get => this.value; set { _ = this.value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(10, 52),
+ // (11,62): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // object I.this[int i] { get => this.value; set { _ = this.value; } }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(11, 62));
+ }
+ }
+
+ [Theory]
+ [CombinatorialData]
+ public void ExplicitImplementation_03(
+ [CombinatorialValues(LanguageVersion.CSharp12, LanguageVersion.Preview)] LanguageVersion languageVersion,
+ [CombinatorialValues("field", "value")] string identifier,
+ bool escapeIdentifier)
+ {
+ string qualifiedIdentifier = (escapeIdentifier ? "@" : "") + identifier;
+ string source = $$"""
+ #pragma warning disable 649
+ using System;
+ interface I
+ {
+ event EventHandler E;
+ }
+ class C : I
+ {
+ int {{identifier}};
+ event EventHandler I.E
+ {
+ add { _ = this.{{qualifiedIdentifier}}; }
+ remove { _ = this.{{qualifiedIdentifier}}; }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular.WithLanguageVersion(languageVersion));
+ if (escapeIdentifier || identifier == "field" || languageVersion > LanguageVersion.CSharp12)
+ {
+ comp.VerifyEmitDiagnostics();
+ }
+ else
+ {
+ comp.VerifyEmitDiagnostics(
+ // (12,24): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // add { _ = this.value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(12, 24),
+ // (13,27): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // remove { _ = this.value; }
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(13, 27));
+ }
+ }
+
[Theory]
[CombinatorialData]
public void IdentifierToken_IdentifierNameSyntax(
From 9b059206bfd224d2ac46964fb94afc26894412bc Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Tue, 4 Jun 2024 06:24:46 -0700
Subject: [PATCH 13/15] Address feedback
---
.../Portable/Binder/Binder_Deconstruct.cs | 3 +-
.../Portable/Binder/Binder_Expressions.cs | 10 +++----
.../CSharp/Portable/Binder/Binder_Lambda.cs | 12 ++++----
.../Syntax/FieldAndValueKeywordTests.cs | 29 +++++++++++++++++++
4 files changed, 42 insertions(+), 12 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
index b622249501fab..95cba95f8b1ab 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs
@@ -869,6 +869,8 @@ private BoundExpression BindDeconstructionVariable(
{
SourceLocalSymbol localSymbol = LookupLocal(designation.Identifier);
+ ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier, diagnostics);
+
// is this a local?
if ((object)localSymbol != null)
{
@@ -904,7 +906,6 @@ private BoundExpression BindDeconstructionVariable(
// Use the binder that owns the scope for the local because this (the current) binder
// might own nested scope.
var hasErrors = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(designation, designation.Identifier, diagnostics);
if (declTypeWithAnnotations.HasType)
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
index c45ccb9cd6e6b..c71c28821cff9 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs
@@ -1549,6 +1549,11 @@ private BoundExpression BindIdentifier(
var members = ArrayBuilder.GetInstance();
Symbol symbol = GetSymbolOrMethodOrPropertyGroup(lookupResult, node, name, node.Arity, members, diagnostics, out isError, qualifierOpt: null); // reports diagnostics in result.
+ if (symbol is not SynthesizedAccessorValueParameterSymbol { Name: "value" })
+ {
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
+ }
+
if ((object)symbol == null)
{
Debug.Assert(members.Count > 0);
@@ -1595,11 +1600,6 @@ private BoundExpression BindIdentifier(
// Note, this call can clear and reuse lookupResult and members
reportPrimaryConstructorParameterShadowing(node, symbol ?? members[0], name, invoked, lookupResult, members, diagnostics);
members.Free();
-
- if (symbol is not SynthesizedAccessorValueParameterSymbol { Name: "value" })
- {
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
- }
}
else
{
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
index fa9dd6aacadbd..9fbebe75d6656 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Lambda.cs
@@ -193,6 +193,8 @@ private UnboundLambda AnalyzeAnonymousFunction(
}
}
+ ReportFieldOrValueContextualKeywordConflictIfAny(p, p.Identifier, diagnostics);
+
namesBuilder.Add(p.Identifier.ValueText);
typesBuilder.Add(type);
refKindsBuilder.Add(refKind);
@@ -304,14 +306,14 @@ static void checkAttributes(AnonymousFunctionExpressionSyntax syntax, SyntaxList
return (refKind, returnType);
}
- private void CheckParenthesizedLambdaParameters(
+ private static void CheckParenthesizedLambdaParameters(
SeparatedSyntaxList parameterSyntaxList, BindingDiagnosticBag diagnostics)
{
if (parameterSyntaxList.Count > 0)
{
var hasTypes = parameterSyntaxList[0].Type != null;
- checkParameter(hasTypes, parameterSyntaxList[0], diagnostics);
+ checkForImplicitDefault(hasTypes, parameterSyntaxList[0], diagnostics);
for (int i = 1, n = parameterSyntaxList.Count; i < n; i++)
{
@@ -329,15 +331,13 @@ private void CheckParenthesizedLambdaParameters(
parameter.Type?.GetLocation() ?? parameter.Identifier.GetLocation());
}
- checkParameter(thisParameterHasType, parameter, diagnostics);
+ checkForImplicitDefault(thisParameterHasType, parameter, diagnostics);
}
}
}
- void checkParameter(bool hasType, ParameterSyntax param, BindingDiagnosticBag diagnostics)
+ static void checkForImplicitDefault(bool hasType, ParameterSyntax param, BindingDiagnosticBag diagnostics)
{
- ReportFieldOrValueContextualKeywordConflictIfAny(param, param.Identifier, diagnostics);
-
if (!hasType && param.Default != null)
{
diagnostics.Add(ErrorCode.ERR_ImplicitlyTypedDefaultParameter,
diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
index 4e5e9809476fb..5532bd92677d2 100644
--- a/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Syntax/FieldAndValueKeywordTests.cs
@@ -1352,6 +1352,35 @@ object P
Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "value").WithArguments("value", "preview").WithLocation(11, 26));
}
+ [Fact]
+ public void Lambda_Parameter_03()
+ {
+ string source = """
+ #pragma warning disable 649
+ using System;
+ class C
+ {
+ object P
+ {
+ set
+ {
+ Action a;
+ a = delegate (object field, object @value) { };
+ a = delegate (object @field, object value) { };
+ }
+ }
+ }
+ """;
+ var comp = CreateCompilation(source, parseOptions: TestOptions.Regular12);
+ comp.VerifyEmitDiagnostics(
+ // (10,27): info CS9258: 'field' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@field' to avoid a breaking change when compiling with language version preview or later.
+ // a = delegate (object field, object @value) { };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object field").WithArguments("field", "preview").WithLocation(10, 27),
+ // (11,42): info CS9258: 'value' is a contextual keyword, with a specific meaning, starting in language version preview. Use '@value' to avoid a breaking change when compiling with language version preview or later.
+ // a = delegate (object @field, object value) { };
+ Diagnostic(ErrorCode.INF_IdentifierConflictWithContextualKeyword, "object value").WithArguments("value", "preview").WithLocation(11, 42));
+ }
+
[Fact]
public void LocalFunction_Local()
{
From d829a41fe472231db5e2bfac709554352ae5eb10 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Tue, 4 Jun 2024 06:54:39 -0700
Subject: [PATCH 14/15] Address feedback
---
.../Portable/Binder/Binder.QueryTranslationState.cs | 3 +++
src/Compilers/CSharp/Portable/Binder/Binder_Query.cs | 11 -----------
.../CSharp/Portable/Binder/Binder_Statements.cs | 4 ++--
3 files changed, 5 insertions(+), 13 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder.QueryTranslationState.cs b/src/Compilers/CSharp/Portable/Binder/Binder.QueryTranslationState.cs
index 6449a041ad43a..f478125bd43d7 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder.QueryTranslationState.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder.QueryTranslationState.cs
@@ -75,6 +75,9 @@ internal RangeVariableSymbol AddRangeVariable(Binder binder, SyntaxToken identif
var result = new RangeVariableSymbol(name, binder.ContainingMemberOrLambda, identifier.GetLocation());
bool error = false;
+ Debug.Assert(identifier.Parent is { });
+ binder.ReportFieldOrValueContextualKeywordConflictIfAny(identifier.Parent, identifier, diagnostics);
+
foreach (var existingRangeVariable in allRangeVariables.Keys)
{
if (existingRangeVariable.Name == name)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
index e8ee3f804093c..491a87033364c 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Query.cs
@@ -28,8 +28,6 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
var fromClause = node.FromClause;
var boundFromExpression = BindLeftOfPotentialColorColorMemberAccess(fromClause.Expression, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(fromClause, fromClause.Identifier, diagnostics);
-
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
// Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
if (boundFromExpression.HasDynamicType())
@@ -75,7 +73,6 @@ internal BoundExpression BindQuery(QueryExpressionSyntax node, BindingDiagnostic
// from ... into x ...
// is translated into
// from x in ( from ... ) ...
- ReportFieldOrValueContextualKeywordConflictIfAny(continuation, continuation.Identifier, diagnostics);
x = PrepareQueryTranslationStateForContinuation(state, continuation, diagnostics);
state.fromExpression = result;
@@ -382,12 +379,6 @@ private void ReduceJoin(JoinClauseSyntax join, QueryTranslationState state, Bind
{
var inExpression = BindRValueWithoutTargetType(join.InExpression, diagnostics);
- ReportFieldOrValueContextualKeywordConflictIfAny(join, join.Identifier, diagnostics);
- if (join.Into is { })
- {
- ReportFieldOrValueContextualKeywordConflictIfAny(join.Into, join.Into.Identifier, diagnostics);
- }
-
// If the from expression is of the type dynamic we can't infer the types for any lambdas that occur in the query.
// Only if there are none we could bind the query but we report an error regardless since such queries are not useful.
if (inExpression.HasDynamicType())
@@ -758,8 +749,6 @@ private void ReduceLet(LetClauseSyntax let, QueryTranslationState state, Binding
return lambdaBodyBinder.CreateLambdaBlockForQueryClause(let.Expression, construction, d);
};
- ReportFieldOrValueContextualKeywordConflictIfAny(let, let.Identifier, diagnostics);
-
var lambda = MakeQueryUnboundLambda(state.RangeVariableMap(), ImmutableArray.Create(x), let.Expression, bodyFactory, diagnostics.AccumulatesDependencies);
state.rangeVariable = state.TransparentRangeVariable(this);
state.AddTransparentIdentifier(x.Name);
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index c4a771e1704ef..4562ded4945ba 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -479,6 +479,8 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, BindingDi
CompoundUseSiteInfo useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics);
var binder = this.LookupSymbolsWithFallback(result, node.Identifier.ValueText, arity: 0, useSiteInfo: ref useSiteInfo, options: LookupOptions.LabelsOnly);
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
+
// result.Symbols can be empty in some malformed code, e.g. when a labeled statement is used an embedded statement in an if or foreach statement
// In this case we create new label symbol on the fly, and an error is reported by parser
var symbol = result.Symbols.Count > 0 && result.IsMultiViable ?
@@ -507,8 +509,6 @@ private BoundLabeledStatement BindLabeled(LabeledStatementSyntax node, BindingDi
diagnostics.Add(node, useSiteInfo);
result.Free();
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
-
var body = BindStatement(node.Statement, diagnostics);
return new BoundLabeledStatement(node, symbol, body, hasError);
}
From 435a126af08c3292340bbcfe0e3356a08e3c9106 Mon Sep 17 00:00:00 2001
From: Charles Stoner <10732005+cston@users.noreply.github.com>
Date: Tue, 4 Jun 2024 08:33:21 -0700
Subject: [PATCH 15/15] Address feedback
---
src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs | 8 ++++----
src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs | 4 ++--
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
index 4562ded4945ba..9eb86f47b11ca 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Statements.cs
@@ -972,7 +972,7 @@ protected BoundLocalDeclaration BindVariableDeclaration(
{
Debug.Assert(declarator != null);
- return BindVariableDeclaration(LocateDeclaredVariableSymbol(declarator, typeSyntax, kind),
+ return BindVariableDeclaration(LocateDeclaredVariableSymbol(declarator, typeSyntax, kind, diagnostics),
kind,
isVar,
declarator,
@@ -1010,8 +1010,6 @@ protected BoundLocalDeclaration BindVariableDeclaration(
bool nameConflict = localSymbol.ScopeBinder.ValidateDeclarationNameConflictsInScope(localSymbol, diagnostics);
bool hasErrors = false;
- ReportFieldOrValueContextualKeywordConflictIfAny(declarator, declarator.Identifier, diagnostics);
-
if (localSymbol.RefKind != RefKind.None)
{
CheckRefLocalInAsyncOrIteratorMethod(localSymbol.IdentifierToken, diagnostics);
@@ -1208,8 +1206,10 @@ internal ImmutableArray BindDeclaratorArguments(VariableDeclara
return arguments;
}
- private SourceLocalSymbol LocateDeclaredVariableSymbol(VariableDeclaratorSyntax declarator, TypeSyntax typeSyntax, LocalDeclarationKind outerKind)
+ private SourceLocalSymbol LocateDeclaredVariableSymbol(VariableDeclaratorSyntax declarator, TypeSyntax typeSyntax, LocalDeclarationKind outerKind, BindingDiagnosticBag diagnostics)
{
+ ReportFieldOrValueContextualKeywordConflictIfAny(declarator, declarator.Identifier, diagnostics);
+
LocalDeclarationKind kind = outerKind == LocalDeclarationKind.UsingVariable ? LocalDeclarationKind.UsingVariable : LocalDeclarationKind.RegularVariable;
return LocateDeclaredVariableSymbol(declarator.Identifier, typeSyntax, declarator.Initializer, kind);
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
index 677b45c02ab63..7348adcb88de9 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
@@ -1213,6 +1213,8 @@ private TypeWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol(
diagnostics, basesBeingResolved, qualifierOpt, node, plainName, node.Arity, options);
NamedTypeSymbol resultType;
+ ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
+
if (isUnboundTypeExpr)
{
if (!IsUnboundTypeAllowed(node))
@@ -1256,8 +1258,6 @@ private TypeWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol(
diagnostics);
}
- ReportFieldOrValueContextualKeywordConflictIfAny(node, node.Identifier, diagnostics);
-
return TypeWithAnnotations.Create(AreNullableAnnotationsEnabled(node.TypeArgumentList.GreaterThanToken), resultType);
}