diff --git a/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs b/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs index 2715fc9adefe4..1aaa9522d014d 100644 --- a/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs +++ b/src/Compilers/CSharp/Portable/Binder/Semantics/AccessCheck.cs @@ -327,8 +327,9 @@ private static bool IsMemberAccessible( return true; } + // For the purpose of accessibility checks, extension members are considered to be declared within the enclosing static type return IsNonPublicMemberAccessible( - containingType, + containingType.IsExtension && containingType.ContainingType is { } extensionEnclosingType ? extensionEnclosingType : containingType, declaredAccessibility, within, throughTypeOpt, diff --git a/src/Compilers/CSharp/Portable/Emitter/Model/NamedTypeSymbolAdapter.cs b/src/Compilers/CSharp/Portable/Emitter/Model/NamedTypeSymbolAdapter.cs index 1f32832dc8550..bd97882f387d8 100644 --- a/src/Compilers/CSharp/Portable/Emitter/Model/NamedTypeSymbolAdapter.cs +++ b/src/Compilers/CSharp/Portable/Emitter/Model/NamedTypeSymbolAdapter.cs @@ -628,7 +628,7 @@ bool Cci.ITypeDefinition.IsSealed { Debug.Assert((object)method != null); - if ((alwaysIncludeConstructors && method.MethodKind == MethodKind.Constructor) || method.GetCciAdapter().ShouldInclude(context)) + if ((alwaysIncludeConstructors && method.MethodKind == MethodKind.Constructor) || method is SynthesizedExtensionMarker || method.GetCciAdapter().ShouldInclude(context)) { yield return method.GetCciAdapter(); } diff --git a/src/Compilers/CSharp/Portable/Symbols/Extensions/SynthesizedExtensionMarker.cs b/src/Compilers/CSharp/Portable/Symbols/Extensions/SynthesizedExtensionMarker.cs index 7a9bc4c1208d4..c2059bcb75e51 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Extensions/SynthesizedExtensionMarker.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Extensions/SynthesizedExtensionMarker.cs @@ -30,7 +30,7 @@ internal SynthesizedExtensionMarker(SourceMemberContainerTypeSymbol extensionTyp return; } - private static DeclarationModifiers GetDeclarationModifiers() => DeclarationModifiers.Public | DeclarationModifiers.Static; + private static DeclarationModifiers GetDeclarationModifiers() => DeclarationModifiers.Private | DeclarationModifiers.Static; internal override bool HasSpecialName => true; // PROTOTYPE: reconcile with spec diff --git a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs index f6af1f1f07439..7df2e04b24557 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Metadata/PE/PENamedTypeSymbol.cs @@ -407,7 +407,7 @@ internal sealed override ParameterSymbol? ExtensionParameter var methodSymbol = getMarkerMethodSymbol(@this, uncommon); // PROTOTYPE: do we want to tighten the flags check further? (require that type be sealed?) - if (methodSymbol.DeclaredAccessibility != Accessibility.Public || + if (methodSymbol.DeclaredAccessibility != Accessibility.Private || methodSymbol.IsGenericMethod || !methodSymbol.IsStatic || !methodSymbol.ReturnsVoid || @@ -2238,11 +2238,15 @@ private PooledDictionary CreateMethods(A // for ordinary embeddable struct types we import private members so that we can report appropriate errors if the structure is used var isOrdinaryEmbeddableStruct = (this.TypeKind == TypeKind.Struct) && (this.SpecialType == Microsoft.CodeAnalysis.SpecialType.None) && this.ContainingAssembly.IsLinked; + MethodDefinitionHandle? extensionMarkerMethod = _lazyUncommonProperties?.lazyExtensionInfo?.MarkerMethod; + Debug.Assert(extensionMarkerMethod is not null || this.TypeKind is not TypeKind.Extension); + try { foreach (var methodHandle in module.GetMethodsOfTypeOrThrow(_handle)) { - if (isOrdinaryEmbeddableStruct || module.ShouldImportMethod(_handle, methodHandle, moduleSymbol.ImportOptions)) + if (isOrdinaryEmbeddableStruct || module.ShouldImportMethod(_handle, methodHandle, moduleSymbol.ImportOptions) || + extensionMarkerMethod == methodHandle) { var method = new PEMethodSymbol(moduleSymbol, this, methodHandle); members.Add(method); diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs index 3d1f5222bb0d5..94ffe236219c3 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourceMemberMethodSymbol.cs @@ -378,26 +378,42 @@ protected void CheckEffectiveAccessibility(TypeWithAnnotations returnType, Immut } } + if (!IsStatic && this.GetIsNewExtensionMember() && ContainingType.ExtensionParameter is { } extensionParameter) + { + if (!extensionParameter.TypeWithAnnotations.IsAtLeastAsVisibleAs(this, ref useSiteInfo)) + { + // Inconsistent accessibility: parameter type '{1}' is less accessible than method '{0}' + diagnostics.Add(code, GetFirstLocation(), this, extensionParameter.Type); + } + } + diagnostics.Add(GetFirstLocation(), useSiteInfo); } protected void CheckFileTypeUsage(TypeWithAnnotations returnType, ImmutableArray parameters, BindingDiagnosticBag diagnostics) { - if (ContainingType.HasFileLocalTypes()) + NamedTypeSymbol containingType = ContainingType; + + if (containingType is { IsExtension: true, ContainingType: { } enclosing }) + { + containingType = enclosing; + } + + if (containingType.HasFileLocalTypes()) { return; } if (returnType.Type.HasFileLocalTypes()) { - diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, GetFirstLocation(), returnType.Type, ContainingType); + diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, GetFirstLocation(), returnType.Type, containingType); } foreach (var param in parameters) { if (param.Type.HasFileLocalTypes()) { - diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, GetFirstLocation(), param.Type, ContainingType); + diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, GetFirstLocation(), param.Type, containingType); } } } diff --git a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs index e1e1f06323023..b7d5c4b4d4742 100644 --- a/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs +++ b/src/Compilers/CSharp/Portable/Symbols/Source/SourcePropertySymbol.cs @@ -576,9 +576,18 @@ private TypeWithAnnotations ComputeType(Binder binder, SyntaxNode syntax, Bindin diagnostics.Add((this.IsIndexer ? ErrorCode.ERR_BadVisIndexerReturn : ErrorCode.ERR_BadVisPropertyType), Location, this, type.Type); } - if (type.Type.HasFileLocalTypes() && !ContainingType.HasFileLocalTypes()) + if (type.Type.HasFileLocalTypes()) { - diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, Location, type.Type, ContainingType); + NamedTypeSymbol containingType = ContainingType; + if (containingType is { IsExtension: true, ContainingType: { } enclosing }) + { + containingType = enclosing; + } + + if (!containingType.HasFileLocalTypes()) + { + diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, Location, type.Type, containingType); + } } diagnostics.Add(Location, useSiteInfo); @@ -652,15 +661,21 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, var useSiteInfo = new CompoundUseSiteInfo(diagnostics, ContainingAssembly); + var containingTypeForFileTypeCheck = this.ContainingType; + if (containingTypeForFileTypeCheck is { IsExtension: true, ContainingType: { } enclosing }) + { + containingTypeForFileTypeCheck = enclosing; + } + foreach (ParameterSymbol param in Parameters) { if (!IsExplicitInterfaceImplementation && !this.IsNoMoreVisibleThan(param.Type, ref useSiteInfo)) { diagnostics.Add(ErrorCode.ERR_BadVisIndexerParam, Location, this, param.Type); } - else if (param.Type.HasFileLocalTypes() && !this.ContainingType.HasFileLocalTypes()) + else if (param.Type.HasFileLocalTypes() && !containingTypeForFileTypeCheck.HasFileLocalTypes()) { - diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, Location, param.Type, this.ContainingType); + diagnostics.Add(ErrorCode.ERR_FileTypeDisallowedInSignature, Location, param.Type, containingTypeForFileTypeCheck); } else if (SetMethod is object && param.Name == ParameterSymbol.ValueParameterName) { @@ -668,6 +683,12 @@ internal override void AfterAddingTypeMembersChecks(ConversionsBase conversions, } } + if (!IsStatic && this.GetIsNewExtensionMember() && ContainingType.ExtensionParameter is { } extensionParameter && + !this.IsNoMoreVisibleThan(extensionParameter.Type, ref useSiteInfo)) + { + diagnostics.Add(ErrorCode.ERR_BadVisIndexerParam, Location, this, extensionParameter.Type); + } + diagnostics.Add(Location, useSiteInfo); if (IsPartialDefinition && OtherPartOfPartial is { } implementation) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs index 69ca80d39ad8a..5b56f0b5058f6 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/ExtensionTests.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.VisualBasic; using Roslyn.Test.Utilities; @@ -114,7 +115,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -204,7 +205,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -284,7 +285,7 @@ 01 00 00 00 extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -531,7 +532,7 @@ extends [netstandard]System.Object 01 00 01 00 00 ) // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -775,7 +776,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -1077,7 +1078,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -1183,7 +1184,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -1300,7 +1301,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -1469,7 +1470,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [netstandard]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -1608,7 +1609,7 @@ extends [netstandard]System.Object 01 00 04 49 74 65 6d 00 00 ) // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -3179,6 +3180,16 @@ public static class Extensions extension(C x) { public void M() {} + public int P { get => 0; set {}} + public int this[int i] { get => 0; set {}} + + private void M1() {} + private int P1 { get => 0; set {}} + private int this[long i] { get => 0; set {}} + + internal void M2() {} + internal int P2 { get => 0; set {}} + internal int this[byte i] { get => 0; set {}} } } @@ -3187,9 +3198,17 @@ class C {} var comp = CreateCompilation(src); comp.VerifyDiagnostics( - // (3,14): error CS0051: Inconsistent accessibility: parameter type 'C' is less accessible than method 'Extensions.extension(C).$(C)' - // extension(C x) - Diagnostic(ErrorCode.ERR_BadVisParamType, "(").WithArguments("Extensions.extension(C).$(C)", "C").WithLocation(3, 14) + // (5,21): error CS0051: Inconsistent accessibility: parameter type 'C' is less accessible than method 'Extensions.extension(C).M()' + // public void M() {} + Diagnostic(ErrorCode.ERR_BadVisParamType, "M").WithArguments("Extensions.extension(C).M()", "C").WithLocation(5, 21), + + // PROTOTYPE: Error wording, this isn't an indexer + // (6,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer 'Extensions.extension(C).P' + // public int P { get => 0; set {}} + Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P").WithArguments("Extensions.extension(C).P", "C").WithLocation(6, 20), + // (7,20): error CS0055: Inconsistent accessibility: parameter type 'C' is less accessible than indexer 'Extensions.extension(C).this[int]' + // public int this[int i] { get => 0; set {}} + Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(C).this[int]", "C").WithLocation(7, 20) ); } @@ -3208,14 +3227,253 @@ private class C {} """; var comp = CreateCompilation(src); - // PROTOTYPE: It looks like there is no way to extend private type. It is possible to do with legacy extensions. + CompileAndVerify(comp).VerifyDiagnostics(); + } + + [Fact] + public void ReceiverParameter_InconsistentTypeAccessibility_03() + { + var src = """ +public static class Extensions +{ + extension(C x) + { + public void M() {} + public int P { get => 0; set {}} + public int this[int i] { get => 0; set {}} + + private void M1() {} + private int P1 { get => 0; set {}} + private int this[long i] { get => 0; set {}} + + internal void M2() {} + internal int P2 { get => 0; set {}} + internal int this[byte i] { get => 0; set {}} + } + + private class C {} +} +"""; + var comp = CreateCompilation(src); + comp.VerifyDiagnostics( - // (3,14): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(Extensions.C).$(Extensions.C)' + // (5,21): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(Extensions.C).M()' + // public void M() {} + Diagnostic(ErrorCode.ERR_BadVisParamType, "M").WithArguments("Extensions.extension(Extensions.C).M()", "Extensions.C").WithLocation(5, 21), + + // PROTOTYPE: Error wording, this isn't an indexer + + // (6,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).P' + // public int P { get => 0; set {}} + Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P").WithArguments("Extensions.extension(Extensions.C).P", "Extensions.C").WithLocation(6, 20), + // (7,20): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).this[int]' + // public int this[int i] { get => 0; set {}} + Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(Extensions.C).this[int]", "Extensions.C").WithLocation(7, 20), + // (13,23): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(Extensions.C).M2()' + // internal void M2() {} + Diagnostic(ErrorCode.ERR_BadVisParamType, "M2").WithArguments("Extensions.extension(Extensions.C).M2()", "Extensions.C").WithLocation(13, 23), + // (14,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).P2' + // internal int P2 { get => 0; set {}} + Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "P2").WithArguments("Extensions.extension(Extensions.C).P2", "Extensions.C").WithLocation(14, 22), + // (15,22): error CS0055: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than indexer 'Extensions.extension(Extensions.C).this[byte]' + // internal int this[byte i] { get => 0; set {}} + Diagnostic(ErrorCode.ERR_BadVisIndexerParam, "this").WithArguments("Extensions.extension(Extensions.C).this[byte]", "Extensions.C").WithLocation(15, 22) + ); + } + + [Fact] + public void InconsistentTypeAccessibility_01() + { + var src = """ +public static class Extensions +{ + extension(int x) + { + public void M1(C c) {} + private void M2(C c) {} + } + + extension(long x) + { + public static void M3(int x) + { + x.M2(new C()); + } + } + + public static void M4(int x) + { + x.M2(new C()); + } + + private class C {} +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyDiagnostics( + // (5,21): error CS0051: Inconsistent accessibility: parameter type 'Extensions.C' is less accessible than method 'Extensions.extension(int).M1(Extensions.C)' + // public void M1(C c) {} + Diagnostic(ErrorCode.ERR_BadVisParamType, "M1").WithArguments("Extensions.extension(int).M1(Extensions.C)", "Extensions.C").WithLocation(5, 21) + ); + } + + [Fact] + public void InconsistentTypeAccessibility_02() + { + var src = """ +public static class Extensions +{ + extension(int x) + { + public C M1 => null; + private C M2 => null; + } + + extension(long x) + { + public static void M3(int x) + { + _ = x.M2; + } + } + + public static void M4(int x) + { + _ = x.M2; + } + + private class C {} +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyDiagnostics( + // (5,18): error CS0053: Inconsistent accessibility: property type 'Extensions.C' is less accessible than property 'Extensions.extension(int).M1' + // public C M1 => null; + Diagnostic(ErrorCode.ERR_BadVisPropertyType, "M1").WithArguments("Extensions.extension(int).M1", "Extensions.C").WithLocation(5, 18) + ); + } + + [Fact] + public void Inaccessible_01() + { + var src = """ +static class Extensions +{ + extension(int x) + { + private void M2() {} + } + + private static void M3(this int x) {} +} + +class C +{ + void Test(int x) + { + x.M2(); + x.M3(); + Extensions.M2(x); + Extensions.M3(x); + } +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyDiagnostics( + // (15,11): error CS1061: 'int' does not contain a definition for 'M2' and no accessible extension method 'M2' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) + // x.M2(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M2").WithArguments("int", "M2").WithLocation(15, 11), + // (16,11): error CS1061: 'int' does not contain a definition for 'M3' and no accessible extension method 'M3' accepting a first argument of type 'int' could be found (are you missing a using directive or an assembly reference?) + // x.M3(); + Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "M3").WithArguments("int", "M3").WithLocation(16, 11), + // (17,20): error CS0122: 'Extensions.M2(int)' is inaccessible due to its protection level + // Extensions.M2(x); + Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("Extensions.M2(int)").WithLocation(17, 20), + // (18,20): error CS0122: 'Extensions.M3(int)' is inaccessible due to its protection level + // Extensions.M3(x); + Diagnostic(ErrorCode.ERR_BadAccess, "M3").WithArguments("Extensions.M3(int)").WithLocation(18, 20) + ); + } + + [Fact] + public void ReceiverParameter_FileType_01() + { + var src = """ +file class C {} + +static class Extensions +{ + extension(C x) + { + } + + private static void M3(this C x) {} +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyDiagnostics( + // (5,14): error CS9051: File-local type 'C' cannot be used in a member signature in non-file-local type 'Extensions'. // extension(C x) - Diagnostic(ErrorCode.ERR_BadVisParamType, "(").WithArguments("Extensions.extension(Extensions.C).$(Extensions.C)", "Extensions.C").WithLocation(3, 14) + Diagnostic(ErrorCode.ERR_FileTypeDisallowedInSignature, "(").WithArguments("C", "Extensions").WithLocation(5, 14), + // (9,25): error CS9051: File-local type 'C' cannot be used in a member signature in non-file-local type 'Extensions'. + // private static void M3(this C x) {} + Diagnostic(ErrorCode.ERR_FileTypeDisallowedInSignature, "M3").WithArguments("C", "Extensions").WithLocation(9, 25) ); } + [Fact] + public void ReceiverParameter_FileType_02() + { + var src = """ +file class C {} + +file static class Extensions +{ + extension(C x) + { + public void M1() {} + public int P => 0; + public int this[int i] => 0; + } + + public static void M2(this C x) {} + + private static void M3(this C x) {} +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyEmitDiagnostics(); + } + + [Fact] + public void FileType_01() + { + var src = """ +file class C {} + +file static class Extensions +{ + extension(int x) + { + public void M1(C c) {} + public C P => null; + public C this[int x] => null; + public int this[C x] => 0; + } + + public static void M2(this int x, C c) {} +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyEmitDiagnostics(); + } + [Fact] public void ReceiverParameter_PointerType() { @@ -3550,7 +3808,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -3598,6 +3856,15 @@ .maxstack 8 } // end of method Extensions::M } // end of class Extensions """.Replace("[mscorlib]", ExecutionConditionUtil.IsMonoOrCoreClr ? "[netstandard]" : "[mscorlib]")); + + CompileAndVerify( + comp, + emitOptions: EmitOptions.Default.WithEmitMetadataOnly(true).WithIncludePrivateMembers(false), + symbolValidator: (m) => + { + AssertEx.Equal("void Extensions.<>E__0.$(System.Object o)", m.GlobalNamespace.GetMember("Extensions.<>E__0.$").ToTestDisplayString()); + } + ).VerifyDiagnostics(); } [Fact] @@ -3660,7 +3927,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -4029,7 +4296,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -4209,7 +4476,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -4397,7 +4664,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -4798,7 +5065,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -5098,7 +5365,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o ) cil managed @@ -5339,7 +5606,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o ) cil managed @@ -5614,7 +5881,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o ) cil managed @@ -5873,7 +6140,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o ) cil managed @@ -6262,7 +6529,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( class C`1 o ) cil managed @@ -6579,7 +6846,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ ) cil managed @@ -7060,7 +7327,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ ) cil managed @@ -7238,7 +7505,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ ) cil managed @@ -7424,7 +7691,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ ) cil managed @@ -7789,7 +8056,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object _ ) cil managed @@ -8079,7 +8346,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -8368,7 +8635,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object '' ) cil managed @@ -8579,7 +8846,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -8725,7 +8992,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o ) cil managed @@ -8869,7 +9136,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o ) cil managed @@ -9014,7 +9281,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -9154,7 +9421,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o ) cil managed @@ -9296,7 +9563,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -9437,7 +9704,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o ) cil managed @@ -9616,7 +9883,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0`1' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( !T o ) cil managed @@ -9779,7 +10046,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends [mscorlib]System.Object { // Methods - .method public hidebysig specialname static + .method private hidebysig specialname static void '$' ( object o ) cil managed @@ -21672,6 +21939,94 @@ static class Extensions ); } + [Fact] + public void SignatureConflict_18() + { + var src = """ +public static class Extensions +{ + extension(object receiver) + { + static public void M1(int x) {} + } + + public static int M1 => 4; + + extension(object receiver) + { + static public void M2(int x) {} + } + + public static int M2 = 4; + + extension(object receiver) + { + static public void M3(int x) {} + } + +#pragma warning disable CS0067 // The event 'Extensions.M3' is never used + public static event System.Action M3; +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyDiagnostics( + // (5,28): error CS0102: The type 'Extensions' already contains a definition for 'M1' + // static public void M1(int x) {} + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M1").WithArguments("Extensions", "M1").WithLocation(5, 28), + // (12,28): error CS0102: The type 'Extensions' already contains a definition for 'M2' + // static public void M2(int x) {} + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M2").WithArguments("Extensions", "M2").WithLocation(12, 28), + // (19,28): error CS0102: The type 'Extensions' already contains a definition for 'M3' + // static public void M3(int x) {} + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M3").WithArguments("Extensions", "M3").WithLocation(19, 28) + ); + } + + [Fact] + public void SignatureConflict_19() + { + var src = """ +public static class Extensions +{ + public static int M1 => 4; + + extension(object receiver) + { + static public void M1(int x) {} + } + + public static int M2 = 4; + + extension(object receiver) + { + static public void M2(int x) {} + } + +#pragma warning disable CS0067 // The event 'Extensions.M3' is never used + public static event System.Action M3; + + extension(object receiver) + { + static public void M3(int x) {} + } +} +"""; + var comp = CreateCompilation(src); + + comp.VerifyDiagnostics( + // (7,28): error CS0102: The type 'Extensions' already contains a definition for 'M1' + // static public void M1(int x) {} + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M1").WithArguments("Extensions", "M1").WithLocation(7, 28), + // (14,28): error CS0102: The type 'Extensions' already contains a definition for 'M2' + // static public void M2(int x) {} + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M2").WithArguments("Extensions", "M2").WithLocation(14, 28), + // (22,28): error CS0102: The type 'Extensions' already contains a definition for 'M3' + // static public void M3(int x) {} + Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M3").WithArguments("Extensions", "M3").WithLocation(22, 28) + ); + } + [Fact] public void MethodInvocation_01() { @@ -24303,7 +24658,7 @@ .class nested public auto ansi sealed beforefieldinit '<>E__0' extends System.Object { // Methods - .method public hidebysig specialname static void '$' ( int32[] i ) cil managed + .method private hidebysig specialname static void '$' ( int32[] i ) cil managed { .param [1] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00) @@ -24373,7 +24728,7 @@ 01 00 00 00 .class nested public auto ansi sealed beforefieldinit '<>E__0' extends System.Object { - .method public hidebysig specialname static void '$' ( int32[] i ) cil managed + .method private hidebysig specialname static void '$' ( int32[] i ) cil managed { .param [1] .custom instance void [mscorlib]System.ParamArrayAttribute::.ctor() = ( 01 00 00 00)