diff --git a/src/Compilers/CSharp/Portable/Binder/Imports.cs b/src/Compilers/CSharp/Portable/Binder/Imports.cs index 7546ac8b10e20..51295d5a6fe27 100644 --- a/src/Compilers/CSharp/Portable/Binder/Imports.cs +++ b/src/Compilers/CSharp/Portable/Binder/Imports.cs @@ -133,7 +133,7 @@ public static Imports FromSyntax( usingsBinder = new InContainerBinder(binder.Container, binder.Next, imports); } - var uniqueUsings = Symbols.SpecializedSymbolCollections.GetPooledSymbolHashSetInstance(); + var uniqueUsings = SpecializedSymbolCollections.GetPooledSymbolHashSetInstance(); foreach (var usingDirective in usingDirectives) { @@ -141,24 +141,29 @@ public static Imports FromSyntax( if (usingDirective.Alias != null) { - if (usingDirective.Alias.Name.Identifier.ContextualKind() == SyntaxKind.GlobalKeyword) + SyntaxToken identifier = usingDirective.Alias.Name.Identifier; + Location location = usingDirective.Alias.Name.Location; + + if (identifier.ContextualKind() == SyntaxKind.GlobalKeyword) { - diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, usingDirective.Alias.Name.Location); + diagnostics.Add(ErrorCode.WRN_GlobalAliasDefn, location); } if (usingDirective.StaticKeyword != default(SyntaxToken)) { - diagnostics.Add(ErrorCode.ERR_NoAliasHere, usingDirective.Alias.Name.Location); + diagnostics.Add(ErrorCode.ERR_NoAliasHere, location); } - string identifierValueText = usingDirective.Alias.Name.Identifier.ValueText; + SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, compilation, diagnostics, location); + + string identifierValueText = identifier.ValueText; if (usingAliases != null && usingAliases.ContainsKey(identifierValueText)) { // Suppress diagnostics if we're already broken. if (!usingDirective.Name.IsMissing) { // The using alias '{0}' appeared previously in this namespace - diagnostics.Add(ErrorCode.ERR_DuplicateAlias, usingDirective.Alias.Name.Location, identifierValueText); + diagnostics.Add(ErrorCode.ERR_DuplicateAlias, location, identifierValueText); } } else diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index f432d9ba1227c..dcf53614bc303 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6419,6 +6419,12 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Members named 'Clone' are disallowed in records. + + Types and aliases should not be named 'record'. + + + Types and aliases 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 5b2f4a245bae5..4109864574526 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 91d065247c391..bb2155275adba 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -475,6 +475,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 7c7cd28322ef0..ee3ecd3a8bc85 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/LocalFunctionSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs index bb11d8623abd5..11fa26452ec70 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/LocalFunctionSymbol.cs @@ -428,6 +428,8 @@ private ImmutableArray MakeTypeParameters(Diagn } } + SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, this.DeclaringCompilation, diagnostics, location); + var tpEnclosing = ContainingSymbol.FindEnclosingTypeParameter(name); if ((object?)tpEnclosing != null) { diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberContainerSymbol.cs index b473eb569646f..8e6d884baf8a9 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,16 +409,40 @@ 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 == SyntaxFacts.GetText(SyntaxKind.RecordKeyword)) + { + foreach (var syntaxRef in SyntaxReferences) + { + SyntaxToken? identifier = syntaxRef.GetSyntax() switch + { + BaseTypeDeclarationSyntax typeDecl => typeDecl.Identifier, + DelegateDeclarationSyntax delegateDecl => delegateDecl.Identifier, + _ => null + }; + + ReportTypeNamedRecord(identifier?.Text, this.DeclaringCompilation, diagnostics, identifier?.GetLocation() ?? Location.None); + } + } + return result; } + static internal void ReportTypeNamedRecord(string? name, CSharpCompilation compilation, DiagnosticBag diagnostics, Location location) + { + if (name == SyntaxFacts.GetText(SyntaxKind.RecordKeyword) && + compilation.LanguageVersion >= MessageID.IDS_FeatureRecords.RequiredVersion()) + { + diagnostics.Add(ErrorCode.WRN_RecordNamedDisallowed, location, name); + } + } + #endregion #region Completion diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs index 291772a05532a..9a75d0a0d7baa 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceNamedTypeSymbol.cs @@ -186,6 +186,9 @@ private ImmutableArray MakeTypeParameters(DiagnosticBag dia var name = typeParameterNames[i]; var location = new SourceLocation(tp.Identifier); var varianceKind = typeParameterVarianceKeywords[i]; + + ReportTypeNamedRecord(tp.Identifier.Text, this.DeclaringCompilation, diagnostics, location); + if (name == null) { name = typeParameterNames[i] = tp.Identifier.ValueText; diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs index c007fbca2e1de..a1742e452436b 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceOrdinaryMethodSymbol.cs @@ -519,6 +519,8 @@ private ImmutableArray MakeTypeParameters(MethodDeclaration } } + SourceMemberContainerTypeSymbol.ReportTypeNamedRecord(identifier.Text, this.DeclaringCompilation, diagnostics, location); + var tpEnclosing = ContainingType.FindEnclosingTypeParameter(name); if ((object)tpEnclosing != null) { diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 99a52efcbf9dc..7eb2a1791f58d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 4676d2e69cabc..1163231366851 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 a96e56ce1ca1f..e09ddbb27dee5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 0d684cf863ccc..2882a183dee5b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 42c56251845f4..d349070d9ebf4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 e4b04001decd5..07eaf975a6897 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 bd597c536f35d..5ceade20d6c83 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 a382b2bdc832e..0877898ce83db 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 785949d37eaa8..2631ef9f5c464 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2507,6 +2507,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 8a9e273a9fa80..4e9c5ce2da00f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 8db0caa3d61ed..827c7ad372266 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 244c7af4b2f79..79b244ffd8a86 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 d607107a2a055..a2873a32fccbb 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2509,6 +2509,16 @@ Type does not implement the collection pattern; member is is not a public instance or extension method. + + Types and aliases should not be named 'record'. + Types and aliases should not be named 'record'. + + + + Types and aliases should not be named 'record'. + Types and aliases 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 8761adb5ae383..e3d7820706159 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,341 @@ record M(record r) => r; }"; var comp = CreateCompilation(src); comp.VerifyDiagnostics( + // (2,7): error CS8860: Types and aliases 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(); + } + + [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: Types and aliases 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: Types and aliases 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_Enum() + { + var src = @" +enum record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,6): warning CS8860: Types and aliases should not be named 'record'. + // enum record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 6) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Delegate() + { + var src = @" +delegate void record(); +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,15): warning CS8860: Types and aliases should not be named 'record'. + // delegate void record(); + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 15) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Delegate_Escaped() + { + var src = @" +delegate void @record(); +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Alias() + { + var src = @" +using record = System.Console; +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using record = System.Console; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using record = System.Console;").WithLocation(2, 1), + // (2,7): warning CS8860: Types and aliases should not be named 'record'. + // using record = System.Console; + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 7) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Alias_Escaped() + { + var src = @" +using @record = System.Console; +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using @record = System.Console; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using @record = System.Console;").WithLocation(2, 1) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_TypeParameter() + { + var src = @" +class C { } // 1 +class C2 +{ + class Nested { } // 2 +} +class C3 +{ + void Method() { } // 3 + + void Method2() + { + void local() // 4 + { + local(); + } + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,9): warning CS8860: Types and aliases should not be named 'record'. + // class C { } // 1 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 9), + // (5,18): warning CS8860: Types and aliases should not be named 'record'. + // class Nested { } // 2 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(5, 18), + // (9,17): warning CS8860: Types and aliases should not be named 'record'. + // void Method() { } // 3 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(9, 17), + // (13,20): warning CS8860: Types and aliases should not be named 'record'. + // void local() // 4 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(13, 20) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_TypeParameter_Escaped() + { + var src = @" +class C<@record> { } +class C2 +{ + class Nested<@record> { } +} +class C3 +{ + void Method<@record>() { } + + void Method2() + { + void local<@record>() + { + local(); + } + } +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_TypeParameter_Escaped_Partial() + { + var src = @" +partial class C<@record> { } +partial class C { } // 1 + +partial class D { } // 2 +partial class D<@record> { } + +partial class D { } // 3 +partial class D { } // 4 + +partial class E<@record> { } +partial class E<@record> { } + +partial class C2 +{ + partial class Nested { } // 5 + partial class Nested<@record> { } +} +partial class C3 +{ + partial void Method<@record>(); + partial void Method() { } // 6 + + partial void Method2<@record>() { } + partial void Method2(); // 7 + + partial void Method3(); // 8 + partial void Method3<@record>() { } + + partial void Method4() { } // 9 + partial void Method4<@record>(); +} +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (3,17): warning CS8860: Types and aliases should not be named 'record'. + // partial class C { } // 1 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(3, 17), + // (5,17): warning CS8860: Types and aliases should not be named 'record'. + // partial class D { } // 2 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(5, 17), + // (8,17): warning CS8860: Types and aliases should not be named 'record'. + // partial class D { } // 3 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(8, 17), + // (9,17): warning CS8860: Types and aliases should not be named 'record'. + // partial class D { } // 4 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(9, 17), + // (16,26): warning CS8860: Types and aliases should not be named 'record'. + // partial class Nested { } // 5 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(16, 26), + // (22,25): warning CS8860: Types and aliases should not be named 'record'. + // partial void Method() { } // 6 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(22, 25), + // (25,26): warning CS8860: Types and aliases should not be named 'record'. + // partial void Method2(); // 7 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(25, 26), + // (27,26): warning CS8860: Types and aliases should not be named 'record'. + // partial void Method3(); // 8 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(27, 26), + // (30,26): warning CS8860: Types and aliases should not be named 'record'. + // partial void Method4() { } // 9 + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(30, 26) + ); + } + + [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: Types and aliases 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_TwoParts() + { + var src = @" +partial class record { } +partial class record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,15): warning CS8860: Types and aliases should not be named 'record'. + // partial class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 15), + // (3,15): warning CS8860: Types and aliases should not be named 'record'. + // partial class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(3, 15) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_Escaped() + { + var src = @" +class @record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_MixedEscapedPartial() + { + var src = @" +partial class @record { } +partial class record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (3,15): warning CS8860: Types and aliases should not be named 'record'. + // partial class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(3, 15) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_MixedEscapedPartial_ReversedOrder() + { + var src = @" +partial class record { } +partial class @record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( + // (2,15): warning CS8860: Types and aliases should not be named 'record'. + // partial class record { } + Diagnostic(ErrorCode.WRN_RecordNamedDisallowed, "record").WithArguments("record").WithLocation(2, 15) + ); + } + + [Fact, WorkItem(47090, "https://github.com/dotnet/roslyn/issues/47090")] + public void TypeNamedRecord_BothEscapedPartial() + { + var src = @" +partial class @record { } +partial class @record { } +"; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics(); } [Fact] @@ -2019,7 +2338,11 @@ public static void Main() } }"; var comp = CreateCompilation(src, options: TestOptions.DebugExe); - comp.VerifyEmitDiagnostics(); + comp.VerifyEmitDiagnostics( + // (2,7): warning CS8860: Types and aliases 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 c673ad73d8779..b66472dc11f43 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: @@ -400,6 +401,7 @@ public void NullableWarnings() ErrorCode.WRN_UseDefViolationOut, ErrorCode.WRN_UseDefViolation, ErrorCode.WRN_SyncAndAsyncEntryPoints, + ErrorCode.WRN_RecordNamedDisallowed, }; Assert.Contains(error, nullableUnrelatedWarnings);