diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index c422390669276..554c92a3cd9e4 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6416,6 +6416,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Members named 'Clone' are disallowed in records. + + A type should not be named 'record'. + + + A type should not be named 'record'. + '{0}' must allow overriding because the containing record is not sealed. diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 33f59d087a838..93997a8972abb 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1853,7 +1853,7 @@ internal enum ErrorCode ERR_InvalidWithReceiverType = 8857, ERR_NoSingleCloneMethod = 8858, ERR_CloneDisallowedInRecord = 8859, - // available = 8860, + WRN_RecordNamedDisallowed = 8860, ERR_UnexpectedArgumentList = 8861, ERR_UnexpectedOrMissingConstructorInitializerInRecord = 8862, ERR_MultipleRecordParameterLists = 8863, diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index ab96b25305990..84c970400eecd 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -474,6 +474,7 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_IsPatternAlways: case ErrorCode.WRN_SwitchExpressionNotExhaustiveWithWhen: case ErrorCode.WRN_SwitchExpressionNotExhaustiveForNullWithWhen: + case ErrorCode.WRN_RecordNamedDisallowed: return 1; default: return 0; diff --git a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs index 88a36b09f9c77..0f237098cb89a 100644 --- a/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/ErrorFacts.Generated.cs @@ -249,6 +249,7 @@ public static bool IsWarning(ErrorCode code) case ErrorCode.WRN_SwitchExpressionNotExhaustiveWithWhen: case ErrorCode.WRN_SwitchExpressionNotExhaustiveForNullWithWhen: case ErrorCode.WRN_PrecedenceInversion: + case ErrorCode.WRN_RecordNamedDisallowed: case ErrorCode.WRN_UnassignedThisAutoProperty: case ErrorCode.WRN_UnassignedThis: case ErrorCode.WRN_ParamUnassigned: diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index b473eb569646f..da0f79fae5e2c 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs @@ -285,7 +285,6 @@ private DeclarationModifiers MakeModifiers(TypeKind typeKind, DiagnosticBag diag var mods = MakeAndCheckTypeModifiers( defaultAccess, allowedModifiers, - this, diagnostics, out modifierErrors); @@ -324,7 +323,6 @@ private DeclarationModifiers MakeModifiers(TypeKind typeKind, DiagnosticBag diag private DeclarationModifiers MakeAndCheckTypeModifiers( DeclarationModifiers defaultAccess, DeclarationModifiers allowedModifiers, - SourceMemberContainerTypeSymbol self, DiagnosticBag diagnostics, out bool modifierErrors) { @@ -356,7 +354,7 @@ private DeclarationModifiers MakeAndCheckTypeModifiers( var info = ModifierUtils.CheckAccessibility(mods, this, isExplicitInterfaceImplementation: false); if (info != null) { - diagnostics.Add(info, self.Locations[0]); + diagnostics.Add(info, this.Locations[0]); modifierErrors = true; } } @@ -383,12 +381,12 @@ private DeclarationModifiers MakeAndCheckTypeModifiers( if ((result & DeclarationModifiers.Partial) == 0) { // duplicate definitions - switch (self.ContainingSymbol.Kind) + switch (this.ContainingSymbol.Kind) { case SymbolKind.Namespace: for (var i = 1; i < partCount; i++) { - diagnostics.Add(ErrorCode.ERR_DuplicateNameInNS, declaration.Declarations[i].NameLocation, self.Name, self.ContainingSymbol); + diagnostics.Add(ErrorCode.ERR_DuplicateNameInNS, declaration.Declarations[i].NameLocation, this.Name, this.ContainingSymbol); modifierErrors = true; } break; @@ -397,7 +395,7 @@ private DeclarationModifiers MakeAndCheckTypeModifiers( for (var i = 1; i < partCount; i++) { if (ContainingType!.Locations.Length == 1 || ContainingType.IsPartial()) - diagnostics.Add(ErrorCode.ERR_DuplicateNameInClass, declaration.Declarations[i].NameLocation, self.ContainingSymbol, self.Name); + diagnostics.Add(ErrorCode.ERR_DuplicateNameInClass, declaration.Declarations[i].NameLocation, this.ContainingSymbol, this.Name); modifierErrors = true; } break; @@ -411,13 +409,18 @@ private DeclarationModifiers MakeAndCheckTypeModifiers( var mods = singleDeclaration.Modifiers; if ((mods & DeclarationModifiers.Partial) == 0) { - diagnostics.Add(ErrorCode.ERR_MissingPartial, singleDeclaration.NameLocation, self.Name); + diagnostics.Add(ErrorCode.ERR_MissingPartial, singleDeclaration.NameLocation, this.Name); modifierErrors = true; } } } } + if (this.Name == "record") + { + diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, declaration.Declarations[0].NameLocation, this.Name); + } + return result; } diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index ad55c9b5fdc3b..fe5c2a3f60ac9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Metoda označená jako [DoesNotReturn] by neměla vracet hodnotu diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 8e35042daf2f0..4f3f4e7f2024a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Eine mit [DoesNotReturn] gekennzeichnete Methode darf nicht zurückgegeben werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 630d2074038ce..0d43e3b40a589 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Un método marcado [DoesNotReturn] no debe devolver. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 7004ed29bf9d0..c6db48c2fff18 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Une méthode marquée [DoesNotReturn] ne doit pas être retournée. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 7c7f2fd041c8c..c3138b71914a3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Un metodo contrassegnato con [DoesNotReturn] non deve essere restituito. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 745f3c6401b94..5b2e5a37515b6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. [DoesNotReturn] とマークされたメソッドを返すことはできません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 401298a3c95e9..ab0cfb8696da9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. [DoesNotReturn]으로 표시된 메서드는 반환하지 않아야 합니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 16c7fe5199756..f74263e9dd3c0 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Metoda oznaczona [DoesNotReturn] nie powinna zwracać wartości. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 39460c7054701..7ab4cbcca83b1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2502,6 +2502,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Um método marcado como [DoesNotReturn] não deve ser retornado. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index a093524636170..c74d062d9c24e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. Метод, помеченный [DoesNotReturn], не должен возвращать значение. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 155a150a2fafe..c4bc018a7f790 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. [DoesNotReturn] olarak işaretlenen bir yöntem, döndürmemelidir. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index c2ced95587fd6..c92c7bdb26154 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. 不应返回标记为 [DoesNotReturn] 的方法。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 7d1221b208a72..3dfe5d10224e4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2504,6 +2504,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + A type should not be named 'record'. + A type should not be named 'record'. + + + + A type should not be named 'record'. + A type should not be named 'record'. + + A method marked [DoesNotReturn] should not return. 標記 [DoesNotReturn] 的方法不應傳回。 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs index d9f9f4d8bf242..aafa0bd1018cb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/RecordTests.cs @@ -1968,7 +1968,7 @@ public override void M(U t) ); } - [Fact] + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] public void TypeNamedRecord() { var src = @" @@ -1980,22 +1980,88 @@ record M(record r) => r; }"; var comp = CreateCompilation(src); comp.VerifyDiagnostics( + // (2,7): error CS8860: A type should not be named 'record'. + // class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7), // (6,24): error CS1514: { expected // record M(record r) => r; Diagnostic(ErrorCode.ERR_LbraceExpected, "=>").WithLocation(6, 24), // (6,24): error CS1513: } expected // record M(record r) => r; Diagnostic(ErrorCode.ERR_RbraceExpected, "=>").WithLocation(6, 24), - // (6,24): error CS1519: Invalid token '=>' in class, struct, or interface member declaration + // (6,24): error CS1519: Invalid token '=>' in class, record, struct, or interface member declaration // record M(record r) => r; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=>").WithArguments("=>").WithLocation(6, 24), - // (6,28): error CS1519: Invalid token ';' in class, struct, or interface member declaration + // (6,28): error CS1519: Invalid token ';' in class, record, struct, or interface member declaration // record M(record r) => r; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(6, 28), - // (6,28): error CS1519: Invalid token ';' in class, struct, or interface member declaration + // (6,28): error CS1519: Invalid token ';' in class, record, struct, or interface member declaration // record M(record r) => r; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, ";").WithArguments(";").WithLocation(6, 28) ); + + comp = CreateCompilation(src, parseOptions: TestOptions.Regular8); + comp.VerifyDiagnostics( + // (2,7): error CS8860: A type should not be named 'record'. + // class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Struct() + { + var src = @" +struct record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,8): warning CS8860: A type should not be named 'record'. + // struct record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 8) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Interface() + { + var src = @" +interface record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,11): warning CS8860: A type should not be named 'record'. + // interface record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 11) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Record() + { + var src = @" +record record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,8): warning CS8860: A type should not be named 'record'. + // record record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 8) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Escaped() + { + var src = @" +class @record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,7): warning CS8860: A type should not be named 'record'. + // class @record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "@record").WithArguments("record").WithLocation(2, 7) + ); } [Fact] @@ -2019,7 +2085,11 @@ public static void Main() } }"; var comp = CreateCompilation(src, options: TestOptions.DebugExe); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (2,7): warning CS8860: A type should not be named 'record'. + // class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7) + ); CompileAndVerify(comp, expectedOutput: "RAN"); } diff --git a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index 148dccc2a1896..d7d3393d69a5e 100644 --- a/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -255,6 +255,7 @@ public void WarningLevel_2() case ErrorCode.WRN_UnconsumedEnumeratorCancellationAttributeUsage: case ErrorCode.WRN_UndecoratedCancellationTokenParameter: case ErrorCode.WRN_SwitchExpressionNotExhaustiveWithWhen: + case ErrorCode.WRN_RecordNamedDisallowed: Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode)); break; case ErrorCode.WRN_MainIgnored: @@ -398,6 +399,7 @@ public void NullableWarnings() ErrorCode.WRN_UseDefViolationThis, ErrorCode.WRN_UseDefViolationOut, ErrorCode.WRN_UseDefViolation, + ErrorCode.WRN_RecordNamedDisallowed, }; Assert.Contains(error, nullableUnrelatedWarnings);