From b363549991090a6d87d25eb3fbc33d69c90e93da Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 11:22:49 -0700 Subject: [PATCH 01/42] Add initial tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 137 +++++++++++++++++- 1 file changed, 136 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 572f5f8ddd22d..3cf9634d44994 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { - public class NameofTests : CSharpTestBase + public sealed class NameofTests : CSharpTestBase { [Fact] public void TestGoodNameofInstances() @@ -2373,5 +2373,140 @@ class Attr : System.Attribute { public Attr(string s) {} }"; CreateCompilation(source, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(expectedDiagnostics); CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(expectedDiagnostics); } + + [Fact] + public void OpenTypeInNameof_CSharp13() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List<>); + Console.WriteLine(v); + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_BaseCase() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List<>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "List"); + } + + [Fact] + public void OpenTypeInNameof_MultipleTypeArguments() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(Dictionary<,>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "Dictionary"); + } + + [Fact] + public void OpenTypeInNameof_NoNestedOpenTypes() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_NoPartialOpenTypes() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(Dictionary<,int>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_MemberAccessThatDoesNotUseTypeArgument() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List<>.Count); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "Count"); + } + + [Fact] + public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + interface IGoo + { + T Count { get; } + } + + var v = nameof(IGoo<>.Count); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "Count"); + } + + [Fact] + public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceObjectMember() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + interface IGoo + { + T Count { get; } + } + + var v = nameof(IGoo<>.Count.ToString); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "ToString"); + } + + [Fact] + public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + interface IGoo where T : IComparable + { + T X { get; } + } + + var v = nameof(IGoo<>.Count.X.CompareTo); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "CompareTo"); + } } } From f1f276b405126c629843e46fd3f5fcaeedb6b3a1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:00:51 -0700 Subject: [PATCH 02/42] Initial work --- .../CSharp/Portable/Binder/Binder_Symbols.cs | 42 +++--- .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/MessageID.cs | 3 + .../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 + .../Test/Semantic/Semantics/NameOfTests.cs | 131 +++++++++++++++++- 17 files changed, 227 insertions(+), 17 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index c35c4512565cd..079a5c04668c4 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1212,7 +1212,7 @@ private TypeWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol( if (isUnboundTypeExpr) { - if (!IsUnboundTypeAllowed(node)) + if (!IsInsideNameof && !IsUnboundTypeAllowed(node)) { // If we already have an error type then skip reporting that the unbound type is illegal. if (!unconstructedType.IsErrorType()) @@ -1373,22 +1373,32 @@ private NamedTypeSymbol ConstructNamedTypeUnlessTypeArgumentOmitted(SyntaxNode t { if (typeArgumentsSyntax.Any(SyntaxKind.OmittedTypeArgument)) { - // Note: lookup won't have reported this, since the arity was correct. - // CONSIDER: the text of this error message makes sense, but we might want to add a separate code. - Error(diagnostics, ErrorCode.ERR_BadArity, typeSyntax, type, MessageID.IDS_SK_TYPE.Localize(), typeArgumentsSyntax.Count); - - // If the syntax looks like an unbound generic type, then they probably wanted the definition. - // Give an error indicating that the syntax is incorrect and then use the definition. - // CONSIDER: we could construct an unbound generic type symbol, but that would probably be confusing - // outside a typeof. - return type; - } - else - { - // we pass an empty basesBeingResolved here because this invocation is not on any possible path of - // infinite recursion in binding base clauses. - return ConstructNamedType(type, typeSyntax, typeArgumentsSyntax, typeArguments, basesBeingResolved: null, diagnostics: diagnostics); + if (this.IsInsideNameof) + { + // Inside a nameof an open-generic type is acceptable. Fall through and bind the remainder accordingly. + CheckFeatureAvailability(typeSyntax, MessageID.IDS_FeatureOpenTypeInNameof, diagnostics); + typeArguments = UnboundArgumentErrorTypeSymbol.CreateTypeArguments( + type.TypeParameters, + type.TypeParameters.Length, + errorInfo: null); + } + else + { + // Note: lookup won't have reported this, since the arity was correct. + // CONSIDER: the text of this error message makes sense, but we might want to add a separate code. + Error(diagnostics, ErrorCode.ERR_BadArity, typeSyntax, type, MessageID.IDS_SK_TYPE.Localize(), typeArgumentsSyntax.Count); + + // If the syntax looks like an unbound generic type, then they probably wanted the definition. + // Give an error indicating that the syntax is incorrect and then use the definition. + // CONSIDER: we could construct an unbound generic type symbol, but that would probably be confusing + // outside a typeof. + return type; + } } + + // we pass an empty basesBeingResolved here because this invocation is not on any possible path of + // infinite recursion in binding base clauses. + return ConstructNamedType(type, typeSyntax, typeArgumentsSyntax, typeArguments, basesBeingResolved: null, diagnostics: diagnostics); } /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 4210d8664c209..7ec2cc161e79b 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4926,6 +4926,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ nameof operator + + Open generic types in nameof operator + dictionary initializer diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index e7b0601c7c545..fc738ddef1990 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -292,6 +292,8 @@ internal enum MessageID IDS_FeatureAllowsRefStructConstraint = MessageBase + 12847, IDS_OverloadResolutionPriority = MessageBase + 12848, + + IDS_FeatureOpenTypeInNameof = MessageBase + 12849, } // Message IDs may refer to strings that need to be localized. @@ -473,6 +475,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) // C# preview features. case MessageID.IDS_FeatureFieldKeyword: + case MessageID.IDS_FeatureOpenTypeInNameof: return LanguageVersion.Preview; // C# 13.0 features. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 88e737c1beb27..5ec0a6129833a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2497,6 +2497,11 @@ nové řádky v interpolacích + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors konstruktory struktury bez parametrů diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 7791b4941b495..504b9777b379f 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2497,6 +2497,11 @@ Zeilenumbrüche in Interpolationen + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors Parameterlose Strukturkonstruktoren diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 49dc784c465a9..fc3b27f7e9b05 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2497,6 +2497,11 @@ Nuevas líneas en interpolaciones + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors constructores de estructuras sin parámetros diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index ebc8306793f12..17773b98e1355 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2497,6 +2497,11 @@ sauts de ligne dans les interpolations + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors constructeurs de struct sans paramètre diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 268e0502cd458..88133a0470931 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2497,6 +2497,11 @@ nuove linee nelle interpolazioni + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors costruttori struct senza parametri diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 7ac7b47912be2..67304ba3e1e4d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2497,6 +2497,11 @@ 補間における改行 + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors パラメーターのない構造体コンストラクター diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 1c3127f912223..5a2323ea3fbc6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2497,6 +2497,11 @@ 보간에서 줄 바꿈 + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors 매개 변수 없는 구조체 생성자 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 4a0500365e1e0..35f821350ac49 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2497,6 +2497,11 @@ nowe wiersze w interpolacjach + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors Konstruktory struktury bez parametrów diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 2c3070ffc18a6..4fdd79bc09bc7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2497,6 +2497,11 @@ novas linhas em interpolações + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors construtores struct sem parâmetros diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 5ad07dbfa5172..1ce13800d4a40 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2497,6 +2497,11 @@ новые линии в интерполяции + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors конструкторы структуры без параметров diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index f6b9d136c9e3c..73d03ea9f3418 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2497,6 +2497,11 @@ ilişkilendirmedeki yeni satırlar + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors parametresiz yapı oluşturucuları diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 430ad886cfb0a..ef27a87597d14 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2497,6 +2497,11 @@ 内插中的换行符 + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors 参数结构构造函数 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 6d362a02305c7..a1f23a79f900b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2497,6 +2497,11 @@ 插補中的新行 + + Open generic types in nameof operator + Open generic types in nameof operator + + parameterless struct constructors 無參數結構建構函式 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 3cf9634d44994..ae9334fa7c863 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2383,6 +2383,51 @@ public void OpenTypeInNameof_CSharp13() var v = nameof(List<>); Console.WriteLine(v); + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( + // (4,16): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(List<>); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Open generic types in nameof operator").WithLocation(4, 16)); + } + + [Fact] + public void OpenTypeInNameof_CSharp13_Nested1() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(A<>.B); + Console.WriteLine(v); + + class A { public class B; } + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_CSharp13_Nested2() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(A.B<>); + Console.WriteLine(v); + + class A { public class B; } + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_CSharp13_Nested3() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(A<>.B<>); + Console.WriteLine(v); + + class A { class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); } @@ -2400,6 +2445,54 @@ public void OpenTypeInNameof_BaseCase() expectedOutput: "List"); } + [Fact] + public void OpenTypeInNameof_Nested1() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(A<>.B); + Console.WriteLine(v); + + class A { public class B; } + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "B"); + } + + [Fact] + public void OpenTypeInNameof_Nested2() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(A.B<>); + Console.WriteLine(v); + + class A { public class B; } + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "B"); + } + + [Fact] + public void OpenTypeInNameof_Nested3() + { + CompileAndVerify( + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(A<>.B<>); + Console.WriteLine(v); + + class A { public class B; } + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "B"); + } + [Fact] public void OpenTypeInNameof_MultipleTypeArguments() { @@ -2414,6 +2507,30 @@ public void OpenTypeInNameof_MultipleTypeArguments() expectedOutput: "Dictionary"); } + [Fact] + public void OpenTypeInNameof_IncorrectTypeArgumentCount1() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(Dictionary<>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_IncorrectTypeArgumentCount2() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List<,>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + [Fact] public void OpenTypeInNameof_NoNestedOpenTypes() { @@ -2427,7 +2544,7 @@ public void OpenTypeInNameof_NoNestedOpenTypes() } [Fact] - public void OpenTypeInNameof_NoPartialOpenTypes() + public void OpenTypeInNameof_NoPartialOpenTypes_1() { CreateCompilation(""" using System; @@ -2438,6 +2555,18 @@ public void OpenTypeInNameof_NoPartialOpenTypes() """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); } + [Fact] + public void OpenTypeInNameof_NoPartialOpenTypes_2() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(Dictionary); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + [Fact] public void OpenTypeInNameof_MemberAccessThatDoesNotUseTypeArgument() { From d5d1423864190a0caf9ef8b041e2df7a9bdcc211 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:03:18 -0700 Subject: [PATCH 03/42] more working --- .../Test/Semantic/Semantics/NameOfTests.cs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index ae9334fa7c863..c8c5ea221f451 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2451,7 +2451,6 @@ public void OpenTypeInNameof_Nested1() CompileAndVerify( CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(A<>.B); Console.WriteLine(v); @@ -2467,7 +2466,6 @@ public void OpenTypeInNameof_Nested2() CompileAndVerify( CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(A.B<>); Console.WriteLine(v); @@ -2483,7 +2481,6 @@ public void OpenTypeInNameof_Nested3() CompileAndVerify( CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(A<>.B<>); Console.WriteLine(v); @@ -2516,7 +2513,13 @@ public void OpenTypeInNameof_IncorrectTypeArgumentCount1() var v = nameof(Dictionary<>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using System.Collections.Generic; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1), + // (4,16): error CS0305: Using the generic type 'Dictionary' requires 2 type arguments + // var v = nameof(Dictionary<>); + Diagnostic(ErrorCode.ERR_BadArity, "Dictionary<>").WithArguments("System.Collections.Generic.Dictionary", "type", "2").WithLocation(4, 16)); } [Fact] @@ -2528,7 +2531,13 @@ public void OpenTypeInNameof_IncorrectTypeArgumentCount2() var v = nameof(List<,>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (2,1): hidden CS8019: Unnecessary using directive. + // using System.Collections.Generic; + Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1), + // (4,16): error CS0305: Using the generic type 'List' requires 1 type arguments + // var v = nameof(List<,>); + Diagnostic(ErrorCode.ERR_BadArity, "List<,>").WithArguments("System.Collections.Generic.List", "type", "1").WithLocation(4, 16)); } [Fact] From f16971d19c1bbbdb0a01f250b02cbc592d00162a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:13:22 -0700 Subject: [PATCH 04/42] Better parsing --- src/Compilers/CSharp/Portable/Parser/LanguageParser.cs | 9 +++++++++ .../CSharp/Test/Semantic/Semantics/NameOfTests.cs | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 1b2c4707840fb..1f4a35c326fa8 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6104,6 +6104,15 @@ private ScanTypeFlags ScanPossibleTypeArgumentList( return result; } + // Allow for any chain of errant commas in teh generic name. like `Dictionary<,int>` or + // `Dictionary` We still want to think of these as generics, just with missing type-arguments, vs + // some invalid tree-expression that we would otherwise form. + if (this.CurrentToken.Kind == SyntaxKind.CommaToken) + { + lastScannedType = default; + continue; + } + lastScannedType = this.ScanType(out _); switch (lastScannedType) { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index c8c5ea221f451..d1c1c243d916a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2561,7 +2561,10 @@ public void OpenTypeInNameof_NoPartialOpenTypes_1() var v = nameof(Dictionary<,int>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (4,27): error CS1031: Type expected + // var v = nameof(Dictionary<,int>); + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(4, 27)); } [Fact] @@ -2573,7 +2576,10 @@ public void OpenTypeInNameof_NoPartialOpenTypes_2() var v = nameof(Dictionary); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (4,31): error CS1031: Type expected + // var v = nameof(Dictionary); + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(4, 31)); } [Fact] From 6d9a0682296aff720673fa8cb777706c84531dc1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:17:12 -0700 Subject: [PATCH 05/42] more work --- .../Test/Semantic/Semantics/NameOfTests.cs | 23 +++++++++++++------ 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index d1c1c243d916a..0f2024536bab2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2394,13 +2394,15 @@ public void OpenTypeInNameof_CSharp13_Nested1() { CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(A<>.B); Console.WriteLine(v); class A { public class B; } - """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( + // (3,16): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(A<>.B); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 16)); } [Fact] @@ -2408,13 +2410,15 @@ public void OpenTypeInNameof_CSharp13_Nested2() { CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(A.B<>); Console.WriteLine(v); class A { public class B; } - """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( + // (3,23): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(A.B<>); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 23)); } [Fact] @@ -2422,13 +2426,18 @@ public void OpenTypeInNameof_CSharp13_Nested3() { CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(A<>.B<>); Console.WriteLine(v); - class A { class B; } - """, parseOptions: TestOptions.Regular13).VerifyDiagnostics(); + class A { public class B; } + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( + // (3,16): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(A<>.B<>); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 16), + // (3,20): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(A<>.B<>); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 20)); } [Fact] From b4ff542dd062613e66faddc41570bbe642a7934b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:31:03 -0700 Subject: [PATCH 06/42] names --- .../Portable/Binder/Binder_Invocation.cs | 28 +++++++++++++++++++ .../CSharp/Portable/CSharpResources.resx | 7 +++-- .../CSharp/Portable/Errors/ErrorCode.cs | 2 ++ .../CSharp/Portable/Errors/MessageID.cs | 2 +- .../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 ++++++---- 17 files changed, 166 insertions(+), 68 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index b5885aa1e4af0..060ef2cbab72a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -2273,6 +2273,9 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no { CheckFeatureAvailability(node, MessageID.IDS_FeatureNameof, diagnostics); var argument = node.ArgumentList.Arguments[0].Expression; + + validateOpenGenericNames(argument, topLevel: true); + var boundArgument = BindExpression(argument, diagnostics); bool syntaxIsOk = CheckSyntaxForNameofArgument(argument, out string name, boundArgument.HasAnyErrors ? BindingDiagnosticBag.Discarded : diagnostics); @@ -2297,6 +2300,31 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no boundArgument = BindToNaturalType(boundArgument, diagnostics, reportNoTargetType: false); return new BoundNameOfOperator(node, boundArgument, ConstantValue.Create(name), Compilation.GetSpecialType(SpecialType.System_String)); + + void validateOpenGenericNames(SyntaxNode current, bool topLevel) + { + if (current is TypeArgumentListSyntax typeArgumentList) + { + if (!topLevel) + { + foreach (var typeArgument in typeArgumentList.Arguments) + { + if (typeArgument.Kind() == SyntaxKind.OmittedTypeArgument) + diagnostics.Add(ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression, typeArgumentList.Parent); + } + } + + // Once we hit a type argument list, we're no longer at the top level, and we want to report errors + // for any omitted type arguments we see at a deeper level. + topLevel = false; + } + + foreach (var child in current.ChildNodesAndTokens()) + { + if (child.IsNode) + validateOpenGenericNames(child.AsNode(), topLevel); + } + } } private void EnsureNameofExpressionSymbols(BoundMethodGroup methodGroup, BindingDiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 7ec2cc161e79b..8c2a8f3d85427 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4926,8 +4926,8 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ nameof operator - - Open generic types in nameof operator + + Unbound generic types in nameof operator dictionary initializer @@ -8005,4 +8005,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Non-nullable property must contain a non-null value when exiting constructor. Consider adding the 'required' modifier, or declaring the property as nullable, or adding '[field: MaybeNull, AllowNull]' attributes. + + Nested unbound generic type not allowed in 'nameof' operator + diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 7c07bb82d271e..f8e35c71b849d 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2345,6 +2345,8 @@ internal enum ErrorCode ERR_CannotApplyOverloadResolutionPriorityToMember = 9262, ERR_PartialPropertyDuplicateInitializer = 9263, + ERR_NestedUnboundTypeNotAllowedInNameofExpression = 9270, + WRN_UninitializedNonNullableBackingField = 9264, // Note: you will need to do the following after adding errors: diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index fc738ddef1990..69f3ef9e592d9 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -293,7 +293,7 @@ internal enum MessageID IDS_FeatureAllowsRefStructConstraint = MessageBase + 12847, IDS_OverloadResolutionPriority = MessageBase + 12848, - IDS_FeatureOpenTypeInNameof = MessageBase + 12849, + IDS_FeatureUnboundGenericTypesInNameof = MessageBase + 12849, } // Message IDs may refer to strings that need to be localized. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 5ec0a6129833a..bcf84888d9b9d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1452,6 +1452,11 @@ Přístup k vloženému poli nemůže mít specifikátor pojmenovaného argumentu. + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Omezení new() nejde používat s omezením unmanaged. @@ -2497,11 +2502,6 @@ nové řádky v interpolacích - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors konstruktory struktury bez parametrů @@ -2577,6 +2577,11 @@ Inicializátory polí struktury + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift nepodepsaný pravý posun diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index 504b9777b379f..e8f86c296ff16 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1452,6 +1452,11 @@ Ein Inlinearrayzugriff verfügt möglicherweise nicht über einen benannten Argumentspezifizierer. + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Die new()-Einschränkung kann nicht mit der unmanaged-Einschränkung verwendet werden. @@ -2497,11 +2502,6 @@ Zeilenumbrüche in Interpolationen - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors Parameterlose Strukturkonstruktoren @@ -2577,6 +2577,11 @@ Strukturfeldinitialisierer + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift Unsignierte Rechtsverschiebung diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index fc3b27f7e9b05..05899a2868505 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1452,6 +1452,11 @@ Un acceso de matriz insertado no puede tener un especificador de argumento con nombre + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint La restricción "new()" no se puede utilizar con la restricción "unmanaged" @@ -2497,11 +2502,6 @@ Nuevas líneas en interpolaciones - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors constructores de estructuras sin parámetros @@ -2577,6 +2577,11 @@ inicializadores de campo de estructura + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift cambio derecho sin firmar diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index 17773b98e1355..e92fa9d3466e8 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1452,6 +1452,11 @@ Un accès au tableau en ligne peut ne pas avoir de spécificateur d'argument nommé + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint La contrainte 'new()' ne peut pas être utilisée avec la contrainte 'unmanaged' @@ -2497,11 +2502,6 @@ sauts de ligne dans les interpolations - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors constructeurs de struct sans paramètre @@ -2577,6 +2577,11 @@ initialiseurs de champ de struct + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift shift droit non signé diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 88133a0470931..7b1615bb369b1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1452,6 +1452,11 @@ Un accesso a matrice inline non può includere un identificatore di argomento denominato + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Non è possibile usare il vincolo 'new()' con il vincolo 'unmanaged' @@ -2497,11 +2502,6 @@ nuove linee nelle interpolazioni - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors costruttori struct senza parametri @@ -2577,6 +2577,11 @@ inizializzatori di campo struct + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift spostamento a destra senza segno diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 67304ba3e1e4d..d599d0bee034a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1452,6 +1452,11 @@ インライン配列のアクセスには名前付き引数の指定子を指定できません + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 制約は 'unmanaged' 制約と一緒には使用できません @@ -2497,11 +2502,6 @@ 補間における改行 - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors パラメーターのない構造体コンストラクター @@ -2577,6 +2577,11 @@ 構造体フィールド初期化子 + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift 符号なし右シフト diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 5a2323ea3fbc6..b4031f12c35b6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1452,6 +1452,11 @@ 인라인 배열 액세스에는 명명된 인수 지정자가 없을 수 있습니다. + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 제약 조건은 'unmanaged' 제약 조건과 함께 사용할 수 없습니다. @@ -2497,11 +2502,6 @@ 보간에서 줄 바꿈 - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors 매개 변수 없는 구조체 생성자 @@ -2577,6 +2577,11 @@ 구조체 필드 이니셜라이저 + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift 부호 없는 오른쪽 시프트 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 35f821350ac49..c05d86c27269a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1452,6 +1452,11 @@ Dostęp do tablicy śródwierszowej nie może mieć specyfikatora argumentu nazwanego + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Ograniczenie „new()” nie może być używane z ograniczeniem „unmanaged” @@ -2497,11 +2502,6 @@ nowe wiersze w interpolacjach - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors Konstruktory struktury bez parametrów @@ -2577,6 +2577,11 @@ inicjatory pola struktury + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift niepodpisane przesunięcie w prawo diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 4fdd79bc09bc7..d7a0c6c7250a3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1452,6 +1452,11 @@ Um acesso à matriz não pode ter um especificador de argumento nomeado + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint A restrição 'new()' não pode ser usada com a restrição 'unmanaged' @@ -2497,11 +2502,6 @@ novas linhas em interpolações - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors construtores struct sem parâmetros @@ -2577,6 +2577,11 @@ inicializadores de campo de struct + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift deslocamento direito não atribuído diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 1ce13800d4a40..e66949fa608e1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1452,6 +1452,11 @@ Доступ к встроенному массиву может не иметь спецификатора именованного аргумента. + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint Ограничение "new()" невозможно использовать вместе с ограничением "unmanaged" @@ -2497,11 +2502,6 @@ новые линии в интерполяции - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors конструкторы структуры без параметров @@ -2577,6 +2577,11 @@ инициализаторы полей структуры + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift сдвиг вправо без знака diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 73d03ea9f3418..63c9552944960 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1452,6 +1452,11 @@ Satır içi dizi erişiminin adlandırılmış bağımsız değişken belirticisi olamaz + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint 'new()' kısıtlaması, 'unmanaged' kısıtlamasıyla kullanılamaz @@ -2497,11 +2502,6 @@ ilişkilendirmedeki yeni satırlar - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors parametresiz yapı oluşturucuları @@ -2577,6 +2577,11 @@ struct alan başlatıcıları + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift işaretsiz sağ kaydırma diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index ef27a87597d14..af11b1abb32e3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1452,6 +1452,11 @@ 内联数组访问可能没有命名参数说明符 + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint "new()" 约束不能与 "unmanaged" 约束一起使用 @@ -2497,11 +2502,6 @@ 内插中的换行符 - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors 参数结构构造函数 @@ -2577,6 +2577,11 @@ 结构字段初始化表达式 + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift 未签名的右移位 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index a1f23a79f900b..3ce02c815c6bd 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1452,6 +1452,11 @@ 內嵌陣列存取不能有具名引數指定名稱 + + Nested unbound generic type not allowed in 'nameof' operator + Nested unbound generic type not allowed in 'nameof' operator + + The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 條件約束不能和 'unmanaged' 條件約束一起使用 @@ -2497,11 +2502,6 @@ 插補中的新行 - - Open generic types in nameof operator - Open generic types in nameof operator - - parameterless struct constructors 無參數結構建構函式 @@ -2577,6 +2577,11 @@ 結構欄位初始設定式 + + Unbound generic types in nameof operator + Unbound generic types in nameof operator + + unsigned right shift 未簽署右移位 From 092b89cf7f4f9a022f631449bf22e33f864770fd Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:35:00 -0700 Subject: [PATCH 07/42] nesting --- .../CSharp/Portable/Binder/Binder_Symbols.cs | 2 +- .../CSharp/Portable/Errors/MessageID.cs | 2 +- .../Test/Semantic/Semantics/NameOfTests.cs | 27 ++++++++++--------- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 079a5c04668c4..aa1593be79fe3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1376,7 +1376,7 @@ private NamedTypeSymbol ConstructNamedTypeUnlessTypeArgumentOmitted(SyntaxNode t if (this.IsInsideNameof) { // Inside a nameof an open-generic type is acceptable. Fall through and bind the remainder accordingly. - CheckFeatureAvailability(typeSyntax, MessageID.IDS_FeatureOpenTypeInNameof, diagnostics); + CheckFeatureAvailability(typeSyntax, MessageID.IDS_FeatureUnboundGenericTypesInNameof, diagnostics); typeArguments = UnboundArgumentErrorTypeSymbol.CreateTypeArguments( type.TypeParameters, type.TypeParameters.Length, diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 69f3ef9e592d9..07cc6f54fdf2f 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -475,7 +475,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) // C# preview features. case MessageID.IDS_FeatureFieldKeyword: - case MessageID.IDS_FeatureOpenTypeInNameof: + case MessageID.IDS_FeatureUnboundGenericTypesInNameof: return LanguageVersion.Preview; // C# 13.0 features. diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 0f2024536bab2..971b5c9bf3c2a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2384,9 +2384,9 @@ public void OpenTypeInNameof_CSharp13() var v = nameof(List<>); Console.WriteLine(v); """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (4,16): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (4,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(List<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Open generic types in nameof operator").WithLocation(4, 16)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Unbound generic types in nameof operator").WithLocation(4, 16)); } [Fact] @@ -2400,9 +2400,9 @@ public void OpenTypeInNameof_CSharp13_Nested1() class A { public class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (3,16): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. - // var v = nameof(A<>.B); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 16)); + // (3,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(A<>.B); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 16)); } [Fact] @@ -2416,9 +2416,9 @@ public void OpenTypeInNameof_CSharp13_Nested2() class A { public class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (3,23): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (3,23): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A.B<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 23)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 23)); } [Fact] @@ -2432,12 +2432,12 @@ public void OpenTypeInNameof_CSharp13_Nested3() class A { public class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (3,16): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (3,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A<>.B<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 16), - // (3,20): error CS8652: The feature 'Open generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 16), + // (3,20): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A<>.B<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Open generic types in nameof operator").WithLocation(3, 20)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 20)); } [Fact] @@ -2558,7 +2558,10 @@ public void OpenTypeInNameof_NoNestedOpenTypes() var v = nameof(List>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + // (4,21): error CS9270: Nested unbound generic type not allowed in 'nameof' operator + // var v = nameof(List>); + Diagnostic(ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression, "List<>").WithLocation(4, 21)); } [Fact] From d0b2d12ee3997a0ccedd69c1df5e2ba0a459ef82 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:35:39 -0700 Subject: [PATCH 08/42] Fixup tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 971b5c9bf3c2a..6c8469580e36c 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2614,15 +2614,14 @@ public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument() CompileAndVerify( CreateCompilation(""" using System; - using System.Collections.Generic; + + var v = nameof(IGoo<>.Count); + Console.WriteLine(v); interface IGoo { T Count { get; } } - - var v = nameof(IGoo<>.Count); - Console.WriteLine(v); """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), expectedOutput: "Count"); } @@ -2634,14 +2633,14 @@ public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceObject CreateCompilation(""" using System; using System.Collections.Generic; + + var v = nameof(IGoo<>.Count.ToString); + Console.WriteLine(v); interface IGoo { T Count { get; } } - - var v = nameof(IGoo<>.Count.ToString); - Console.WriteLine(v); """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), expectedOutput: "ToString"); } @@ -2653,14 +2652,14 @@ public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstr CreateCompilation(""" using System; using System.Collections.Generic; + + var v = nameof(IGoo<>.Count.X.CompareTo); + Console.WriteLine(v); interface IGoo where T : IComparable { T X { get; } } - - var v = nameof(IGoo<>.Count.X.CompareTo); - Console.WriteLine(v); """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), expectedOutput: "CompareTo"); } From 2d0155ab08def9d4fabd62089ad6d76d55a25e37 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:39:14 -0700 Subject: [PATCH 09/42] Fixup tests --- .../CSharp/Test/Semantic/Semantics/NameOfTests.cs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 6c8469580e36c..9c97c99de1bc5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -249,9 +249,6 @@ class Test // (17,66): error CS1031: Type expected // s = nameof(System.Collections.Generic.Dictionary.KeyCollection); Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(17, 66), - // (11,27): error CS0305: Using the generic type 'Action' requires 1 type arguments - // s = nameof(System.Action<>); - Diagnostic(ErrorCode.ERR_BadArity, "Action<>").WithArguments("System.Action", "type", "1").WithLocation(11, 27), // (16,20): error CS0103: The name 'List' does not exist in the current context // s = nameof(List.Enumerator); Diagnostic(ErrorCode.ERR_NameNotInContext, "List").WithArguments("List").WithLocation(16, 20), @@ -282,9 +279,6 @@ class Test // (31,20): error CS8083: An alias-qualified name is not an expression. // s = nameof(global::Program); // not an expression Diagnostic(ErrorCode.ERR_AliasQualifiedNameNotAnExpression, "global::Program").WithLocation(31, 20), - // (32,20): error CS0305: Using the generic type 'Test' requires 1 type arguments - // s = nameof(Test<>.s); // inaccessible - Diagnostic(ErrorCode.ERR_BadArity, "Test<>").WithArguments("Test", "type", "1").WithLocation(32, 20), // (32,27): error CS0122: 'Test.s' is inaccessible due to its protection level // s = nameof(Test<>.s); // inaccessible Diagnostic(ErrorCode.ERR_BadAccess, "s").WithArguments("Test.s").WithLocation(32, 27), @@ -2632,7 +2626,6 @@ public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceObject CompileAndVerify( CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(IGoo<>.Count.ToString); Console.WriteLine(v); @@ -2653,7 +2646,7 @@ public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstr using System; using System.Collections.Generic; - var v = nameof(IGoo<>.Count.X.CompareTo); + var v = nameof(IGoo<>.X.CompareTo); Console.WriteLine(v); interface IGoo where T : IComparable From db4626624dc43dbd187c45a11a9bdbfae9247245 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:43:20 -0700 Subject: [PATCH 10/42] Fixup tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 45 +++++++++++++++++-- 1 file changed, 42 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 9c97c99de1bc5..9b657176b542d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -4,7 +4,6 @@ #nullable disable -using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using System.Threading; @@ -2639,12 +2638,11 @@ interface IGoo } [Fact] - public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember() + public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_Interface() { CompileAndVerify( CreateCompilation(""" using System; - using System.Collections.Generic; var v = nameof(IGoo<>.X.CompareTo); Console.WriteLine(v); @@ -2656,5 +2654,46 @@ interface IGoo where T : IComparable """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), expectedOutput: "CompareTo"); } + + [Fact] + public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_ThroughTypeParameter() + { + CompileAndVerify( + CreateCompilation(""" + using System; + + var v = nameof(IGoo<,>.X.CompareTo); + Console.WriteLine(v); + + interface IGoo where T : U where U : IComparable + { + T X { get; } + } + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "CompareTo"); + } + + [Fact] + public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_Class() + { + CompileAndVerify( + CreateCompilation(""" + using System; + + var v = nameof(IGoo<>.X.Z); + Console.WriteLine(v); + + class Base + { + public int Z { get; } + } + + interface IGoo where T : Base + { + T X { get; } + } + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + expectedOutput: "Z"); + } } } From 074bd23c2f186111320eec48d187467e07e6ee4a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 3 Oct 2024 12:53:26 -0700 Subject: [PATCH 11/42] Fix check --- src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 4c8a7e03fa39c..150d1d88e3eff 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2460,6 +2460,7 @@ or ErrorCode.ERR_CannotApplyOverloadResolutionPriorityToOverride or ErrorCode.ERR_CannotApplyOverloadResolutionPriorityToMember or ErrorCode.ERR_PartialPropertyDuplicateInitializer or ErrorCode.WRN_UninitializedNonNullableBackingField + or ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression => 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. From 08e46f4cdf0ba4ebfb0bf14690e7fcb666fac5ff Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 8 Oct 2024 12:11:19 -0700 Subject: [PATCH 12/42] Fix test --- .../Emit3/FlowAnalysis/FlowDiagnosticTests.cs | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/FlowDiagnosticTests.cs b/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/FlowDiagnosticTests.cs index 4a8797b493957..1cc9d48984c2c 100644 --- a/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/FlowDiagnosticTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/FlowAnalysis/FlowDiagnosticTests.cs @@ -858,10 +858,17 @@ public static int goo(int i) return 1; } }"; - var comp = CreateCompilation(program); - var parseErrors = comp.SyntaxTrees[0].GetDiagnostics(); - var errors = comp.GetDiagnostics(); - Assert.Equal(parseErrors.Count(), errors.Count()); + var comp = CreateCompilation(program).VerifyDiagnostics( + // (6,17): error CS0305: Using the generic method 'Program.goo(int)' requires 1 type arguments + // var s = goo<,int>(123); + Diagnostic(ErrorCode.ERR_BadArity, "goo<,int>").WithArguments("Program.goo(int)", "method", "1").WithLocation(6, 17), + // (6,21): error CS1031: Type expected + // var s = goo<,int>(123); + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(6, 21)); + comp.SyntaxTrees[0].GetDiagnostics().Verify( + // (6,21): error CS1031: Type expected + // var s = goo<,int>(123); + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(6, 21)); } [Fact] From 2198c857cf94d83a89bbcb3b8be6196eb242f8b2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 10 Oct 2024 13:36:07 -0700 Subject: [PATCH 13/42] message id --- src/Compilers/CSharp/Portable/Errors/MessageID.cs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 3583a4c4af182..0783ddd7a7a0f 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -476,11 +476,8 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) // C# preview features. case MessageID.IDS_FeatureFieldKeyword: -<<<<<<< HEAD - case MessageID.IDS_FeatureUnboundGenericTypesInNameof: -======= case MessageID.IDS_FeatureFirstClassSpan: ->>>>>>> upstream/main + case MessageID.IDS_FeatureUnboundGenericTypesInNameof: return LanguageVersion.Preview; // C# 13.0 features. From da8e09e6fd555eb215d20c6beb7d9a9f58e1023f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 13:41:16 -0800 Subject: [PATCH 14/42] Update src/Compilers/CSharp/Portable/Parser/LanguageParser.cs Co-authored-by: Julien Couvreur --- src/Compilers/CSharp/Portable/Parser/LanguageParser.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index f3345fab50efb..8ed96d2f9c71a 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -6052,7 +6052,7 @@ private ScanTypeFlags ScanPossibleTypeArgumentList( return result; } - // Allow for any chain of errant commas in teh generic name. like `Dictionary<,int>` or + // Allow for any chain of errant commas in the generic name. like `Dictionary<,int>` or // `Dictionary` We still want to think of these as generics, just with missing type-arguments, vs // some invalid tree-expression that we would otherwise form. if (this.CurrentToken.Kind == SyntaxKind.CommaToken) From 31474976a0f2c6f6b8b5d26476b52936be7671b4 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 13:45:22 -0800 Subject: [PATCH 15/42] ADd tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 9b657176b542d..529e7fdadf3a2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2382,6 +2382,30 @@ public void OpenTypeInNameof_CSharp13() Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Unbound generic types in nameof operator").WithLocation(4, 16)); } + [Fact] + public void OpenTypeInNameof_Next() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List<>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_Preview() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List<>); + Console.WriteLine(v); + """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + } + [Fact] public void OpenTypeInNameof_CSharp13_Nested1() { From 1df770bb23869ad9dc00d5ede15ca4bf63fe8c6a Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 13:47:01 -0800 Subject: [PATCH 16/42] Remove unnecessary options --- .../Test/Semantic/Semantics/NameOfTests.cs | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 529e7fdadf3a2..2604a25dfcb77 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2368,7 +2368,7 @@ class Attr : System.Attribute { public Attr(string s) {} }"; } [Fact] - public void OpenTypeInNameof_CSharp13() + public void OpenTypeInNameof_Preview() { CreateCompilation(""" using System; @@ -2376,14 +2376,11 @@ public void OpenTypeInNameof_CSharp13() var v = nameof(List<>); Console.WriteLine(v); - """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (4,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. - // var v = nameof(List<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Unbound generic types in nameof operator").WithLocation(4, 16)); + """).VerifyDiagnostics(); } [Fact] - public void OpenTypeInNameof_Next() + public void OpenTypeInNameof_CSharp13() { CreateCompilation(""" using System; @@ -2391,11 +2388,14 @@ public void OpenTypeInNameof_Next() var v = nameof(List<>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); + """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( + // (4,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // var v = nameof(List<>); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Unbound generic types in nameof operator").WithLocation(4, 16)); } [Fact] - public void OpenTypeInNameof_Preview() + public void OpenTypeInNameof_Next() { CreateCompilation(""" using System; @@ -2403,7 +2403,7 @@ public void OpenTypeInNameof_Preview() var v = nameof(List<>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); } [Fact] @@ -2467,7 +2467,7 @@ public void OpenTypeInNameof_BaseCase() var v = nameof(List<>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "List"); } @@ -2482,7 +2482,7 @@ public void OpenTypeInNameof_Nested1() Console.WriteLine(v); class A { public class B; } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "B"); } @@ -2497,7 +2497,7 @@ public void OpenTypeInNameof_Nested2() Console.WriteLine(v); class A { public class B; } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "B"); } @@ -2512,7 +2512,7 @@ public void OpenTypeInNameof_Nested3() Console.WriteLine(v); class A { public class B; } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "B"); } @@ -2526,7 +2526,7 @@ public void OpenTypeInNameof_MultipleTypeArguments() var v = nameof(Dictionary<,>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "Dictionary"); } @@ -2539,7 +2539,7 @@ public void OpenTypeInNameof_IncorrectTypeArgumentCount1() var v = nameof(Dictionary<>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + """).VerifyDiagnostics( // (2,1): hidden CS8019: Unnecessary using directive. // using System.Collections.Generic; Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1), @@ -2557,7 +2557,7 @@ public void OpenTypeInNameof_IncorrectTypeArgumentCount2() var v = nameof(List<,>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + """).VerifyDiagnostics( // (2,1): hidden CS8019: Unnecessary using directive. // using System.Collections.Generic; Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using System.Collections.Generic;").WithLocation(2, 1), @@ -2575,7 +2575,7 @@ public void OpenTypeInNameof_NoNestedOpenTypes() var v = nameof(List>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + """).VerifyDiagnostics( // (4,21): error CS9270: Nested unbound generic type not allowed in 'nameof' operator // var v = nameof(List>); Diagnostic(ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression, "List<>").WithLocation(4, 21)); @@ -2590,7 +2590,7 @@ public void OpenTypeInNameof_NoPartialOpenTypes_1() var v = nameof(Dictionary<,int>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + """).VerifyDiagnostics( // (4,27): error CS1031: Type expected // var v = nameof(Dictionary<,int>); Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(4, 27)); @@ -2605,7 +2605,7 @@ public void OpenTypeInNameof_NoPartialOpenTypes_2() var v = nameof(Dictionary); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( + """).VerifyDiagnostics( // (4,31): error CS1031: Type expected // var v = nameof(Dictionary); Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(4, 31)); @@ -2621,7 +2621,7 @@ public void OpenTypeInNameof_MemberAccessThatDoesNotUseTypeArgument() var v = nameof(List<>.Count); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "Count"); } @@ -2639,7 +2639,7 @@ interface IGoo { T Count { get; } } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "Count"); } @@ -2657,7 +2657,7 @@ interface IGoo { T Count { get; } } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "ToString"); } @@ -2675,7 +2675,7 @@ interface IGoo where T : IComparable { T X { get; } } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "CompareTo"); } @@ -2693,7 +2693,7 @@ interface IGoo where T : U where U : IComparable { T X { get; } } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "CompareTo"); } @@ -2716,7 +2716,7 @@ interface IGoo where T : Base { T X { get; } } - """, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics(), + """).VerifyDiagnostics(), expectedOutput: "Z"); } } From 5a695dc52f19c91450921a32b923422f9ea48b12 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 13:55:52 -0800 Subject: [PATCH 17/42] Add tests --- .../Parsing/TypeArgumentListParsingTests.cs | 878 +++++++++++++++++- 1 file changed, 874 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs index 9a47468d3af2b..4a14eda2eeba3 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/TypeArgumentListParsingTests.cs @@ -2,19 +2,17 @@ // 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 Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { - public class TypeArgumentListParsingTests : ParsingTests + public sealed class TypeArgumentListParsingTests : ParsingTests { public TypeArgumentListParsingTests(ITestOutputHelper output) : base(output) { } - protected override SyntaxTree ParseTree(string text, CSharpParseOptions options) + protected override SyntaxTree ParseTree(string text, CSharpParseOptions? options) { return SyntaxFactory.ParseSyntaxTree(text, options: options); } @@ -2826,5 +2824,877 @@ void M() } EOF(); } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes1() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo.Instance; + } + } + """, + // (5,32): error CS1031: Type expected + // var added = Goo.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 32), + // (5,33): error CS1031: Type expected + // var added = Goo.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 33)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.StringKeyword); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes2() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo.Instance; + } + } + """, + // (5,28): error CS1031: Type expected + // var added = Goo.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 28), + // (5,29): error CS1031: Type expected + // var added = Goo.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 29)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Id"); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes3() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo<,Id,>.Instance; + } + } + """, + // (5,25): error CS1031: Type expected + // var added = Goo<,Id,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 25), + // (5,29): error CS1031: Type expected + // var added = Goo<,Id,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 29)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Id"); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes4() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo<,,Id>.Instance; + } + } + """, + // (5,25): error CS1031: Type expected + // var added = Goo<,,Id>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 25), + // (5,26): error CS1031: Type expected + // var added = Goo<,,Id>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 26)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Id"); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes5() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo.Instance; + } + } + """, + // (5,30): error CS1031: Type expected + // var added = Goo.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 30), + // (5,31): error CS1031: Type expected + // var added = Goo.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 31)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.ArrayType); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Id"); + } + N(SyntaxKind.ArrayRankSpecifier); + { + N(SyntaxKind.OpenBracketToken); + N(SyntaxKind.OmittedArraySizeExpression); + { + N(SyntaxKind.OmittedArraySizeExpressionToken); + } + N(SyntaxKind.CloseBracketToken); + } + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes6() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo<(int i, int j),,>.Instance; + } + } + """, + // (5,40): error CS1031: Type expected + // var added = Goo<(int i, int j),,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 40), + // (5,41): error CS1031: Type expected + // var added = Goo<(int i, int j),,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 41)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.TupleType); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "i"); + } + N(SyntaxKind.CommaToken); + N(SyntaxKind.TupleElement); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.IdentifierToken, "j"); + } + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes7() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo,,>.Instance; + } + } + """, + // (5,32): error CS1031: Type expected + // var added = Goo,,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 32), + // (5,33): error CS1031: Type expected + // var added = Goo,,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 33)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "K"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } + + [Fact] + public void TestGenericWithExtraCommasAndMissingTypes8() + { + UsingTree(""" + class C + { + void M() + { + var added = Goo,,>.Instance; + } + } + """, + // (5,31): error CS1031: Type expected + // var added = Goo,,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 31), + // (5,32): error CS1031: Type expected + // var added = Goo,,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 32), + // (5,34): error CS1031: Type expected + // var added = Goo,,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(5, 34), + // (5,35): error CS1031: Type expected + // var added = Goo,,>.Instance; + Diagnostic(ErrorCode.ERR_TypeExpected, ">").WithLocation(5, 35)); + + N(SyntaxKind.CompilationUnit); + { + N(SyntaxKind.ClassDeclaration); + { + N(SyntaxKind.ClassKeyword); + N(SyntaxKind.IdentifierToken, "C"); + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.MethodDeclaration); + { + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.VoidKeyword); + } + N(SyntaxKind.IdentifierToken, "M"); + N(SyntaxKind.ParameterList); + { + N(SyntaxKind.OpenParenToken); + N(SyntaxKind.CloseParenToken); + } + N(SyntaxKind.Block); + { + N(SyntaxKind.OpenBraceToken); + N(SyntaxKind.LocalDeclarationStatement); + { + N(SyntaxKind.VariableDeclaration); + { + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "var"); + } + N(SyntaxKind.VariableDeclarator); + { + N(SyntaxKind.IdentifierToken, "added"); + N(SyntaxKind.EqualsValueClause); + { + N(SyntaxKind.EqualsToken); + N(SyntaxKind.SimpleMemberAccessExpression); + { + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "Goo"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.GenericName); + { + N(SyntaxKind.IdentifierToken, "K"); + N(SyntaxKind.TypeArgumentList); + { + N(SyntaxKind.LessThanToken); + N(SyntaxKind.PredefinedType); + { + N(SyntaxKind.IntKeyword); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.CommaToken); + M(SyntaxKind.IdentifierName); + { + M(SyntaxKind.IdentifierToken); + } + N(SyntaxKind.GreaterThanToken); + } + } + N(SyntaxKind.DotToken); + N(SyntaxKind.IdentifierName); + { + N(SyntaxKind.IdentifierToken, "Instance"); + } + } + } + } + } + N(SyntaxKind.SemicolonToken); + } + N(SyntaxKind.CloseBraceToken); + } + } + N(SyntaxKind.CloseBraceToken); + } + N(SyntaxKind.EndOfFileToken); + } + EOF(); + } } } From 4fcadd9681ec2c8ea9e1faac0f395b6bcb41b415 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 13:59:09 -0800 Subject: [PATCH 18/42] Simplify tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 192 ++++++++---------- 1 file changed, 85 insertions(+), 107 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 2604a25dfcb77..c93d5d859ebb5 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2460,74 +2460,64 @@ class A { public class B; } [Fact] public void OpenTypeInNameof_BaseCase() { - CompileAndVerify( - CreateCompilation(""" - using System; - using System.Collections.Generic; + CompileAndVerify(""" + using System; + using System.Collections.Generic; - var v = nameof(List<>); - Console.WriteLine(v); - """).VerifyDiagnostics(), - expectedOutput: "List"); + var v = nameof(List<>); + Console.WriteLine(v); + """, expectedOutput: "List").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_Nested1() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(A<>.B); - Console.WriteLine(v); + var v = nameof(A<>.B); + Console.WriteLine(v); - class A { public class B; } - """).VerifyDiagnostics(), - expectedOutput: "B"); + class A { public class B; } + """, expectedOutput: "B").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_Nested2() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(A.B<>); - Console.WriteLine(v); + var v = nameof(A.B<>); + Console.WriteLine(v); - class A { public class B; } - """).VerifyDiagnostics(), - expectedOutput: "B"); + class A { public class B; } + """, expectedOutput: "B").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_Nested3() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(A<>.B<>); - Console.WriteLine(v); + var v = nameof(A<>.B<>); + Console.WriteLine(v); - class A { public class B; } - """).VerifyDiagnostics(), - expectedOutput: "B"); + class A { public class B; } + """, expectedOutput: "B").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_MultipleTypeArguments() { - CompileAndVerify( - CreateCompilation(""" - using System; - using System.Collections.Generic; + CompileAndVerify(""" + using System; + using System.Collections.Generic; - var v = nameof(Dictionary<,>); - Console.WriteLine(v); - """).VerifyDiagnostics(), - expectedOutput: "Dictionary"); + var v = nameof(Dictionary<,>); + Console.WriteLine(v); + """, expectedOutput: "Dictionary").VerifyDiagnostics(); } [Fact] @@ -2614,110 +2604,98 @@ public void OpenTypeInNameof_NoPartialOpenTypes_2() [Fact] public void OpenTypeInNameof_MemberAccessThatDoesNotUseTypeArgument() { - CompileAndVerify( - CreateCompilation(""" - using System; - using System.Collections.Generic; + CompileAndVerify(""" + using System; + using System.Collections.Generic; - var v = nameof(List<>.Count); - Console.WriteLine(v); - """).VerifyDiagnostics(), - expectedOutput: "Count"); + var v = nameof(List<>.Count); + Console.WriteLine(v); + """, expectedOutput: "Count").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(IGoo<>.Count); - Console.WriteLine(v); + var v = nameof(IGoo<>.Count); + Console.WriteLine(v); - interface IGoo - { - T Count { get; } - } - """).VerifyDiagnostics(), - expectedOutput: "Count"); + interface IGoo + { + T Count { get; } + } + """, expectedOutput: "Count").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceObjectMember() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(IGoo<>.Count.ToString); - Console.WriteLine(v); + var v = nameof(IGoo<>.Count.ToString); + Console.WriteLine(v); - interface IGoo - { - T Count { get; } - } - """).VerifyDiagnostics(), - expectedOutput: "ToString"); + interface IGoo + { + T Count { get; } + } + """, expectedOutput: "ToString").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_Interface() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(IGoo<>.X.CompareTo); - Console.WriteLine(v); + var v = nameof(IGoo<>.X.CompareTo); + Console.WriteLine(v); - interface IGoo where T : IComparable - { - T X { get; } - } - """).VerifyDiagnostics(), - expectedOutput: "CompareTo"); + interface IGoo where T : IComparable + { + T X { get; } + } + """, expectedOutput: "CompareTo").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_ThroughTypeParameter() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(IGoo<,>.X.CompareTo); - Console.WriteLine(v); + var v = nameof(IGoo<,>.X.CompareTo); + Console.WriteLine(v); - interface IGoo where T : U where U : IComparable - { - T X { get; } - } - """).VerifyDiagnostics(), - expectedOutput: "CompareTo"); + interface IGoo where T : U where U : IComparable + { + T X { get; } + } + """, expectedOutput: "CompareTo").VerifyDiagnostics(); } [Fact] public void OpenTypeInNameof_MemberAccessThatDoesUseTypeArgument_ReferenceConstraintMember_Class() { - CompileAndVerify( - CreateCompilation(""" - using System; + CompileAndVerify(""" + using System; - var v = nameof(IGoo<>.X.Z); - Console.WriteLine(v); + var v = nameof(IGoo<>.X.Z); + Console.WriteLine(v); - class Base - { - public int Z { get; } - } + class Base + { + public int Z { get; } + } - interface IGoo where T : Base - { - T X { get; } - } - """).VerifyDiagnostics(), - expectedOutput: "Z"); + interface IGoo where T : Base + { + T X { get; } + } + """, expectedOutput: "Z").VerifyDiagnostics(); } } } From 7aff3440ea5f49733bf65b6e4b2b439ec7f51f89 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:12:15 -0800 Subject: [PATCH 19/42] Share open type binding --- .../Portable/Binder/Binder_Invocation.cs | 27 ----- .../CSharp/Portable/Binder/Binder_Symbols.cs | 2 +- .../CSharp/Portable/Binder/NameofBinder.cs | 12 ++- .../CSharp/Portable/Binder/OpenTypeVisitor.cs | 99 +++++++++++++++++++ .../CSharp/Portable/Binder/TypeofBinder.cs | 94 +----------------- .../CSharp/Portable/CSharpResources.resx | 3 - .../CSharp/Portable/Errors/ErrorCode.cs | 2 - .../CSharp/Portable/Errors/ErrorFacts.cs | 1 - .../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 - .../Test/Semantic/Semantics/NameOfTests.cs | 4 +- 22 files changed, 114 insertions(+), 195 deletions(-) create mode 100644 src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index cea3ebdc28da1..b1dfcab8fc30d 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -2222,8 +2222,6 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no CheckFeatureAvailability(node, MessageID.IDS_FeatureNameof, diagnostics); var argument = node.ArgumentList.Arguments[0].Expression; - validateOpenGenericNames(argument, topLevel: true); - var boundArgument = BindExpression(argument, diagnostics); bool syntaxIsOk = CheckSyntaxForNameofArgument(argument, out string name, boundArgument.HasAnyErrors ? BindingDiagnosticBag.Discarded : diagnostics); @@ -2248,31 +2246,6 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no boundArgument = BindToNaturalType(boundArgument, diagnostics, reportNoTargetType: false); return new BoundNameOfOperator(node, boundArgument, ConstantValue.Create(name), Compilation.GetSpecialType(SpecialType.System_String)); - - void validateOpenGenericNames(SyntaxNode current, bool topLevel) - { - if (current is TypeArgumentListSyntax typeArgumentList) - { - if (!topLevel) - { - foreach (var typeArgument in typeArgumentList.Arguments) - { - if (typeArgument.Kind() == SyntaxKind.OmittedTypeArgument) - diagnostics.Add(ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression, typeArgumentList.Parent); - } - } - - // Once we hit a type argument list, we're no longer at the top level, and we want to report errors - // for any omitted type arguments we see at a deeper level. - topLevel = false; - } - - foreach (var child in current.ChildNodesAndTokens()) - { - if (child.IsNode) - validateOpenGenericNames(child.AsNode(), topLevel); - } - } } private void EnsureNameofExpressionSymbols(BoundMethodGroup methodGroup, BindingDiagnosticBag diagnostics) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index aa1593be79fe3..7aebd527acc06 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1212,7 +1212,7 @@ private TypeWithAnnotations BindGenericSimpleNamespaceOrTypeOrAliasSymbol( if (isUnboundTypeExpr) { - if (!IsInsideNameof && !IsUnboundTypeAllowed(node)) + if (!IsUnboundTypeAllowed(node)) { // If we already have an error type then skip reporting that the unbound type is illegal. if (!unconstructedType.IsErrorType()) diff --git a/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs b/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs index 668cad30a97f3..acf4ba3dfcf59 100644 --- a/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/NameofBinder.cs @@ -2,7 +2,9 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Collections.Generic; using Microsoft.CodeAnalysis.CSharp.Symbols; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.CSharp @@ -19,19 +21,25 @@ namespace Microsoft.CodeAnalysis.CSharp /// internal sealed class NameofBinder : Binder { - private readonly SyntaxNode _nameofArgument; + private readonly ExpressionSyntax _nameofArgument; private readonly WithTypeParametersBinder? _withTypeParametersBinder; private readonly Binder? _withParametersBinder; private ThreeState _lazyIsNameofOperator; - internal NameofBinder(SyntaxNode nameofArgument, Binder next, WithTypeParametersBinder? withTypeParametersBinder, Binder? withParametersBinder) + private readonly Dictionary? _allowedMap; + + internal NameofBinder(ExpressionSyntax nameofArgument, Binder next, WithTypeParametersBinder? withTypeParametersBinder, Binder? withParametersBinder) : base(next) { _nameofArgument = nameofArgument; _withTypeParametersBinder = withTypeParametersBinder; _withParametersBinder = withParametersBinder; + OpenTypeVisitor.Visit(nameofArgument, out _allowedMap); } + protected override bool IsUnboundTypeAllowed(GenericNameSyntax syntax) + => _allowedMap != null && _allowedMap.TryGetValue(syntax, out bool allowed) && allowed; + private bool IsNameofOperator { get diff --git a/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs b/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs new file mode 100644 index 0000000000000..1b1b9c1326877 --- /dev/null +++ b/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs @@ -0,0 +1,99 @@ +// 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. + +using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; + +namespace Microsoft.CodeAnalysis.CSharp; + +internal partial class Binder +{ + /// + /// This visitor walks over a type expression looking for open types. + /// + /// Open types are allowed if an only if: + /// + /// There is no constructed generic type elsewhere in the visited syntax; and + /// The open type is not used as a type argument or array/pointer/nullable element type. + /// + /// + /// Open types can be used both in typeof(...) and nameof(...) expressions. + /// + protected sealed class OpenTypeVisitor : CSharpSyntaxVisitor + { + private Dictionary? _allowedMap; + private bool _seenConstructed; + + /// The argument to typeof. + /// + /// Keys are GenericNameSyntax nodes representing unbound generic types. + /// Values are false if the node should result in an error and true otherwise. + /// + public static void Visit(ExpressionSyntax typeSyntax, out Dictionary? allowedMap) + { + OpenTypeVisitor visitor = new OpenTypeVisitor(); + visitor.Visit(typeSyntax); + allowedMap = visitor._allowedMap; + } + + public override void VisitGenericName(GenericNameSyntax node) + { + SeparatedSyntaxList typeArguments = node.TypeArgumentList.Arguments; + if (node.IsUnboundGenericName) + { + _allowedMap ??= []; + _allowedMap[node] = !_seenConstructed; + } + else + { + _seenConstructed = true; + foreach (TypeSyntax arg in typeArguments) + { + Visit(arg); + } + } + } + + public override void VisitQualifiedName(QualifiedNameSyntax node) + { + bool seenConstructedBeforeRight = _seenConstructed; + + // Visit Right first because it's smaller (to make backtracking cheaper). + Visit(node.Right); + + bool seenConstructedBeforeLeft = _seenConstructed; + + Visit(node.Left); + + // If the first time we saw a constructed type was in Left, then we need to re-visit Right + if (!seenConstructedBeforeRight && !seenConstructedBeforeLeft && _seenConstructed) + { + Visit(node.Right); + } + } + + public override void VisitAliasQualifiedName(AliasQualifiedNameSyntax node) + { + Visit(node.Name); + } + + public override void VisitArrayType(ArrayTypeSyntax node) + { + _seenConstructed = true; + Visit(node.ElementType); + } + + public override void VisitPointerType(PointerTypeSyntax node) + { + _seenConstructed = true; + Visit(node.ElementType); + } + + public override void VisitNullableType(NullableTypeSyntax node) + { + _seenConstructed = true; + Visit(node.ElementType); + } + } +} diff --git a/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs b/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs index 279fbd58e052c..6ba2056754f2b 100644 --- a/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp /// should be considered open so that the flag can be set /// appropriately in BoundTypeOfOperator. /// - internal sealed class TypeofBinder : Binder + internal sealed partial class TypeofBinder : Binder { private readonly Dictionary _allowedMap; @@ -32,96 +32,6 @@ internal TypeofBinder(ExpressionSyntax typeExpression, Binder next) } protected override bool IsUnboundTypeAllowed(GenericNameSyntax syntax) - { - bool allowed; - return _allowedMap != null && _allowedMap.TryGetValue(syntax, out allowed) && allowed; - } - - /// - /// This visitor walks over a type expression looking for open types. - /// Open types are allowed if an only if: - /// 1) There is no constructed generic type elsewhere in the visited syntax; and - /// 2) The open type is not used as a type argument or array/pointer/nullable - /// element type. - /// - private class OpenTypeVisitor : CSharpSyntaxVisitor - { - private Dictionary _allowedMap; - private bool _seenConstructed; - - /// The argument to typeof. - /// - /// Keys are GenericNameSyntax nodes representing unbound generic types. - /// Values are false if the node should result in an error and true otherwise. - /// - public static void Visit(ExpressionSyntax typeSyntax, out Dictionary allowedMap) - { - OpenTypeVisitor visitor = new OpenTypeVisitor(); - visitor.Visit(typeSyntax); - allowedMap = visitor._allowedMap; - } - - public override void VisitGenericName(GenericNameSyntax node) - { - SeparatedSyntaxList typeArguments = node.TypeArgumentList.Arguments; - if (node.IsUnboundGenericName) - { - if (_allowedMap == null) - { - _allowedMap = new Dictionary(); - } - _allowedMap[node] = !_seenConstructed; - } - else - { - _seenConstructed = true; - foreach (TypeSyntax arg in typeArguments) - { - Visit(arg); - } - } - } - - public override void VisitQualifiedName(QualifiedNameSyntax node) - { - bool seenConstructedBeforeRight = _seenConstructed; - - // Visit Right first because it's smaller (to make backtracking cheaper). - Visit(node.Right); - - bool seenConstructedBeforeLeft = _seenConstructed; - - Visit(node.Left); - - // If the first time we saw a constructed type was in Left, then we need to re-visit Right - if (!seenConstructedBeforeRight && !seenConstructedBeforeLeft && _seenConstructed) - { - Visit(node.Right); - } - } - - public override void VisitAliasQualifiedName(AliasQualifiedNameSyntax node) - { - Visit(node.Name); - } - - public override void VisitArrayType(ArrayTypeSyntax node) - { - _seenConstructed = true; - Visit(node.ElementType); - } - - public override void VisitPointerType(PointerTypeSyntax node) - { - _seenConstructed = true; - Visit(node.ElementType); - } - - public override void VisitNullableType(NullableTypeSyntax node) - { - _seenConstructed = true; - Visit(node.ElementType); - } - } + => _allowedMap != null && _allowedMap.TryGetValue(syntax, out bool allowed) && allowed; } } diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 5c89169ebc8d0..3b72670421515 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -8008,9 +8008,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Non-nullable property must contain a non-null value when exiting constructor. Consider adding the 'required' modifier, or declaring the property as nullable, or adding '[field: MaybeNull, AllowNull]' attributes. - - Nested unbound generic type not allowed in 'nameof' operator - first-class Span types diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index 7918c9339f489..90e45ee89de30 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -2345,8 +2345,6 @@ internal enum ErrorCode ERR_CannotApplyOverloadResolutionPriorityToMember = 9262, ERR_PartialPropertyDuplicateInitializer = 9263, - ERR_NestedUnboundTypeNotAllowedInNameofExpression = 9270, - WRN_UninitializedNonNullableBackingField = 9264, WRN_UnassignedInternalRefField = 9265, WRN_AccessorDoesNotUseBackingField = 9266, diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs index 609393fa529ac..b3c03386122fa 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorFacts.cs @@ -2467,7 +2467,6 @@ or ErrorCode.WRN_UninitializedNonNullableBackingField or ErrorCode.WRN_UnassignedInternalRefField or ErrorCode.WRN_AccessorDoesNotUseBackingField or ErrorCode.ERR_IteratorRefLikeElementType - or ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression => 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/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 90f4f4128269f..d57d2056d6ac4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -1457,11 +1457,6 @@ Přístup k vloženému poli nemůže mít specifikátor pojmenovaného argumentu. - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint Omezení new() nejde používat s omezením unmanaged. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index de221dea80883..d1c2050f539cc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -1457,11 +1457,6 @@ Ein Inlinearrayzugriff verfügt möglicherweise nicht über einen benannten Argumentspezifizierer. - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint Die new()-Einschränkung kann nicht mit der unmanaged-Einschränkung verwendet werden. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index b3b218dad5b8d..18af306ceff6a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -1457,11 +1457,6 @@ Un acceso de matriz insertado no puede tener un especificador de argumento con nombre - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint La restricción "new()" no se puede utilizar con la restricción "unmanaged" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index cf9930538a830..20801aee27d5d 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -1457,11 +1457,6 @@ Un accès au tableau en ligne peut ne pas avoir de spécificateur d'argument nommé - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint La contrainte 'new()' ne peut pas être utilisée avec la contrainte 'unmanaged' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index a8ab3ed4f6fdf..4ffc922323fff 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -1457,11 +1457,6 @@ Un accesso a matrice inline non può includere un identificatore di argomento denominato - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint Non è possibile usare il vincolo 'new()' con il vincolo 'unmanaged' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 383f0a71d9d03..ce7577b0eff94 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -1457,11 +1457,6 @@ インライン配列のアクセスには名前付き引数の指定子を指定できません - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 制約は 'unmanaged' 制約と一緒には使用できません diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index e8efe2aab4a81..2b18ff361afec 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -1457,11 +1457,6 @@ 인라인 배열 액세스에는 명명된 인수 지정자가 없을 수 있습니다. - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 제약 조건은 'unmanaged' 제약 조건과 함께 사용할 수 없습니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index f6d441038d1ee..2db0850452569 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -1457,11 +1457,6 @@ Dostęp do tablicy śródwierszowej nie może mieć specyfikatora argumentu nazwanego - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint Ograniczenie „new()” nie może być używane z ograniczeniem „unmanaged” diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 9aa9dbaf780a2..eb945e5c7dece 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -1457,11 +1457,6 @@ Um acesso à matriz não pode ter um especificador de argumento nomeado - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint A restrição 'new()' não pode ser usada com a restrição 'unmanaged' diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index abcb4ac722ddc..7575c0f6172ac 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -1457,11 +1457,6 @@ Доступ к встроенному массиву может не иметь спецификатора именованного аргумента. - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint Ограничение "new()" невозможно использовать вместе с ограничением "unmanaged" diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 108d9cc367851..91fded227f750 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -1457,11 +1457,6 @@ Satır içi dizi erişiminin adlandırılmış bağımsız değişken belirticisi olamaz - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint 'new()' kısıtlaması, 'unmanaged' kısıtlamasıyla kullanılamaz diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index f69f68c1732a7..8612f36308be7 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -1457,11 +1457,6 @@ 内联数组访问可能没有命名参数说明符 - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint "new()" 约束不能与 "unmanaged" 约束一起使用 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 42d250ed421dd..2f63ff0cdce65 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -1457,11 +1457,6 @@ 內嵌陣列存取不能有具名引數指定名稱 - - Nested unbound generic type not allowed in 'nameof' operator - Nested unbound generic type not allowed in 'nameof' operator - - The 'new()' constraint cannot be used with the 'unmanaged' constraint new()' 條件約束不能和 'unmanaged' 條件約束一起使用 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index c93d5d859ebb5..2c77708276b69 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2566,9 +2566,9 @@ public void OpenTypeInNameof_NoNestedOpenTypes() var v = nameof(List>); Console.WriteLine(v); """).VerifyDiagnostics( - // (4,21): error CS9270: Nested unbound generic type not allowed in 'nameof' operator + // (4,21): error CS7003: Unexpected use of an unbound generic name // var v = nameof(List>); - Diagnostic(ErrorCode.ERR_NestedUnboundTypeNotAllowedInNameofExpression, "List<>").WithLocation(4, 21)); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21)); } [Fact] From f006bbb3f3daea0c7e44aec4aaa9ae4e9ac0a1d0 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:15:01 -0800 Subject: [PATCH 20/42] Update src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs --- src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs index b1dfcab8fc30d..fcf522526898d 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Invocation.cs @@ -2221,7 +2221,6 @@ private BoundExpression BindNameofOperatorInternal(InvocationExpressionSyntax no { CheckFeatureAvailability(node, MessageID.IDS_FeatureNameof, diagnostics); var argument = node.ArgumentList.Arguments[0].Expression; - var boundArgument = BindExpression(argument, diagnostics); bool syntaxIsOk = CheckSyntaxForNameofArgument(argument, out string name, boundArgument.HasAnyErrors ? BindingDiagnosticBag.Discarded : diagnostics); From 74a3fe0959c169c24fca2615b8c56fef03d10151 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:16:40 -0800 Subject: [PATCH 21/42] Update src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs --- src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs b/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs index 6ba2056754f2b..66e1192f235fe 100644 --- a/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs @@ -20,7 +20,7 @@ namespace Microsoft.CodeAnalysis.CSharp /// should be considered open so that the flag can be set /// appropriately in BoundTypeOfOperator. /// - internal sealed partial class TypeofBinder : Binder + internal sealed class TypeofBinder : Binder { private readonly Dictionary _allowedMap; From a671848d47923b78edeab0387a1a2cae25596e52 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:21:15 -0800 Subject: [PATCH 22/42] Add tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 41 ++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 2c77708276b69..34307cd7a70fa 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2557,7 +2557,7 @@ public void OpenTypeInNameof_IncorrectTypeArgumentCount2() } [Fact] - public void OpenTypeInNameof_NoNestedOpenTypes() + public void OpenTypeInNameof_NoNestedOpenTypes1() { CreateCompilation(""" using System; @@ -2571,6 +2571,45 @@ public void OpenTypeInNameof_NoNestedOpenTypes() Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21)); } + [Fact] + public void OpenTypeInNameof_NoNestedOpenTypes2() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List[]>); + Console.WriteLine(v); + """).VerifyDiagnostics( + // (4,21): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(List>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21)); + } + + [Fact] + public void Nameof_NestedClosedType1() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List>); + Console.WriteLine(v); + """).VerifyDiagnostics(); + } + + [Fact] + public void Nameof_NestedClosedType2() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List>); + Console.WriteLine(v); + """).VerifyDiagnostics(); + } + [Fact] public void OpenTypeInNameof_NoPartialOpenTypes_1() { From ae6727f85d2b66bbf6a84303870d76c60d171e5f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:24:06 -0800 Subject: [PATCH 23/42] Add tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 34307cd7a70fa..a7695da9cd697 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2586,6 +2586,40 @@ public void OpenTypeInNameof_NoNestedOpenTypes2() Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21)); } + [Fact] + public void OpenTypeInNameof_NoNestedOpenTypes3() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List.Inner>); + Console.WriteLine(v); + + public class Outer { public class Inner { } } + """).VerifyDiagnostics( + // (4,21): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(List.Inner>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "Outer<>").WithLocation(4, 21)); + } + + [Fact] + public void OpenTypeInNameof_NoNestedOpenTypes4() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List>); + Console.WriteLine(v); + + public class Outer { public class Inner { } } + """).VerifyDiagnostics( + // (4,27): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(List>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "Inner<>").WithLocation(4, 27)); + } + [Fact] public void Nameof_NestedClosedType1() { From 7a6328a59652cf0ed6aee2ee9586560ce1d145a5 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:38:43 -0800 Subject: [PATCH 24/42] Simplify --- src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 7aebd527acc06..576c0012a969a 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1377,23 +1377,20 @@ private NamedTypeSymbol ConstructNamedTypeUnlessTypeArgumentOmitted(SyntaxNode t { // Inside a nameof an open-generic type is acceptable. Fall through and bind the remainder accordingly. CheckFeatureAvailability(typeSyntax, MessageID.IDS_FeatureUnboundGenericTypesInNameof, diagnostics); - typeArguments = UnboundArgumentErrorTypeSymbol.CreateTypeArguments( - type.TypeParameters, - type.TypeParameters.Length, - errorInfo: null); } else { // Note: lookup won't have reported this, since the arity was correct. // CONSIDER: the text of this error message makes sense, but we might want to add a separate code. - Error(diagnostics, ErrorCode.ERR_BadArity, typeSyntax, type, MessageID.IDS_SK_TYPE.Localize(), typeArgumentsSyntax.Count); // If the syntax looks like an unbound generic type, then they probably wanted the definition. // Give an error indicating that the syntax is incorrect and then use the definition. // CONSIDER: we could construct an unbound generic type symbol, but that would probably be confusing // outside a typeof. - return type; + Error(diagnostics, ErrorCode.ERR_BadArity, typeSyntax, type, MessageID.IDS_SK_TYPE.Localize(), typeArgumentsSyntax.Count); } + + return type; } // we pass an empty basesBeingResolved here because this invocation is not on any possible path of From cf0df29f0dc4f819cb857f0dfae0360af844a47d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:43:08 -0800 Subject: [PATCH 25/42] Add semantic model test --- .../Test/Semantic/Semantics/NameOfTests.cs | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index a7695da9cd697..2c8f404a0b525 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2770,5 +2770,37 @@ interface IGoo where T : Base } """, expectedOutput: "Z").VerifyDiagnostics(); } + + [Fact] + public void OpenTypeInNameof_SemanticModelTests() + { + var compilation = CreateCompilation(""" + using System; + + var v1 = nameof(IGoo<>); + var v2 = typeof(IGoo<>); + Console.WriteLine(v1 + v2); + + interface IGoo { } + """).VerifyDiagnostics(); + var tree = compilation.SyntaxTrees.Single(); + var semanticModel = compilation.GetSemanticModel(tree); + + var root = tree.GetRoot(); + + var firstGeneric = root.DescendantNodes().OfType().First(); + var lastGeneric = root.DescendantNodes().OfType().Last(); + + Assert.NotSame(firstGeneric, lastGeneric); + + // Ensure the type inside the nameof is the same as the type inside the typeof. + var type1 = semanticModel.GetTypeInfo(firstGeneric).Type; + var type2 = semanticModel.GetTypeInfo(firstGeneric).Type; + + Assert.NotNull(type1); + Assert.NotNull(type2); + + Assert.Equal(type1, type2); + } } } From 5af3f7ad20a3ec2de62d72f5b08753d8c8f0ddbe Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:45:22 -0800 Subject: [PATCH 26/42] Update test --- .../CSharp/Test/Semantic/Semantics/NameOfTests.cs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 2c8f404a0b525..6dbcfe735f6bb 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2771,17 +2771,19 @@ interface IGoo where T : Base """, expectedOutput: "Z").VerifyDiagnostics(); } - [Fact] - public void OpenTypeInNameof_SemanticModelTests() + [Theory] + [InlineData("IGoo<>")] + [InlineData("IGoo<>.Count")] + public void OpenTypeInNameof_SemanticModelTest1(string nameofType) { - var compilation = CreateCompilation(""" + var compilation = CreateCompilation($$""" using System; - var v1 = nameof(IGoo<>); + var v1 = nameof({{nameofType}}); var v2 = typeof(IGoo<>); Console.WriteLine(v1 + v2); - interface IGoo { } + interface IGoo { public T Count { get; } } """).VerifyDiagnostics(); var tree = compilation.SyntaxTrees.Single(); var semanticModel = compilation.GetSemanticModel(tree); From 48688a53b72e5a7e4cc800f771d71f989368f0c1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 14:58:05 -0800 Subject: [PATCH 27/42] Add testS --- .../Test/Semantic/Semantics/NameOfTests.cs | 54 +++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 6dbcfe735f6bb..b9f520ed140d0 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2771,6 +2771,60 @@ interface IGoo where T : Base """, expectedOutput: "Z").VerifyDiagnostics(); } + [Fact] + public void OpenTypeInNameof_GenericMethod1() + { + CompileAndVerify(""" + using System; + + var v = nameof(IGoo.M); + Console.WriteLine(v); + + interface IGoo + { + void M(); + } + """, expectedOutput: "M").VerifyDiagnostics(); + } + + [Fact] + public void OpenTypeInNameof_GenericMethod2() + { + CreateCompilation(""" + using System; + + var v = nameof(IGoo.M<>); + Console.WriteLine(v); + + interface IGoo + { + void M(); + } + """).VerifyDiagnostics( + // (3,16): error CS0305: Using the generic method group 'M' requires 1 type arguments + // var v = nameof(IGoo.M<>); + Diagnostic(ErrorCode.ERR_BadArity, "IGoo.M<>").WithArguments("M", "method group", "1").WithLocation(3, 16)); + } + + [Fact] + public void OpenTypeInNameof_GenericMethod3() + { + CreateCompilation(""" + using System; + + var v = nameof(IGoo.M); + Console.WriteLine(v); + + interface IGoo + { + void M(); + } + """).VerifyDiagnostics( + // (3,16): error CS8084: Type parameters are not allowed on a method group as an argument to 'nameof'. + // var v = nameof(IGoo.M); + Diagnostic(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, "IGoo.M").WithLocation(3, 16)); + } + [Theory] [InlineData("IGoo<>")] [InlineData("IGoo<>.Count")] From d0b7fa551d08e8b0beed4fd40bd4a6d9bb7a550d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 16:08:43 -0800 Subject: [PATCH 28/42] Update test --- src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index b9f520ed140d0..13ffdbd2e5a6a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2851,12 +2851,12 @@ interface IGoo { public T Count { get; } } // Ensure the type inside the nameof is the same as the type inside the typeof. var type1 = semanticModel.GetTypeInfo(firstGeneric).Type; - var type2 = semanticModel.GetTypeInfo(firstGeneric).Type; + var type2 = semanticModel.GetTypeInfo(lastGeneric).Type; Assert.NotNull(type1); Assert.NotNull(type2); - Assert.Equal(type1, type2); + Assert.NotEqual(type1, type2); } } } From 13e7eba07d3643a15bcbbc74a347bcd570beb233 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 16:10:07 -0800 Subject: [PATCH 29/42] Update test --- src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 13ffdbd2e5a6a..86120193c10e2 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2639,7 +2639,7 @@ public void Nameof_NestedClosedType2() using System; using System.Collections.Generic; - var v = nameof(List>); + var v = nameof(List[]>); Console.WriteLine(v); """).VerifyDiagnostics(); } From 1e6366f565c60b6cf6b87254c8a9d67a0a4a5ebf Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 17:19:44 -0800 Subject: [PATCH 30/42] Add docs and tests --- .../CSharp/Portable/Binder/Binder_Symbols.cs | 9 +++++++++ .../Test/Semantic/Semantics/NameOfTests.cs | 19 ++++++++++++------- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 576c0012a969a..5b1564b9e09d7 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1377,6 +1377,15 @@ private NamedTypeSymbol ConstructNamedTypeUnlessTypeArgumentOmitted(SyntaxNode t { // Inside a nameof an open-generic type is acceptable. Fall through and bind the remainder accordingly. CheckFeatureAvailability(typeSyntax, MessageID.IDS_FeatureUnboundGenericTypesInNameof, diagnostics); + + // From the spec: + // + // Member lookup on an unbound type expression will be performed the same way as for a `this` + // expression within that type declaration. + // + // So we want to just return the originating type symbol as is (e.g. List in nameof(List<>)). + // This is distinctly different than how typeof(List<>) works, where it returns an unbound generic + // type. } else { diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 86120193c10e2..7349c25dec38d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2828,12 +2828,12 @@ interface IGoo [Theory] [InlineData("IGoo<>")] [InlineData("IGoo<>.Count")] - public void OpenTypeInNameof_SemanticModelTest1(string nameofType) + public void OpenTypeInNameof_SemanticModelTest1(string nameofTypeString) { var compilation = CreateCompilation($$""" using System; - var v1 = nameof({{nameofType}}); + var v1 = nameof({{nameofTypeString}}); var v2 = typeof(IGoo<>); Console.WriteLine(v1 + v2); @@ -2850,13 +2850,18 @@ interface IGoo { public T Count { get; } } Assert.NotSame(firstGeneric, lastGeneric); // Ensure the type inside the nameof is the same as the type inside the typeof. - var type1 = semanticModel.GetTypeInfo(firstGeneric).Type; - var type2 = semanticModel.GetTypeInfo(lastGeneric).Type; + var nameofType = semanticModel.GetTypeInfo(firstGeneric).Type; + var typeofType = semanticModel.GetTypeInfo(lastGeneric).Type; - Assert.NotNull(type1); - Assert.NotNull(type2); + Assert.NotNull(nameofType); + Assert.NotNull(typeofType); - Assert.NotEqual(type1, type2); + Assert.NotEqual(nameofType, typeofType); + + var igooType = compilation.GetTypeByMetadataName("IGoo`1").GetPublicSymbol(); + Assert.NotNull(igooType); + + Assert.Equal(igooType, nameofType); } } } From 739a4ef95a761cd4cf9db96ae505746b449e9ed7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 14 Nov 2024 17:21:06 -0800 Subject: [PATCH 31/42] Update test --- src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 7349c25dec38d..1024d22990f6c 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2856,8 +2856,13 @@ interface IGoo { public T Count { get; } } Assert.NotNull(nameofType); Assert.NotNull(typeofType); + // typeof will produce IGoo<>, while nameof will produce IGoo. These are distinctly different types (the + // latter has members for example). Assert.NotEqual(nameofType, typeofType); + Assert.Empty(typeofType.GetMembers("Count")); + Assert.Single(nameofType.GetMembers("Count")); + var igooType = compilation.GetTypeByMetadataName("IGoo`1").GetPublicSymbol(); Assert.NotNull(igooType); From 401ec47c51cc44ad948bc6a4e03798b19a4158a7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 15 Nov 2024 13:15:14 -0800 Subject: [PATCH 32/42] Add more checks --- src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs | 6 ++++++ src/Compilers/Test/Utilities/CSharp/Extensions.cs | 4 +--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 1024d22990f6c..74e55cf4e90fa 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2860,6 +2860,12 @@ interface IGoo { public T Count { get; } } // latter has members for example). Assert.NotEqual(nameofType, typeofType); + Assert.True(nameofType.IsDefinition); + Assert.False(nameofType.IsUnboundGenericType()); + + Assert.False(typeofType.IsDefinition); + Assert.True(typeofType.IsUnboundGenericType()); + Assert.Empty(typeofType.GetMembers("Count")); Assert.Single(nameofType.GetMembers("Count")); diff --git a/src/Compilers/Test/Utilities/CSharp/Extensions.cs b/src/Compilers/Test/Utilities/CSharp/Extensions.cs index 6b4e838a76726..13cd405a7b597 100644 --- a/src/Compilers/Test/Utilities/CSharp/Extensions.cs +++ b/src/Compilers/Test/Utilities/CSharp/Extensions.cs @@ -764,9 +764,7 @@ public static ImmutableArray GetParameters(this ISymbol member } public static bool IsUnboundGenericType(this ITypeSymbol type) - { - return type is INamedTypeSymbol namedType && namedType.IsUnboundGenericType; - } + => type is INamedTypeSymbol { IsUnboundGenericType: true }; public static bool GivesAccessTo(this AssemblySymbol first, AssemblySymbol second) { From 9497a5ec07bdcd90dcc86cc4e29f156b6c65a1b7 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 09:03:00 -0800 Subject: [PATCH 33/42] rename --- .../CSharp/Portable/CSharpResources.resx | 2 +- .../Test/Semantic/Semantics/NameOfTests.cs | 20 +++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 67840d39fa4f2..85dd758873c3f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4933,7 +4933,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator dictionary initializer diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 74e55cf4e90fa..f43c1101589f9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2389,9 +2389,9 @@ public void OpenTypeInNameof_CSharp13() var v = nameof(List<>); Console.WriteLine(v); """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (4,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (4,16): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(List<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("Unbound generic types in nameof operator").WithLocation(4, 16)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "List<>").WithArguments("unbound generic types in nameof operator").WithLocation(4, 16)); } [Fact] @@ -2417,9 +2417,9 @@ public void OpenTypeInNameof_CSharp13_Nested1() class A { public class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (3,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (3,16): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A<>.B); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 16)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 16)); } [Fact] @@ -2433,9 +2433,9 @@ public void OpenTypeInNameof_CSharp13_Nested2() class A { public class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (3,23): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (3,23): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A.B<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 23)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 23)); } [Fact] @@ -2449,12 +2449,12 @@ public void OpenTypeInNameof_CSharp13_Nested3() class A { public class B; } """, parseOptions: TestOptions.Regular13).VerifyDiagnostics( - // (3,16): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // (3,16): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A<>.B<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 16), - // (3,20): error CS8652: The feature 'Unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + Diagnostic(ErrorCode.ERR_FeatureInPreview, "A<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 16), + // (3,20): error CS8652: The feature 'unbound generic types in nameof operator' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. // var v = nameof(A<>.B<>); - Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("Unbound generic types in nameof operator").WithLocation(3, 20)); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "B<>").WithArguments("unbound generic types in nameof operator").WithLocation(3, 20)); } [Fact] From 7ed0bfe6c8a86c8386e31d29210ec33fd5ef6a5c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 09:07:44 -0800 Subject: [PATCH 34/42] do not use collection expression --- src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs b/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs index 1b1b9c1326877..7654a5e40e9e1 100644 --- a/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs +++ b/src/Compilers/CSharp/Portable/Binder/OpenTypeVisitor.cs @@ -42,7 +42,7 @@ public override void VisitGenericName(GenericNameSyntax node) SeparatedSyntaxList typeArguments = node.TypeArgumentList.Arguments; if (node.IsUnboundGenericName) { - _allowedMap ??= []; + _allowedMap ??= new Dictionary(); _allowedMap[node] = !_seenConstructed; } else From 30c1a45eae94a60278fc05456bcc97a0721ab1ab Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 09:09:13 -0800 Subject: [PATCH 35/42] do not use expr body or out var --- src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs b/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs index 66e1192f235fe..7f0c3d231363e 100644 --- a/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs +++ b/src/Compilers/CSharp/Portable/Binder/TypeofBinder.cs @@ -32,6 +32,9 @@ internal TypeofBinder(ExpressionSyntax typeExpression, Binder next) } protected override bool IsUnboundTypeAllowed(GenericNameSyntax syntax) - => _allowedMap != null && _allowedMap.TryGetValue(syntax, out bool allowed) && allowed; + { + bool allowed; + return _allowedMap != null && _allowedMap.TryGetValue(syntax, out allowed) && allowed; + } } } From efeea4cc85ab26a5e72b0894c5274a5f531a4777 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 09:26:44 -0800 Subject: [PATCH 36/42] Add tesets --- .../Portable/xlf/CSharpResources.cs.xlf | 4 +- .../Portable/xlf/CSharpResources.de.xlf | 4 +- .../Portable/xlf/CSharpResources.es.xlf | 4 +- .../Portable/xlf/CSharpResources.fr.xlf | 4 +- .../Portable/xlf/CSharpResources.it.xlf | 4 +- .../Portable/xlf/CSharpResources.ja.xlf | 4 +- .../Portable/xlf/CSharpResources.ko.xlf | 4 +- .../Portable/xlf/CSharpResources.pl.xlf | 4 +- .../Portable/xlf/CSharpResources.pt-BR.xlf | 4 +- .../Portable/xlf/CSharpResources.ru.xlf | 4 +- .../Portable/xlf/CSharpResources.tr.xlf | 4 +- .../Portable/xlf/CSharpResources.zh-Hans.xlf | 4 +- .../Portable/xlf/CSharpResources.zh-Hant.xlf | 4 +- .../Test/Semantic/Semantics/NameOfTests.cs | 107 ++++++++++++++++++ .../Test/Semantic/Semantics/TypeOfTests.cs | 62 ++++++++++ 15 files changed, 195 insertions(+), 26 deletions(-) diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 34990bbc79621..a5d4e7d459849 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index b5cfe0057f869..49661004a2962 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index fe0550138a8bb..581451baade5e 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index bb071c083d82f..246bddbdd5cc6 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 5b99259647824..438db326e9229 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index a59c803c0f335..e6eb82d333c76 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index 11686860ab693..303ca7e9dc7a5 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index 1041c8c9b9c0c..a0d2f13e94d99 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 1e34a32c674ce..e6828357934e3 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 85ad495f3ee09..af40b0f4b46af 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 7e4009a05b044..62efb622ebeaf 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index 1f180771820bc..6f8caf4fd86c1 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index 7ab84a8b739d5..c8ffa8fac8617 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2578,8 +2578,8 @@ - Unbound generic types in nameof operator - Unbound generic types in nameof operator + unbound generic types in nameof operator + unbound generic types in nameof operator diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index f43c1101589f9..a5d6212f1c1f9 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2825,6 +2825,113 @@ interface IGoo Diagnostic(ErrorCode.ERR_NameofMethodGroupWithTypeParameters, "IGoo.M").WithLocation(3, 16)); } + [Fact] + public void NameofFunctionPointer1() + { + CreateCompilation(""" + class C + { + unsafe void M() + { + var v = nameof(delegate*); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (5,32): error CS1514: { expected + // var v = nameof(delegate*); + Diagnostic(ErrorCode.ERR_LbraceExpected, "*").WithLocation(5, 32), + // (5,32): warning CS8848: Operator '*' cannot be used here due to precedence. Use parentheses to disambiguate. + // var v = nameof(delegate*); + Diagnostic(ErrorCode.WRN_PrecedenceInversion, "*").WithArguments("*").WithLocation(5, 32), + // (5,33): error CS1525: Invalid expression term '<' + // var v = nameof(delegate*); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(5, 33), + // (5,34): error CS1525: Invalid expression term 'int' + // var v = nameof(delegate*); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "int").WithArguments("int").WithLocation(5, 34), + // (5,38): error CS1525: Invalid expression term ')' + // var v = nameof(delegate*); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(5, 38)); + } + + [Fact] + public void NameofFunctionPointer2() + { + CreateCompilation(""" + using System.Collections.Generic; + + class C + { + unsafe void M() + { + var v = nameof(delegate*>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (7,32): error CS1514: { expected + // var v = nameof(delegate*>); + Diagnostic(ErrorCode.ERR_LbraceExpected, "*").WithLocation(7, 32), + // (7,32): warning CS8848: Operator '*' cannot be used here due to precedence. Use parentheses to disambiguate. + // var v = nameof(delegate*>); + Diagnostic(ErrorCode.WRN_PrecedenceInversion, "*").WithArguments("*").WithLocation(7, 32), + // (7,33): error CS1525: Invalid expression term '<' + // var v = nameof(delegate*>); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, "<").WithArguments("<").WithLocation(7, 33), + // (7,34): error CS0119: 'List' is a type, which is not valid in the given context + // var v = nameof(delegate*>); + Diagnostic(ErrorCode.ERR_BadSKunknown, "List<>").WithArguments("System.Collections.Generic.List", "type").WithLocation(7, 34), + // (7,41): error CS1525: Invalid expression term ')' + // var v = nameof(delegate*>); + Diagnostic(ErrorCode.ERR_InvalidExprTerm, ")").WithArguments(")").WithLocation(7, 41)); + } + + [Fact] + public void NameofFunctionPointer3() + { + CreateCompilation(""" + using System.Collections.Generic; + + class C + { + unsafe void M() + { + var v = nameof(List>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (7,13): warning CS0219: The variable 'v' is assigned but its value is never used + // var v = nameof(List>); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "v").WithArguments("v").WithLocation(7, 13), + // (7,29): error CS0306: The type 'delegate*' may not be used as a type argument + // var v = nameof(List>); + Diagnostic(ErrorCode.ERR_BadTypeArgument, "delegate*").WithArguments("delegate*").WithLocation(7, 29)); + } + + [Fact] + public void NameofFunctionPointer4() + { + CreateCompilation(""" + using System.Collections.Generic; + + class C + { + unsafe void M() + { + var v = nameof(List>>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (7,13): warning CS0219: The variable 'v' is assigned but its value is never used + // var v = nameof(List>>); + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "v").WithArguments("v").WithLocation(7, 13), + // (7,29): error CS0306: The type 'delegate*>' may not be used as a type argument + // var v = nameof(List>>); + Diagnostic(ErrorCode.ERR_BadTypeArgument, "delegate*>").WithArguments("delegate*>").WithLocation(7, 29), + // (7,39): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(List>>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 39)); + } + [Theory] [InlineData("IGoo<>")] [InlineData("IGoo<>.Count")] diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs index 61ee254c26203..d402ddeaad902 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs @@ -37,7 +37,69 @@ public C(int i) Assert.Equal("C..ctor(System.Int32 i)", symbolInfo.Symbol.ToTestDisplayString()); var typeInfo = model.GetTypeInfo(node); Assert.Equal("C", typeInfo.Type.ToTestDisplayString()); + } + + [Fact] + public void TypeofPointer() + { + CreateCompilation(""" + class C + { + unsafe void M() + { + var v = typeof(int*); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); + } + + [Fact] + public void TypeofFunctionPointer1() + { + CreateCompilation(""" + class C + { + unsafe void M() + { + var v = typeof(delegate*); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); + } + + [Fact] + public void TypeofFunctionPointer2() + { + CreateCompilation(""" + using System.Collections.Generic; + + class C + { + unsafe void M() + { + var v = typeof(delegate*,int>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics(); + } + + [Fact] + public void TypeofFunctionPointer3() + { + CreateCompilation(""" + using System.Collections.Generic; + class C + { + unsafe void M() + { + var v = typeof(delegate*,int>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (7,34): error CS7003: Unexpected use of an unbound generic name + // var v = typeof(delegate*,int>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 34)); } } } From f77d4d00e0dda379397e7486daf17dcd1832d747 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 09:31:32 -0800 Subject: [PATCH 37/42] Adding tests --- .../Test/Semantic/Semantics/NameOfTests.cs | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index a5d6212f1c1f9..a24109caecf42 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2932,6 +2932,62 @@ unsafe void M() Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 39)); } + [Fact] + public void Namof_NestedOpenType1() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List[]>); + Console.WriteLine(v); + """).VerifyDiagnostics(); + } + + [Fact] + public void Namof_NestedOpenType2() + { + CreateCompilation(""" + using System; + using System.Collections.Generic; + + var v = nameof(List[]>); + Console.WriteLine(v); + """).VerifyDiagnostics( + // (4,21): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(List[]>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(4, 21)); + } + + [Fact] + public void Namof_NestedOpenType3() + { + CreateCompilation(""" + #nullable enable + using System; + using System.Collections.Generic; + + var v = nameof(List?>); + Console.WriteLine(v); + """).VerifyDiagnostics(); + } + + [Fact] + public void Namof_NestedOpenType4() + { + CreateCompilation(""" + #nullable enable + using System; + using System.Collections.Generic; + + var v = nameof(List?>); + Console.WriteLine(v); + """).VerifyDiagnostics( + // (5,21): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(List?>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(5, 21)); + } + [Theory] [InlineData("IGoo<>")] [InlineData("IGoo<>.Count")] From 0a3e50a2a2bf6dae5ac2e84fb84b99b63c244636 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 09:48:54 -0800 Subject: [PATCH 38/42] use explicit else clause --- .../CSharp/Portable/Binder/Binder_Symbols.cs | 10 ++++++---- .../Test/Semantic/Semantics/NameOfTests.cs | 19 +++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 5b1564b9e09d7..b3c42874d46a0 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -1401,10 +1401,12 @@ private NamedTypeSymbol ConstructNamedTypeUnlessTypeArgumentOmitted(SyntaxNode t return type; } - - // we pass an empty basesBeingResolved here because this invocation is not on any possible path of - // infinite recursion in binding base clauses. - return ConstructNamedType(type, typeSyntax, typeArgumentsSyntax, typeArguments, basesBeingResolved: null, diagnostics: diagnostics); + else + { + // we pass an empty basesBeingResolved here because this invocation is not on any possible path of + // infinite recursion in binding base clauses. + return ConstructNamedType(type, typeSyntax, typeArgumentsSyntax, typeArguments, basesBeingResolved: null, diagnostics: diagnostics); + } } /// diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index a24109caecf42..a22a10cb8453a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2933,7 +2933,7 @@ unsafe void M() } [Fact] - public void Namof_NestedOpenType1() + public void Nameof_NestedOpenType1() { CreateCompilation(""" using System; @@ -2945,7 +2945,7 @@ public void Namof_NestedOpenType1() } [Fact] - public void Namof_NestedOpenType2() + public void Nameof_NestedOpenType2() { CreateCompilation(""" using System; @@ -2960,7 +2960,7 @@ public void Namof_NestedOpenType2() } [Fact] - public void Namof_NestedOpenType3() + public void Nameof_NestedOpenType3() { CreateCompilation(""" #nullable enable @@ -2973,7 +2973,7 @@ public void Namof_NestedOpenType3() } [Fact] - public void Namof_NestedOpenType4() + public void Nameof_NestedOpenType4() { CreateCompilation(""" #nullable enable @@ -2988,6 +2988,17 @@ public void Namof_NestedOpenType4() Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(5, 21)); } + [Fact] + public void Nameof_AliasQualifiedName() + { + CreateCompilation(""" + using System; + + var v = nameof(global::System.Collections.Generic.List<>); + Console.WriteLine(v); + """).VerifyDiagnostics(); + } + [Theory] [InlineData("IGoo<>")] [InlineData("IGoo<>.Count")] From 21d4a4e19601b8e39d8479b76700797b679f37f8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 10:18:58 -0800 Subject: [PATCH 39/42] validate runtime behavior --- .../Test/Semantic/Semantics/NameOfTests.cs | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index a22a10cb8453a..cf4ff3cdac972 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2370,13 +2370,13 @@ class Attr : System.Attribute { public Attr(string s) {} }"; [Fact] public void OpenTypeInNameof_Preview() { - CreateCompilation(""" + CompileAndVerify(""" using System; using System.Collections.Generic; var v = nameof(List<>); Console.WriteLine(v); - """).VerifyDiagnostics(); + """, expectedOutput: "List").VerifyDiagnostics(); } [Fact] @@ -2397,13 +2397,13 @@ public void OpenTypeInNameof_CSharp13() [Fact] public void OpenTypeInNameof_Next() { - CreateCompilation(""" + CompileAndVerify(""" using System; using System.Collections.Generic; var v = nameof(List<>); Console.WriteLine(v); - """, parseOptions: TestOptions.RegularNext).VerifyDiagnostics(); + """, parseOptions: TestOptions.RegularNext, expectedOutput: "List").VerifyDiagnostics(); } [Fact] @@ -2623,25 +2623,25 @@ public class Outer { public class Inner { } } [Fact] public void Nameof_NestedClosedType1() { - CreateCompilation(""" + CompileAndVerify(""" using System; using System.Collections.Generic; var v = nameof(List>); Console.WriteLine(v); - """).VerifyDiagnostics(); + """, expectedOutput: "List").VerifyDiagnostics(); } [Fact] public void Nameof_NestedClosedType2() { - CreateCompilation(""" + CompileAndVerify(""" using System; using System.Collections.Generic; var v = nameof(List[]>); Console.WriteLine(v); - """).VerifyDiagnostics(); + """, expectedOutput: "List").VerifyDiagnostics(); } [Fact] @@ -2935,13 +2935,13 @@ unsafe void M() [Fact] public void Nameof_NestedOpenType1() { - CreateCompilation(""" + CompileAndVerify(""" using System; using System.Collections.Generic; var v = nameof(List[]>); Console.WriteLine(v); - """).VerifyDiagnostics(); + """, expectedOutput: "List").VerifyDiagnostics(); } [Fact] @@ -2962,14 +2962,14 @@ public void Nameof_NestedOpenType2() [Fact] public void Nameof_NestedOpenType3() { - CreateCompilation(""" + CompileAndVerify(""" #nullable enable using System; using System.Collections.Generic; var v = nameof(List?>); Console.WriteLine(v); - """).VerifyDiagnostics(); + """, expectedOutput: "List").VerifyDiagnostics(); } [Fact] @@ -2991,12 +2991,12 @@ public void Nameof_NestedOpenType4() [Fact] public void Nameof_AliasQualifiedName() { - CreateCompilation(""" + CompileAndVerify(""" using System; var v = nameof(global::System.Collections.Generic.List<>); Console.WriteLine(v); - """).VerifyDiagnostics(); + """, expectedOutput: "List").VerifyDiagnostics(); } [Theory] From 0be4c20136337d9555e58d86d089954a2c443cad Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 10:19:48 -0800 Subject: [PATCH 40/42] Do not use expression bodies or patterns --- src/Compilers/Test/Utilities/CSharp/Extensions.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Compilers/Test/Utilities/CSharp/Extensions.cs b/src/Compilers/Test/Utilities/CSharp/Extensions.cs index 13cd405a7b597..6b4e838a76726 100644 --- a/src/Compilers/Test/Utilities/CSharp/Extensions.cs +++ b/src/Compilers/Test/Utilities/CSharp/Extensions.cs @@ -764,7 +764,9 @@ public static ImmutableArray GetParameters(this ISymbol member } public static bool IsUnboundGenericType(this ITypeSymbol type) - => type is INamedTypeSymbol { IsUnboundGenericType: true }; + { + return type is INamedTypeSymbol namedType && namedType.IsUnboundGenericType; + } public static bool GivesAccessTo(this AssemblySymbol first, AssemblySymbol second) { From a0e8e13ea257931c9ba260c07c2bac5050c27b75 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 11:00:22 -0800 Subject: [PATCH 41/42] Add typeof teest --- .../Test/Semantic/Semantics/TypeOfTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs index d402ddeaad902..fbb75ecdb1d65 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/TypeOfTests.cs @@ -101,5 +101,27 @@ unsafe void M() // var v = typeof(delegate*,int>); Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 34)); } + + [Fact] + public void TypeofFunctionPointer4() + { + CreateCompilation(""" + using System.Collections.Generic; + + class D + { + unsafe void M() + { + var v = typeof(D<, delegate*, List<>>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (7,26): error CS1031: Type expected + // var v = typeof(D<, delegate*, List<>>); + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(7, 26), + // (7,44): error CS7003: Unexpected use of an unbound generic name + // var v = typeof(D<, delegate*, List<>>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 44)); + } } } From 4d19b869eb3b3625eb142649d7a53b5ee65cf2b4 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 19 Nov 2024 11:02:06 -0800 Subject: [PATCH 42/42] Add nameof teest --- .../Test/Semantic/Semantics/NameOfTests.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index cf4ff3cdac972..216a495096a2a 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -2932,6 +2932,28 @@ unsafe void M() Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 39)); } + [Fact] + public void NameofFunctionPointer5() + { + CreateCompilation(""" + using System.Collections.Generic; + + class D + { + unsafe void M() + { + var v = nameof(D<, delegate*, List<>>); + } + } + """, options: TestOptions.UnsafeReleaseDll).VerifyDiagnostics( + // (7,26): error CS1031: Type expected + // var v = nameof(D<, delegate*, List<>>); + Diagnostic(ErrorCode.ERR_TypeExpected, ",").WithLocation(7, 26), + // (7,44): error CS7003: Unexpected use of an unbound generic name + // var v = nameof(D<, delegate*, List<>>); + Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "List<>").WithLocation(7, 44)); + } + [Fact] public void Nameof_NestedOpenType1() {