From 8beed73fdb26ce9c7bf3aed2e6ffc6fd76286837 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Wed, 23 Mar 2022 14:49:45 +0200 Subject: [PATCH 1/4] [semi-auto-props]: Disallow 'nameof(field)' --- .../Portable/Binder/Binder_Expressions.cs | 3 +- .../Semantics/PropertyFieldKeywordTests.cs | 82 +++++-------------- 2 files changed, 23 insertions(+), 62 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index d17db8b7d80f8..4e1e8833aec3a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1557,7 +1557,8 @@ private BoundExpression BindIdentifier( // Cannot escape out of the current expression, as it's a compiler-synthesized location. expression = new BoundDiscardExpression(node, LocalScopeDepth, type: null); } - else if (node.Identifier.ContextualKind() == SyntaxKind.FieldKeyword && + else if (!IsInsideNameof && + node.Identifier.ContextualKind() == SyntaxKind.FieldKeyword && // PROTOTYPE(semi-auto-props): Use ContainingMember() to support local functions and lambdas. ContainingMemberOrLambda is SourcePropertyAccessorSymbol { Property.IsIndexer: false } accessor) { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs index 0259715de6a14..591de0e2b12b1 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs @@ -105,58 +105,11 @@ public class MyAttribute : System.Attribute public MyAttribute(string s) { } } "); - comp.VerifyDiagnostics(); - VerifyTypeIL(comp, "C", @" -.class public auto ansi beforefieldinit C - extends [mscorlib]System.Object -{ - // Fields - .field private initonly int32 '

k__BackingField' - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - // Methods - .method public hidebysig specialname - instance int32 get_P () cil managed - { - // Method begins at RVA 0x2050 - // Code size 6 (0x6) - .maxstack 8 - IL_0000: call int32 C::'g__local|1_0'() - IL_0005: ret - } // end of method C::get_P - .method public hidebysig specialname rtspecialname - instance void .ctor () cil managed - { - // Method begins at RVA 0x2057 - // Code size 7 (0x7) - .maxstack 8 - IL_0000: ldarg.0 - IL_0001: call instance void [mscorlib]System.Object::.ctor() - IL_0006: ret - } // end of method C::.ctor - .method assembly hidebysig static - int32 'g__local|1_0' () cil managed - { - .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( - 01 00 00 00 - ) - .custom instance void MyAttribute::.ctor(string) = ( - 01 00 05 66 69 65 6c 64 00 00 - ) - // Method begins at RVA 0x205f - // Code size 2 (0x2) - .maxstack 8 - IL_0000: ldc.i4.0 - IL_0001: ret - } // end of method C::'g__local|1_0' - // Properties - .property instance int32 P() - { - .get instance int32 C::get_P() - } -} // end of class C -"); + comp.VerifyDiagnostics( + // (10,24): error CS0103: The name 'field' does not exist in the current context + // [My(nameof(field))] + Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(10, 24) + ); } [Fact(Skip = "PROTOTYPE(semi-auto-props): Assigning in constructor is not yet supported.")] @@ -3839,16 +3792,20 @@ public MyAttribute(string s) { } Assert.Equal("System.Int32 C.

k__BackingField", comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single().ToTestDisplayString()); var fieldKeywordSymbolInfo = speculativeModel.GetSymbolInfo(fieldNode); + + // Since we're passing fieldNode, the model don't know we're inside nameof, so field is bound to backing field. + // This doesn't match fieldKeywordSymbolInfo where semantic model is aware we're inside nameof and doesn't bind to backing. var fieldKeywordSymbolInfo2 = model.GetSpeculativeSymbolInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); + + Assert.True(fieldKeywordSymbolInfo.IsEmpty); + Assert.Null(fieldKeywordSymbolInfo.Symbol); if (bindingOption == SpeculativeBindingOption.BindAsTypeOrNamespace) { - Assert.True(fieldKeywordSymbolInfo2.IsEmpty); - Assert.Null(fieldKeywordSymbolInfo2.Symbol); + Assert.Equal(fieldKeywordSymbolInfo2, fieldKeywordSymbolInfo); } else { - Assert.Equal(fieldKeywordSymbolInfo, fieldKeywordSymbolInfo2); - Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo.Symbol.GetSymbol()); + Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo2.Symbol.GetSymbol()); } var typeInfo = model.GetSpeculativeTypeInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); @@ -3901,15 +3858,19 @@ public MyAttribute(string s) { } model.TryGetSpeculativeSemanticModel(attributeSyntax.SpanStart, newAttributeSyntax, out var speculativeModel); var fieldKeywordSymbolInfo = speculativeModel.GetSymbolInfo(fieldNode); + + // Since we're passing fieldNode, the model don't know we're inside nameof, so field is bound to backing field. + // This doesn't match fieldKeywordSymbolInfo where semantic model is aware we're inside nameof and doesn't bind to backing. var fieldKeywordSymbolInfo2 = model.GetSpeculativeSymbolInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); - if (bindingOption == SpeculativeBindingOption.BindAsExpression) + Assert.True(fieldKeywordSymbolInfo.IsEmpty); + Assert.Null(fieldKeywordSymbolInfo.Symbol); + if (bindingOption == SpeculativeBindingOption.BindAsTypeOrNamespace) { - Assert.Equal(fieldKeywordSymbolInfo, fieldKeywordSymbolInfo2); + Assert.Equal(fieldKeywordSymbolInfo2, fieldKeywordSymbolInfo); } else { - Assert.True(fieldKeywordSymbolInfo2.IsEmpty); - Assert.Null(fieldKeywordSymbolInfo2.Symbol); + Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo2.Symbol.GetSymbol()); } var typeInfo = model.GetSpeculativeTypeInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); @@ -3921,7 +3882,6 @@ public MyAttribute(string s) { } Assert.Null(aliasInfo); Assert.Equal("System.Int32 C.

k__BackingField", comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single().ToTestDisplayString()); - Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo.Symbol.GetSymbol()); Assert.Equal(runNullableAnalysis == "always" ? 0 : 1, accessorBindingData.NumberOfPerformedAccessorBinding); } From 215346244d5ae37c3f11ee85fa97c159cf480e87 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 25 Mar 2022 20:39:05 +0200 Subject: [PATCH 2/4] Add more tests --- .../Semantics/PropertyFieldKeywordTests.cs | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs index 591de0e2b12b1..f2fd8098c63e3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs @@ -112,6 +112,170 @@ public MyAttribute(string s) { } ); } + [Fact] + public void TestNameOfField() + { + var comp = CreateCompilation(@" +public class C +{ + public int P + { + get + { + return nameof(field); + } + } +} +"); + comp.VerifyDiagnostics( + // (8,27): error CS0103: The name 'field' does not exist in the current context + // return nameof(field); + Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(8, 27) + ); + } + + [Fact] + public void TestNameOfField_NameofIsMethodInvocation() + { + var comp = CreateCompilation(@" +public class C +{ + public int P + { + get + { + return nameof(field); + } + } + + public int nameof(int x) => 0; +} +"); + comp.VerifyDiagnostics(); + VerifyTypeIL(comp, "C", @" +.class public auto ansi beforefieldinit C + extends [mscorlib]System.Object +{ + // Fields + .field private initonly int32 '

k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname + instance int32 get_P () cil managed + { + // Method begins at RVA 0x2050 + // Code size 13 (0xd) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldarg.0 + IL_0002: ldfld int32 C::'

k__BackingField' + IL_0007: call instance int32 C::nameof(int32) + IL_000c: ret + } // end of method C::get_P + .method public hidebysig + instance int32 nameof ( + int32 x + ) cil managed + { + // Method begins at RVA 0x205e + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } // end of method C::nameof + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x2061 + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method C::.ctor + // Properties + .property instance int32 P() + { + .get instance int32 C::get_P() + } +} // end of class C +"); + } + + [Fact] + public void TestNameOfField_NameofIsLocalFunctionInvocation() + { + var comp = CreateCompilation(@" +public class C +{ + public int P + { + get + { + return nameof(field); + + int nameof(int x) => 0; + } + } +} +"); + comp.VerifyDiagnostics(); + VerifyTypeIL(comp, "C", @" +.class public auto ansi beforefieldinit C + extends [mscorlib]System.Object +{ + // Fields + .field private initonly int32 '

k__BackingField' + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Methods + .method public hidebysig specialname + instance int32 get_P () cil managed + { + // Method begins at RVA 0x2050 + // Code size 12 (0xc) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: ldfld int32 C::'

k__BackingField' + IL_0006: call int32 C::'g__nameof|1_0'(int32) + IL_000b: ret + } // end of method C::get_P + .method public hidebysig specialname rtspecialname + instance void .ctor () cil managed + { + // Method begins at RVA 0x205d + // Code size 7 (0x7) + .maxstack 8 + IL_0000: ldarg.0 + IL_0001: call instance void [mscorlib]System.Object::.ctor() + IL_0006: ret + } // end of method C::.ctor + .method assembly hidebysig static + int32 'g__nameof|1_0' ( + int32 x + ) cil managed + { + .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = ( + 01 00 00 00 + ) + // Method begins at RVA 0x2065 + // Code size 2 (0x2) + .maxstack 8 + IL_0000: ldc.i4.0 + IL_0001: ret + } // end of method C::'g__nameof|1_0' + // Properties + .property instance int32 P() + { + .get instance int32 C::get_P() + } +} // end of class C +"); + } + [Fact(Skip = "PROTOTYPE(semi-auto-props): Assigning in constructor is not yet supported.")] public void TestFieldOnlyGetter() { From d196e24b8de0d44924d621b34cf903f94895cb43 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Fri, 1 Apr 2022 14:25:23 +0200 Subject: [PATCH 3/4] Add suggested test --- .../Semantics/PropertyFieldKeywordTests.cs | 40 +++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs index f2fd8098c63e3..4fb73fc4e427e 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs @@ -105,11 +105,14 @@ public class MyAttribute : System.Attribute public MyAttribute(string s) { } } "); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; comp.VerifyDiagnostics( // (10,24): error CS0103: The name 'field' does not exist in the current context // [My(nameof(field))] Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(10, 24) ); + Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } [Fact] @@ -127,11 +130,14 @@ public int P } } "); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; comp.VerifyDiagnostics( // (8,27): error CS0103: The name 'field' does not exist in the current context // return nameof(field); Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(8, 27) ); + Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } [Fact] @@ -151,6 +157,8 @@ public int P public int nameof(int x) => 0; } "); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; comp.VerifyDiagnostics(); VerifyTypeIL(comp, "C", @" .class public auto ansi beforefieldinit C @@ -202,6 +210,7 @@ .property instance int32 P() } } // end of class C "); + Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } [Fact] @@ -221,6 +230,8 @@ public int P } } "); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; comp.VerifyDiagnostics(); VerifyTypeIL(comp, "C", @" .class public auto ansi beforefieldinit C @@ -274,6 +285,35 @@ .property instance int32 P() } } // end of class C "); + Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); + } + + [Theory] + [InlineData("private void field() { }")] + [InlineData("private int field { get => 0; }")] + [InlineData("private int field;")] + public void TestNameOfField_FieldIsMember(string member) + { + var comp = CreateCompilation($@" +System.Console.WriteLine(new C().P); + +public class C +{{ + {member} + + public string P + {{ + get + {{ + return nameof(field); + }} + }} +}} +"); + var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); + comp.TestOnlyCompilationData = accessorBindingData; + CompileAndVerify(comp, expectedOutput: "field"); + Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } [Fact(Skip = "PROTOTYPE(semi-auto-props): Assigning in constructor is not yet supported.")] From 61d2d8e3941771d6c20d91c85ec4bc5549df57b4 Mon Sep 17 00:00:00 2001 From: Youssef1313 Date: Mon, 4 Apr 2022 17:10:42 +0200 Subject: [PATCH 4/4] Address review comment --- .../Portable/Binder/Binder_Expressions.cs | 7 ++-- .../CSharp/Portable/CSharpResources.resx | 3 ++ .../CSharp/Portable/Errors/ErrorCode.cs | 2 ++ .../Portable/xlf/CSharpResources.cs.xlf | 5 +++ .../Portable/xlf/CSharpResources.de.xlf | 5 +++ .../Portable/xlf/CSharpResources.es.xlf | 5 +++ .../Portable/xlf/CSharpResources.fr.xlf | 5 +++ .../Portable/xlf/CSharpResources.it.xlf | 5 +++ .../Portable/xlf/CSharpResources.ja.xlf | 5 +++ .../Portable/xlf/CSharpResources.ko.xlf | 5 +++ .../Portable/xlf/CSharpResources.pl.xlf | 5 +++ .../Portable/xlf/CSharpResources.pt-BR.xlf | 5 +++ .../Portable/xlf/CSharpResources.ru.xlf | 5 +++ .../Portable/xlf/CSharpResources.tr.xlf | 5 +++ .../Portable/xlf/CSharpResources.zh-Hans.xlf | 5 +++ .../Portable/xlf/CSharpResources.zh-Hant.xlf | 5 +++ .../Semantics/PropertyFieldKeywordTests.cs | 34 +++++++++---------- 17 files changed, 91 insertions(+), 20 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 4e1e8833aec3a..0e515f49875aa 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -1557,14 +1557,17 @@ private BoundExpression BindIdentifier( // Cannot escape out of the current expression, as it's a compiler-synthesized location. expression = new BoundDiscardExpression(node, LocalScopeDepth, type: null); } - else if (!IsInsideNameof && - node.Identifier.ContextualKind() == SyntaxKind.FieldKeyword && + else if (node.Identifier.ContextualKind() == SyntaxKind.FieldKeyword && // PROTOTYPE(semi-auto-props): Use ContainingMember() to support local functions and lambdas. ContainingMemberOrLambda is SourcePropertyAccessorSymbol { Property.IsIndexer: false } accessor) { if (GetSymbolForPossibleFieldKeyword() is { } backingField) { expression = BindNonMethod(node, backingField, diagnostics, LookupResultKind.Viable, indexed: false, isError: false); + if (IsInsideNameof) + { + Error(diagnostics, ErrorCode.ERR_FieldKeywordInsideNameOf, node); + } } } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 3abfac0e83f71..7eb0b8a3802b3 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -7001,4 +7001,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Unexpected keyword 'record'. Did you mean 'record struct' or 'record class'? + + Cannot use 'field' keyword inside 'nameof' expressions. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 4b07492640e46..cafbaa6e06359 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2050,6 +2050,8 @@ internal enum ErrorCode ERR_NoDelegateConstraint = 9011, ERR_MisplacedRecord = 9012, + ERR_FieldKeywordInsideNameOf = 9013, + #endregion // Note: you will need to re-generate compiler code after adding warnings (eng\generate-compiler-code.cmd) diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index f68dcd3be5136..37119e712aa13 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -532,6 +532,11 @@ Funkce {0} není v C# 9.0 dostupná. Použijte prosím jazykovou verzi {1} nebo větší. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. Událost podobná poli {0} nemůže mít modifikátor readonly. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 508a996c17c0b..cb70dcf30c5cb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -532,6 +532,11 @@ Die Funktion "{0}" ist in C# 9.0 nicht verfügbar. Verwenden Sie Sprachversion {1} oder höher. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. Ein feldähnliches Ereignis "{0}" darf nicht "readonly" sein. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 2908ff4afb81a..bd64294278d02 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -532,6 +532,11 @@ La característica "{0}" no está disponible en C# 9.0. Use la versión {1} del lenguaje o una posterior. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. El evento de tipo campo "{0}" no puede ser "readonly". diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index bbca3ed9d5fdd..768d4eb2c1d3f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -532,6 +532,11 @@ La fonctionnalité '{0}' n'est pas disponible en C# 9.0. Utilisez la version de langage {1} ou une version ultérieure. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. L'événement de type champ '{0}' ne peut pas être 'readonly'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index cbab7dce34dbc..f579173609b8d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -532,6 +532,11 @@ La funzionalità '{0}' non è disponibile in C# 9.0. Usare la versione {1} o versioni successive del linguaggio. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. L'evento simile a campo '{0}' non può essere 'readonly'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 794537811a0e8..98ef7d7367289 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -532,6 +532,11 @@ 機能 '{0}' は C# 9.0 では使用できません。言語バージョン {1} 以上を使用してください。 + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. フィールドに類似したイベント '{0}' を 'readonly' にすることはできません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 6e2f95eade78b..4baf018b78d8c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -532,6 +532,11 @@ '{0}' 기능은 C# 9.0에서 사용할 수 없습니다. {1} 이상의 언어 버전을 사용하세요. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. 필드와 유사한 이벤트 '{0}'이(가) 'readonly'일 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index c18e47055be97..b89134579c9a9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -532,6 +532,11 @@ Funkcja „{0}” nie jest dostępna w języku C# 9.0. Użyj języka w wersji {1} lub nowszej. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. Zdarzenie-pole „{0}” nie może być zadeklarowane jako „readonly”. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index fd93d2f204ded..81fd4a3b46f66 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -532,6 +532,11 @@ O recurso '{0}' não está disponível no C# 9.0. Use a versão da linguagem {1} ou superior. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. O evento '{0}' semelhante ao de campo não pode ser 'readonly'. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 1a91c5e5625ec..fb2cc16e03c03 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -532,6 +532,11 @@ Функция "{0}" недоступна в C# 9.0. Используйте как минимум версию языка {1}. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. Подобное полю событие "{0}" не может быть readonly. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 9f7b4fb609c52..5dc93241e253a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -532,6 +532,11 @@ '{0}' özelliği C# 9.0'da kullanılamıyor. Lütfen {1} veya daha yüksek dil sürümünü kullanın. + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. Alan benzeri '{0}' olayı 'readonly' olamaz. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 01d54adcd19b0..99a8d4a41389f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -532,6 +532,11 @@ 功能“{0}”在 C# 9.0 中不可用。请使用语言版本 {1} 或更高版本。 + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. 类似字段的事件 "{0}" 不能为 "readonly"。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 85cdecf84ae38..eb9751002831f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -532,6 +532,11 @@ 在 C# 9.0 中無法使用 '{0}' 功能。請使用語言版本 {1} 或更高的版本。 + + Cannot use 'field' keyword inside 'nameof' expressions. + Cannot use 'field' keyword inside 'nameof' expressions. + + Field-like event '{0}' cannot be 'readonly'. 類似欄位的事件 '{0}' 不能是 'readonly'。 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs index 4fb73fc4e427e..07c4644635ce2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/PropertyFieldKeywordTests.cs @@ -108,9 +108,9 @@ public MyAttribute(string s) { } var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); comp.TestOnlyCompilationData = accessorBindingData; comp.VerifyDiagnostics( - // (10,24): error CS0103: The name 'field' does not exist in the current context + // (10,24): error CS9013: Cannot use 'field' keyword inside 'nameof' expressions. // [My(nameof(field))] - Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(10, 24) + Diagnostic(ErrorCode.ERR_FieldKeywordInsideNameOf, "field").WithLocation(10, 24) ); Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } @@ -133,9 +133,12 @@ public int P var accessorBindingData = new SourcePropertySymbolBase.AccessorBindingData(); comp.TestOnlyCompilationData = accessorBindingData; comp.VerifyDiagnostics( - // (8,27): error CS0103: The name 'field' does not exist in the current context + // (8,20): error CS0029: Cannot implicitly convert type 'string' to 'int' // return nameof(field); - Diagnostic(ErrorCode.ERR_NameNotInContext, "field").WithArguments("field").WithLocation(8, 27) + Diagnostic(ErrorCode.ERR_NoImplicitConv, "nameof(field)").WithArguments("string", "int").WithLocation(8, 20), + // (8,27): error CS9013: Cannot use 'field' keyword inside 'nameof' expressions. + // return nameof(field); + Diagnostic(ErrorCode.ERR_FieldKeywordInsideNameOf, "field").WithLocation(8, 27) ); Assert.Equal(0, accessorBindingData.NumberOfPerformedAccessorBinding); } @@ -3996,20 +3999,17 @@ public MyAttribute(string s) { } Assert.Equal("System.Int32 C.

k__BackingField", comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single().ToTestDisplayString()); var fieldKeywordSymbolInfo = speculativeModel.GetSymbolInfo(fieldNode); - - // Since we're passing fieldNode, the model don't know we're inside nameof, so field is bound to backing field. - // This doesn't match fieldKeywordSymbolInfo where semantic model is aware we're inside nameof and doesn't bind to backing. var fieldKeywordSymbolInfo2 = model.GetSpeculativeSymbolInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); + Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo.Symbol.GetSymbol()); - Assert.True(fieldKeywordSymbolInfo.IsEmpty); - Assert.Null(fieldKeywordSymbolInfo.Symbol); if (bindingOption == SpeculativeBindingOption.BindAsTypeOrNamespace) { - Assert.Equal(fieldKeywordSymbolInfo2, fieldKeywordSymbolInfo); + Assert.True(fieldKeywordSymbolInfo2.IsEmpty); + Assert.Null(fieldKeywordSymbolInfo2.Symbol); } else { - Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo2.Symbol.GetSymbol()); + Assert.Equal(fieldKeywordSymbolInfo2, fieldKeywordSymbolInfo); } var typeInfo = model.GetSpeculativeTypeInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); @@ -4062,19 +4062,17 @@ public MyAttribute(string s) { } model.TryGetSpeculativeSemanticModel(attributeSyntax.SpanStart, newAttributeSyntax, out var speculativeModel); var fieldKeywordSymbolInfo = speculativeModel.GetSymbolInfo(fieldNode); - - // Since we're passing fieldNode, the model don't know we're inside nameof, so field is bound to backing field. - // This doesn't match fieldKeywordSymbolInfo where semantic model is aware we're inside nameof and doesn't bind to backing. var fieldKeywordSymbolInfo2 = model.GetSpeculativeSymbolInfo(attributeSyntax.SpanStart, fieldNode, bindingOption); - Assert.True(fieldKeywordSymbolInfo.IsEmpty); - Assert.Null(fieldKeywordSymbolInfo.Symbol); + Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo.Symbol.GetSymbol()); + if (bindingOption == SpeculativeBindingOption.BindAsTypeOrNamespace) { - Assert.Equal(fieldKeywordSymbolInfo2, fieldKeywordSymbolInfo); + Assert.True(fieldKeywordSymbolInfo2.IsEmpty); + Assert.Null(fieldKeywordSymbolInfo2.Symbol); } else { - Assert.Equal(comp.GetTypeByMetadataName("C").GetFieldsToEmit().Single(), fieldKeywordSymbolInfo2.Symbol.GetSymbol()); + Assert.Equal(fieldKeywordSymbolInfo2, fieldKeywordSymbolInfo); } var typeInfo = model.GetSpeculativeTypeInfo(attributeSyntax.SpanStart, fieldNode, bindingOption);