diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 435dbe470fa32..3fc5f7db8eeeb 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -2075,19 +2075,18 @@ private BoundExpression SynthesizeReceiver(SyntaxNode node, Symbol member, Bindi (currentType.IsInterface && (declaringType.IsObjectType() || currentType.AllInterfacesNoUseSiteDiagnostics.Contains(declaringType)))) { bool hasErrors = false; - if (EnclosingNameofArgument != node) + if (!IsInsideNameof || (EnclosingNameofArgument != node && !IsFeatureAvailable(node, MessageID.IDS_FeatureReducedMemberAccessChecksInNameof))) { + DiagnosticInfo diagnosticInfoOpt = null; if (InFieldInitializer && !currentType.IsScriptClass) { //can't access "this" in field initializers - Error(diagnostics, ErrorCode.ERR_FieldInitRefNonstatic, node, member); - hasErrors = true; + diagnosticInfoOpt = new CSDiagnosticInfo(ErrorCode.ERR_FieldInitRefNonstatic, member); } else if (InConstructorInitializer || InAttributeArgument) { //can't access "this" in constructor initializers or attribute arguments - Error(diagnostics, ErrorCode.ERR_ObjectRequired, node, member); - hasErrors = true; + diagnosticInfoOpt = new CSDiagnosticInfo(ErrorCode.ERR_ObjectRequired, member); } else { @@ -2099,12 +2098,24 @@ private BoundExpression SynthesizeReceiver(SyntaxNode node, Symbol member, Bindi if (!locationIsInstanceMember) { // error CS0120: An object reference is required for the non-static field, method, or property '{0}' - Error(diagnostics, ErrorCode.ERR_ObjectRequired, node, member); - hasErrors = true; + diagnosticInfoOpt = new CSDiagnosticInfo(ErrorCode.ERR_ObjectRequired, member); } } - hasErrors = hasErrors || IsRefOrOutThisParameterCaptured(node, diagnostics); + diagnosticInfoOpt ??= GetDiagnosticIfRefOrOutThisParameterCaptured(); + hasErrors = hasErrors || diagnosticInfoOpt is not null; + + if (hasErrors) + { + if (IsInsideNameof) + { + CheckFeatureAvailability(node, MessageID.IDS_FeatureReducedMemberAccessChecksInNameof, diagnostics); + } + else + { + Error(diagnostics, diagnosticInfoOpt, node); + } + } } return ThisReference(node, currentType, hasErrors, wasCompilerGenerated: true); @@ -2276,20 +2287,35 @@ private BoundThisReference ThisReference(SyntaxNode node, NamedTypeSymbol thisTy return new BoundThisReference(node, thisTypeOpt ?? CreateErrorType(), hasErrors) { WasCompilerGenerated = wasCompilerGenerated }; } +#nullable enable private bool IsRefOrOutThisParameterCaptured(SyntaxNodeOrToken thisOrBaseToken, BindingDiagnosticBag diagnostics) { - ParameterSymbol thisSymbol = this.ContainingMemberOrLambda.EnclosingThisSymbol(); - // If there is no this parameter, then it is definitely not captured and - // any diagnostic would be cascading. - if ((object)thisSymbol != null && thisSymbol.ContainingSymbol != ContainingMemberOrLambda && thisSymbol.RefKind != RefKind.None) + if (GetDiagnosticIfRefOrOutThisParameterCaptured() is { } diagnosticInfo) { - Error(diagnostics, ErrorCode.ERR_ThisStructNotInAnonMeth, thisOrBaseToken); + var location = thisOrBaseToken.GetLocation(); + Debug.Assert(location is not null); + Error(diagnostics, diagnosticInfo, location); return true; } return false; } + private DiagnosticInfo? GetDiagnosticIfRefOrOutThisParameterCaptured() + { + Debug.Assert(this.ContainingMemberOrLambda is not null); + ParameterSymbol? thisSymbol = this.ContainingMemberOrLambda.EnclosingThisSymbol(); + // If there is no this parameter, then it is definitely not captured and + // any diagnostic would be cascading. + if (thisSymbol is not null && thisSymbol.ContainingSymbol != ContainingMemberOrLambda && thisSymbol.RefKind != RefKind.None) + { + return new CSDiagnosticInfo(ErrorCode.ERR_ThisStructNotInAnonMeth); + } + + return null; + } +#nullable disable + private BoundBaseReference BindBase(BaseExpressionSyntax node, BindingDiagnosticBag diagnostics) { bool hasErrors = false; @@ -7714,10 +7740,17 @@ private bool CheckInstanceOrStatic( { if (instanceReceiver == true) { - ErrorCode errorCode = this.Flags.Includes(BinderFlags.ObjectInitializerMember) ? - ErrorCode.ERR_StaticMemberInObjectInitializer : - ErrorCode.ERR_ObjectProhibited; - Error(diagnostics, errorCode, node, symbol); + if (!IsInsideNameof) + { + ErrorCode errorCode = this.Flags.Includes(BinderFlags.ObjectInitializerMember) ? + ErrorCode.ERR_StaticMemberInObjectInitializer : + ErrorCode.ERR_ObjectProhibited; + Error(diagnostics, errorCode, node, symbol); + } + else if (CheckFeatureAvailability(node, MessageID.IDS_FeatureReducedMemberAccessChecksInNameof, diagnostics)) + { + return false; + } resultKind = LookupResultKind.StaticInstanceMismatch; return true; } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs index 91caae3a24fa3..198cf6883b4b3 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs @@ -2686,6 +2686,11 @@ protected AssemblySymbol GetForwardedToAssembly(string name, int arity, ref Name } #nullable enable + internal static bool IsFeatureAvailable(SyntaxNode syntax, MessageID feature) + { + return ((CSharpParseOptions)syntax.SyntaxTree.Options).IsFeatureEnabled(feature); + } + internal static bool CheckFeatureAvailability(SyntaxNode syntax, MessageID feature, BindingDiagnosticBag diagnostics, Location? location = null) { return CheckFeatureAvailability(syntax, feature, diagnostics.DiagnosticBag, location); diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 17f5372130206..90ea44c7ec0fe 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -6817,6 +6817,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Parameter is unread. Did you forget to use it to initialize the property with that name? + + reduced member access checks in 'nameof' + The primary constructor conflicts with the synthesized copy constructor. diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index e55e7ad573ffb..d140243217f0b 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -265,6 +265,8 @@ internal enum MessageID IDS_FeaturePrimaryConstructors = MessageBase + 12833, IDS_FeatureUsingTypeAlias = MessageBase + 12834, + + IDS_FeatureReducedMemberAccessChecksInNameof = MessageBase + 12835, } // Message IDs may refer to strings that need to be localized. @@ -393,6 +395,7 @@ internal static LanguageVersion RequiredVersion(this MessageID feature) case MessageID.IDS_FeatureLambdaParamsArray: // semantic check case MessageID.IDS_FeaturePrimaryConstructors: // declaration table check case MessageID.IDS_FeatureUsingTypeAlias: // semantic check + case MessageID.IDS_FeatureReducedMemberAccessChecksInNameof: // semantic check return LanguageVersion.Preview; // C# 11.0 features. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf index 5d0c7b8d38c97..489db3f96d8e9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.cs.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Sestavení {0}, které obsahuje typ {1}, se odkazuje na architekturu .NET Framework, což se nepodporuje. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf index cbaf0e3d6453a..ebdb802cdfe76 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.de.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Die Assembly "{0}" mit dem Typ "{1}" verweist auf das .NET Framework. Dies wird nicht unterstützt. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf index 1ca730094499d..ad81e43ba003c 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.es.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. El ensamblado "{0}" que contiene el tipo "{1}" hace referencia a .NET Framework, lo cual no se admite. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf index adc89cef5c597..f52757076a017 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.fr.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. L'assembly '{0}' contenant le type '{1}' référence le .NET Framework, ce qui n'est pas pris en charge. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf index 55e65685f45b1..bf399fdd95902 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.it.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. L'assembly '{0}' che contiene il tipo '{1}' fa riferimento a .NET Framework, che non è supportato. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf index 28a6f3390d900..3ca67cf353ba9 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ja.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 型 '{1}' を含むアセンブリ '{0}' が .NET Framework を参照しています。これはサポートされていません。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf index f20f98eeecbb6..bff492398e779 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ko.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. '{1}' 형식을 포함하는 '{0}' 어셈블리가 지원되지 않는 .NET Framework를 참조합니다. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf index a1abd909de892..f5c2514e5689b 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pl.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Zestaw „{0}” zawierający typ „{1}” odwołuje się do platformy .NET Framework, co nie jest obsługiwane. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf index 8a6c9a7435da2..1479d7ccdc284 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.pt-BR.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. O assembly '{0}' contendo o tipo '{1}' referencia o .NET Framework, mas não há suporte para isso. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf index 31219991d28c3..02ff33415c90a 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.ru.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. Сборка "{0}", содержащая тип "{1}", ссылается на платформу .NET Framework, которая не поддерживается. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf index 3da8f1d398625..7dc9ef89be4a4 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.tr.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. '{1}' türünü içeren '{0}' bütünleştirilmiş kodu, desteklenmeyen .NET Framework'e başvuruyor. diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf index e81aad7713c4e..1dd0727aaf4fc 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hans.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 包含类型“{1}”的程序集“{0}”引用了 .NET Framework,而此操作不受支持。 diff --git a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf index f7c55165deed8..f76dbced46104 100644 --- a/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf +++ b/src/Compilers/CSharp/Portable/xlf/CSharpResources.zh-Hant.xlf @@ -2032,6 +2032,11 @@ The '&' operator should not be used on parameters or local variables in async methods. + + reduced member access checks in 'nameof' + reduced member access checks in 'nameof' + + The assembly '{0}' containing type '{1}' references .NET Framework, which is not supported. 包含類型 '{1}' 的組件 '{0}' 參考了 .NET Framework,此情形不受支援。 diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs index 4699165bab2b7..cdc6a8c6f881d 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/NameOfTests.cs @@ -1487,5 +1487,469 @@ public void nameof(string x) var option = TestOptions.ReleaseDll; CreateCompilation(source, options: option).VerifyDiagnostics(); } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceInstanceMembersFromStaticMemberInNameof_Flat() + { + var source = @" +System.Console.Write(C.M()); +public class C +{ + public object Property { get; } + public object Field; + public event System.Action Event; + public void M2() { } + public static string M() => nameof(Property) + + "","" + nameof(Field) + + "","" + nameof(Event) + + "","" + nameof(M2) + ; +}"; + var expectedOutput = "Property,Field,Event,M2"; + + CompileAndVerify(source, parseOptions: TestOptions.Regular11, expectedOutput: expectedOutput).VerifyDiagnostics(); + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: expectedOutput).VerifyDiagnostics(); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceInstanceMembersFromStaticMemberInNameof_Nested() + { + var source = @" +System.Console.Write(C.M()); +public class C +{ + public C1 Property { get; } + public C1 Field; + public event System.Action Event; + public static string M() => nameof(Property.Property) + + "","" + nameof(Property.Field) + + "","" + nameof(Property.Method) + + "","" + nameof(Property.Event) + + "","" + nameof(Field.Property) + + "","" + nameof(Field.Field) + + "","" + nameof(Field.Method) + + "","" + nameof(Field.Event) + + "","" + nameof(Event.Invoke) + ; +} + +public class C1 +{ + public int Property { get; } + public int Field; + public void Method(){} + public event System.Action Event; +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, + expectedOutput: "Property,Field,Method,Event,Property,Field,Method,Event,Invoke").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (8,40): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public static string M() => nameof(Property.Property) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Property").WithArguments("reduced member access checks in 'nameof'").WithLocation(8, 40), + // (9,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Property.Field) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Property").WithArguments("reduced member access checks in 'nameof'").WithLocation(9, 24), + // (10,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Property.Method) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Property").WithArguments("reduced member access checks in 'nameof'").WithLocation(10, 24), + // (11,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Property.Event) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Property").WithArguments("reduced member access checks in 'nameof'").WithLocation(11, 24), + // (12,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Field.Property) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("reduced member access checks in 'nameof'").WithLocation(12, 24), + // (13,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Field.Field) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("reduced member access checks in 'nameof'").WithLocation(13, 24), + // (14,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Field.Method) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("reduced member access checks in 'nameof'").WithLocation(14, 24), + // (15,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Field.Event) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Field").WithArguments("reduced member access checks in 'nameof'").WithLocation(15, 24), + // (16,24): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // + "," + nameof(Event.Invoke) + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Event").WithArguments("reduced member access checks in 'nameof'").WithLocation(16, 24)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceInstanceMembersFromFieldInitializerInNameof() + { + var source = @" +System.Console.Write(new C().S); +public class C +{ + public string S { get; } = nameof(S.Length); +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "Length").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (5,39): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public string S { get; } = nameof(S.Length); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(5, 39)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceInstanceMembersFromAttributeInNameof() + { + var source = @" +var p = new C().P; // 1 +public class C +{ + [System.Obsolete(nameof(S.Length))] + public int P { get; } + public string S { get; } +}"; + CreateCompilation(source, parseOptions: TestOptions.RegularNext).VerifyDiagnostics( + // (2,9): warning CS0618: 'C.P' is obsolete: 'Length' + // var p = new C().P; // 1 + Diagnostic(ErrorCode.WRN_DeprecatedSymbolStr, "new C().P").WithArguments("C.P", "Length").WithLocation(2, 9)); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (5,29): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // [System.Obsolete(nameof(S.Length))] + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(5, 29)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceInstanceMembersFromConstructorInitializersInNameof() + { + var source = @" +System.Console.WriteLine(new C().S); +public class C +{ + public C(string s){ S = s; } + public C() : this(nameof(S.Length)){} + public string S { get; } +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "Length").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (6,30): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public C() : this(nameof(S.Length)){} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(6, 30)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanAccessStructInstancePropertyInLambdaInNameof() + { + var source = @" +using System; + +string s = ""str""; +new S().M(ref s); + +public struct S +{ + public string P { get; } + public void M(ref string x) + { + Func func = () => nameof(P.Length); + Console.WriteLine(func()); + } +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "Length").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (12,42): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // Func func = () => nameof(P.Length); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "P").WithArguments("reduced member access checks in 'nameof'").WithLocation(12, 42)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameof1() + { + var source = @" +System.Console.WriteLine(new C().M()); +public class C +{ + public C Prop { get; } + public static int StaticProp { get; } + public string M() => nameof(Prop.StaticProp); +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "StaticProp").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (7,33): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public string M() => nameof(Prop.StaticProp); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop.StaticProp").WithArguments("reduced member access checks in 'nameof'").WithLocation(7, 33)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameof2() + { + var source = @" +System.Console.WriteLine(C.M()); +public class C +{ + public C Prop { get; } + public static int StaticProp { get; } + public static string M() => nameof(Prop.StaticProp); +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "StaticProp").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (7,40): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public static string M() => nameof(Prop.StaticProp); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("reduced member access checks in 'nameof'").WithLocation(7, 40), + // (7,40): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public static string M() => nameof(Prop.StaticProp); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop.StaticProp").WithArguments("reduced member access checks in 'nameof'").WithLocation(7, 40)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameof3() + { + var source = @" +System.Console.WriteLine(C.M()); +public class C +{ + public C Prop { get; } + public static string M() => nameof(Prop.M); +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "M").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (6,40): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public static string M() => nameof(Prop.M); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop").WithArguments("reduced member access checks in 'nameof'").WithLocation(6, 40)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameof4() + { + var source = @" +System.Console.WriteLine(new C().M()); +public class C +{ + public C Prop { get; } + public static void StaticMethod(){} + public string M() => nameof(Prop.StaticMethod); +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularNext, expectedOutput: "StaticMethod").VerifyDiagnostics(); + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics(); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCannotReferenceInstanceMembersFromStaticMemberInNameofInCSharp11() + { + var source = @" +public class C +{ + public string S { get; } + public static string M() => nameof(S.Length); +}"; + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (5,40): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public static string M() => nameof(S.Length); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(5, 40)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCannotReferenceInstanceMembersFromFieldInitializerInNameofInCSharp11() + { + var source = @" +public class C +{ + public string S { get; } = nameof(S.Length); +}"; + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (4,39): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public string S { get; } = nameof(S.Length); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(4, 39)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCannotReferenceInstanceMembersFromAttributeInNameofInCSharp11() + { + var source = @" +public class C +{ + [System.Obsolete(nameof(S.Length))] + public int P { get; } + public string S { get; } +}"; + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (4,29): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // [System.Obsolete(nameof(S.Length))] + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(4, 29)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCannotReferenceInstanceMembersFromConstructorInitializersInNameofInCSharp11() + { + var source = @" +public class C +{ + public C(string s){} + public C() : this(nameof(S.Length)){} + public string S { get; } +}"; + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (5,30): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public C() : this(nameof(S.Length)){} + Diagnostic(ErrorCode.ERR_FeatureInPreview, "S").WithArguments("reduced member access checks in 'nameof'").WithLocation(5, 30)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCannotAccessStructInstancePropertyInLambdaInNameofInCSharp11() + { + var source = @" +using System; + +public struct S +{ + public string P { get; } + public void M(ref string x) + { + Func func = () => nameof(P.Length); + } +}"; + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (9,42): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // Func func = () => nameof(P.Length); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "P").WithArguments("reduced member access checks in 'nameof'").WithLocation(9, 42)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCannotReferenceStaticPropertyFromInstanceMemberInNameofInCSharp11() + { + var source = @" +public class C +{ + public C Prop { get; } + public static int StaticProp { get; } + public string M() => nameof(Prop.StaticProp); +}"; + CreateCompilation(source, parseOptions: TestOptions.Regular11).VerifyDiagnostics( + // (6,33): error CS8652: The feature 'reduced member access checks in 'nameof'' is currently in Preview and *unsupported*. To use Preview features, use the 'preview' language version. + // public string M() => nameof(Prop.StaticProp); + Diagnostic(ErrorCode.ERR_FeatureInPreview, "Prop.StaticProp").WithArguments("reduced member access checks in 'nameof'").WithLocation(6, 33)); + } + + [Fact] + public void TestCanReferenceStaticMethodFromInstanceMemberInNameofInCSharp11() + { + var source = @" +System.Console.WriteLine(new C().M()); +public class C +{ + public C Prop { get; } + public static void StaticMethod(){} + public string M() => nameof(Prop.StaticMethod); +}"; + CompileAndVerify(source, parseOptions: TestOptions.Regular11, expectedOutput: "StaticMethod").VerifyDiagnostics(); + } + + [Fact] + public void TestCanAccessRefParameterInLambdaInNameof() + { + var source = @" +using System; + +string s = ""str""; +new S().M(ref s); + +public struct S +{ + public void M(ref string x) + { + Func func = () => nameof(x.Length); + Console.WriteLine(func()); + } +}"; + CompileAndVerify(source, expectedOutput: "Length").VerifyDiagnostics(); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameofUsedRecursivelyInAttributes1() + { + var source = @" +using System; +using System.Reflection; +Console.WriteLine(typeof(C).GetProperty(""Prop"").GetCustomAttribute().S); +class C +{ + [Attr(nameof(Prop.StaticMethod))] + public C Prop { get; } + public static void StaticMethod(){} +} +class Attr : Attribute +{ + public readonly string S; + public Attr(string s) { S = s; } +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "StaticMethod") + .VerifyDiagnostics(); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameofUsedRecursivelyInAttributes2() + { + var source = @" +using System; +using System.Reflection; +Console.WriteLine(typeof(C).GetProperty(""Prop"").GetCustomAttribute().S); +class C +{ + [Attr(nameof(Prop.Prop))] + public static C Prop { get; } +} +class Attr : Attribute +{ + public readonly string S; + public Attr(string s) { S = s; } +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Prop") + .VerifyDiagnostics(); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestCanReferenceStaticMembersFromInstanceMemberInNameofUsedRecursivelyInAttributes3() + { + var source = @" +using System; +using System.Reflection; +Console.WriteLine(typeof(C).GetCustomAttribute().S); +[Attr(nameof(C.Prop.Prop))] +class C +{ + public static C Prop { get; } +} +class Attr : Attribute +{ + public readonly string S; + public Attr(string s) { S = s; } +}"; + CompileAndVerify(source, parseOptions: TestOptions.RegularPreview, expectedOutput: "Prop") + .VerifyDiagnostics(); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler1() + { + var source = @" +class C +{ + [Attr(nameof(Method().Method))] + T Method() where T : C => default; +} +class Attr : System.Attribute { public Attr(string s) {} }"; + CreateCompilation(source, parseOptions: TestOptions.RegularPreview) + .VerifyDiagnostics( + // (4,18): error CS0411: The type arguments for method 'C.Method()' cannot be inferred from the usage. Try specifying the type arguments explicitly. + // [Attr(nameof(Method().Method))] + Diagnostic(ErrorCode.ERR_CantInferMethTypeArgs, "Method").WithArguments("C.Method()").WithLocation(4, 18)); + } + + [Fact, WorkItem(40229, "https://github.com/dotnet/roslyn/issues/40229")] + public void TestInvalidRecursiveUsageOfNameofInAttributesDoesNotCrashCompiler2() + { + var source = @" +class C +{ + [Attr(nameof(Method().Method))] + T Method() where T : C => default; +} +class Attr : System.Attribute { public Attr(string s) {} }"; + CreateCompilation(source, parseOptions: TestOptions.RegularPreview) + .VerifyDiagnostics( + // (4,18): error CS8082: Sub-expression cannot be used in an argument to nameof. + // [Attr(nameof(Method().Method))] + Diagnostic(ErrorCode.ERR_SubexpressionNotInNameof, "Method()").WithLocation(4, 18)); + } } } diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/StaticAbstractMembersInInterfacesTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/StaticAbstractMembersInInterfacesTests.cs index f35bd414f7716..fe6c672902c0a 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/StaticAbstractMembersInInterfacesTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/StaticAbstractMembersInInterfacesTests.cs @@ -13102,18 +13102,6 @@ static void MT2() where T : I1 targetFramework: _supportingFramework); compilation1.VerifyDiagnostics( - // (14,20): error CS0176: Member 'I1.P01' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(this.P01); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "this.P01").WithArguments("I1.P01").WithLocation(14, 20), - // (15,20): error CS0176: Member 'I1.P04' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(this.P04); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "this.P04").WithArguments("I1.P04").WithLocation(15, 20), - // (28,20): error CS0176: Member 'I1.P01' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(x.P01); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "x.P01").WithArguments("I1.P01").WithLocation(28, 20), - // (30,20): error CS0176: Member 'I1.P04' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(x.P04); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "x.P04").WithArguments("I1.P04").WithLocation(30, 20), // (35,20): error CS0704: Cannot do non-virtual member lookup in 'T' because it is a type parameter // _ = nameof(T.P03); Diagnostic(ErrorCode.ERR_LookupInTypeVariable, "T").WithArguments("T").WithLocation(35, 20), @@ -13984,18 +13972,6 @@ static void MT2() where T : I1 targetFramework: _supportingFramework); compilation1.VerifyDiagnostics( - // (14,20): error CS0176: Member 'I1.P01' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(this.P01); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "this.P01").WithArguments("I1.P01").WithLocation(14, 20), - // (15,20): error CS0176: Member 'I1.P04' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(this.P04); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "this.P04").WithArguments("I1.P04").WithLocation(15, 20), - // (28,20): error CS0176: Member 'I1.P01' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(x.P01); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "x.P01").WithArguments("I1.P01").WithLocation(28, 20), - // (30,20): error CS0176: Member 'I1.P04' cannot be accessed with an instance reference; qualify it with a type name instead - // _ = nameof(x.P04); - Diagnostic(ErrorCode.ERR_ObjectProhibited, "x.P04").WithArguments("I1.P04").WithLocation(30, 20), // (35,20): error CS0704: Cannot do non-virtual member lookup in 'T' because it is a type parameter // _ = nameof(T.P03); Diagnostic(ErrorCode.ERR_LookupInTypeVariable, "T").WithArguments("T").WithLocation(35, 20),