/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Test/Symbol/Symbols/DefaultInterfaceImplementationTests.cs
70 244 строки
3 MB
Fred Silberberg
Add C# 15 language version (#84799)
11 авг 2026, 23:51
Не верифицирован
11 авг 2026, 23:51
1284a4a
Код
Авторство
О чём код?
// 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. #nullable disable using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Basic.Reference.Assemblies; using Microsoft.CodeAnalysis.CSharp.Symbols; using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols { [CompilerTrait(CompilerFeature.DefaultInterfaceImplementation)] public class DefaultInterfaceImplementationTests : CSharpTestBase { private sealed class CSharp13_CSharp14_Preview() : CombinatorialValuesAttribute(LanguageVersion.CSharp13, LanguageVersion.CSharp14, LanguageVersion.Preview); [Theory] [CombinatorialData] [WorkItem(33083, "https://github.com/dotnet/roslyn/issues/33083")] public void MethodImplementation_011(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + modifiers + @"void M1() { System.Console.WriteLine(""M1""); } } "; ValidateMethodImplementation_011(source1, isStatic); } private static Verification VerifyOnMonoOrCoreClr { get { return ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.Passes : Verification.Skipped; } } private static Verification Verify(bool isStatic) { // IL Verify complains about static constrained calls: "Missing callvirt following constrained prefix." return isStatic ? Verification.Skipped : VerifyOnMonoOrCoreClr; } private static bool Execute(bool isStatic, bool haveImplementationInDerivedInterface = false, bool hasImplementationOfVirtualInDerivedType = false) { return ExecutionConditionUtil.IsMonoOrCoreClr; } private static Verification VerifyOnMonoOrCoreClr_FailsIlVerify { get { return ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.FailsILVerify : Verification.Skipped; } } private static Verification VerifyFailsIlVerify(bool isStatic) { return !isStatic && ExecutionConditionUtil.IsMonoOrCoreClr ? Verification.FailsILVerify : Verification.Skipped; } private void ValidateMethodImplementation_011(string source, bool isStatic = false) { foreach (string access in new[] { "x.M1();", "new System.Action(x.M1)();" }) { foreach (string typeKind in new[] { "class", "struct" }) { string source1; if (!isStatic) { source1 = typeKind + " Test1 " + @": I1 { static void Main() { I1 x = new Test1(); " + access + @" } } "; } else { source1 = typeKind + " Test1 " + @": I1 { static void Main() { Test<Test1>(); } #pragma warning disable CS8981 // The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. static void Test<x>() where x : I1 { " + access + @" } } "; } source1 = source + source1; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, targetFramework: TargetFramework.Net60, parseOptions: TestOptions.RegularPreview); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { ValidateMethodImplementationTest1_011(m, "void I1.M1()", isStatic); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: Validate1); string source2; if (!isStatic) { source2 = typeKind + " Test2 " + @": I1 { static void Main() { I1 x = new Test2(); " + access + @" } } "; } else { source2 = typeKind + " Test2 " + @": I1 { static void Main() { Test<Test2>(); } #pragma warning disable CS8981 // The type name 'x' only contains lower-cased ascii characters. Such names may become reserved for the language. static void Test<x>() where x : I1 { " + access + @" } } "; } foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate2(ModuleSymbol m) { ValidateMethodImplementationTest2_011(m, "void I1.M1()"); } Validate2(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: Validate2); } } } } private static void ValidateMethodImplementationTest1_011(ModuleSymbol m, string expectedImplementation, bool isStatic, string methodName = null) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.Name); var m1 = i1.GetMembers().OfType<MethodSymbol>().Where(m => methodName is null ? true : m.Name == methodName).Single(); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.False(m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); if (m is PEModuleSymbol peModule) { int rva; peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)m1.OriginalDefinition).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } Assert.Equal(expectedImplementation, test1.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); Assert.Same(m1, i1.FindImplementationForInterfaceMember(m1)); } private static void ValidateMethodImplementationTest2_011(ModuleSymbol m, string expectedImplementation, string methodName = null) { var test2 = m.GlobalNamespace.GetTypeMember("Test2"); var i1 = test2.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.Name); var m1 = i1.GetMember<MethodSymbol>(methodName ?? "M1"); Assert.Equal(expectedImplementation, test2.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); Assert.Same(m1, i1.FindImplementationForInterfaceMember(m1)); } [Theory] [CombinatorialData] public void MethodImplementation_012(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test1 M1""); } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { ValidateMethodImplementationTest1_011(m, "void Test1.M1()", isStatic); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? "Test1 M1" : null, verify: Verify(isStatic), symbolValidator: Validate1); var source2 = @" class Test2 : I1 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test2 M1""); } "; if (!isStatic) { source2 += @" static void Main() { I1 x = new Test2(); x.M1(); } "; } else { source2 += @" static void Main() { Test<Test2>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source2 += @" } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate2(ModuleSymbol m) { ValidateMethodImplementationTest2_011(m, "void Test2.M1()"); } Validate2(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: Execute(isStatic) ? "Test2 M1" : null, verify: Verify(isStatic), symbolValidator: Validate2); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate2(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: Execute(isStatic) ? "Test2 M1" : null, verify: Verify(isStatic), symbolValidator: Validate2); } [Theory] [CombinatorialData] public void MethodImplementation_013(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test1 M1""); } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { ValidateMethodImplementationTest1_011(m, "void Test1.I1.M1()", isStatic); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? "Test1 M1" : null, verify: Verify(isStatic), symbolValidator: Validate1); var source2 = @" class Test2 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test2 M1""); } "; if (!isStatic) { source2 += @" static void Main() { I1 x = new Test2(); x.M1(); } "; } else { source2 += @" static void Main() { Test<Test2>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source2 += @" } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate2(ModuleSymbol m) { ValidateMethodImplementationTest2_011(m, "void Test2.I1.M1()"); } Validate2(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: Execute(isStatic) ? "Test2 M1" : null, verify: Verify(isStatic), symbolValidator: Validate2); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate2(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: Execute(isStatic) ? "Test2 M1" : null, verify: Verify(isStatic), symbolValidator: Validate2); } [Theory] [CombinatorialData] public void MethodImplementation_021(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } " + declModifiers + @"void M2() { System.Console.WriteLine(""M2""); } } class Base { " + implModifiers + @"void M1() { } } class Derived : Base, I1 { " + implModifiers + @"void M2() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Derived(); x.M1(); x.M2(); } "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<T>() where T : I1 { T.M1(); T.M2(); } "; } source1 += @" } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var m1 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M1"); var m2 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M2"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Same(m1, derived.FindImplementationForInterfaceMember(m1)); Assert.Same(m2, derived.FindImplementationForInterfaceMember(m2)); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"M1 M2", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void MethodImplementation_022(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } " + declModifiers + @"void M2() { System.Console.WriteLine(""M2""); } } class Base : Test { " + implModifiers + @"void M1() { } } class Derived : Base, I1 { " + implModifiers + @"void M2() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Derived(); x.M1(); x.M2(); } "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<T>() where T : I1 { T.M1(); T.M2(); } "; } source1 += @" } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var m1 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M1"); var m2 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M2"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Same(m1, derived.FindImplementationForInterfaceMember(m1)); Assert.Same(m2, derived.FindImplementationForInterfaceMember(m2)); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"M1 M2", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void MethodImplementation_023(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() {} " + declModifiers + @"void M2() {} } class Base : Test { " + implModifiers + @"void M1() { } } class Derived : Base, I1 { " + implModifiers + @"void M2() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Derived(); x.M1(); x.M2(); } "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<T>() where T : I1 { T.M1(); T.M2(); } "; } source1 += @" } class Test : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test.M1""); } " + implModifiers + @"void I1.M2() { System.Console.WriteLine(""Test.M2""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var m1 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M1"); var m2 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M2"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("void Test.I1.M1()", derived.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); Assert.Equal("void Test.I1.M2()", derived.FindImplementationForInterfaceMember(m2).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"Test.M1 Test.M2", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void MethodImplementation_024(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() {} " + declModifiers + @"void M2() {} } class Base : Test { new " + implModifiers + @"void M1() { } } class Derived : Base, I1 { new " + implModifiers + @"void M2() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Derived(); x.M1(); x.M2(); } "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<T>() where T : I1 { T.M1(); T.M2(); } "; } source1 += @" } class Test : I1 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test.M1""); } " + implModifiers + @"public void M2() { System.Console.WriteLine(""Test.M2""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var m1 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M1"); var m2 = m.GlobalNamespace.GetMember<MethodSymbol>("I1.M2"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("void Test.M1()", derived.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); Assert.Equal("void Test.M2()", derived.FindImplementationForInterfaceMember(m2).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"Test.M1 Test.M2", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void MethodImplementation_031(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = !isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 { public " + implModifiers + @" void M1() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_032(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = !isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : Test2, I1 { public " + implModifiers + @" void M1() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_033(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; string notImplModifiers = !isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } } class Test1 : Test2, I1 { public " + notImplModifiers + @" void M1() { } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } class Test2 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test2.M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Equal("void Test2.I1.M1()", test1.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? "Test2.M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_034(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; string notImplModifiers = !isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } } class Test1 : Test2, I1 { new public " + notImplModifiers + @" void M1() { System.Console.WriteLine(""Test1.M1""); } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } class Test2 : I1 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test2.M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Equal("void Test2.M1()", test1.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? "Test2.M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_041(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } " + declModifiers + @"int M2() => 2; } class Test1 : I1 { " + implModifiers + @"public int M1() { return 0; } " + implModifiers + @"public ref int M2() { throw null; } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); System.Console.WriteLine(x.M2()); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); System.Console.WriteLine(T.M2()); } "; } source1 += @" } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var m2 = compilation1.GetMember<MethodSymbol>("I1.M2"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"M1 2", verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_042(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } " + declModifiers + @"int M2() => 2; } class Test1 : Test2, I1 { " + implModifiers + @"public int M1() { return 0; } " + implModifiers + @"public ref int M2() { throw null; } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); System.Console.WriteLine(x.M2()); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); System.Console.WriteLine(T.M2()); } "; } source1 += @" } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var m2 = compilation1.GetMember<MethodSymbol>("I1.M2"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"M1 2", verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_043(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() {} " + declModifiers + @"int M2() => 1; } class Test1 : Test2, I1 { " + implModifiers + @"public int M1() { return 0; } " + implModifiers + @"public ref int M2() { throw null; } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); System.Console.WriteLine(x.M2()); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); System.Console.WriteLine(T.M2()); } "; } source1 += @" } class Test2 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test2.M1""); } " + implModifiers + @"int I1.M2() => 2; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var m2 = compilation1.GetMember<MethodSymbol>("I1.M2"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Equal("void Test2.I1.M1()", test1.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); Assert.Equal("System.Int32 Test2.I1.M2()", test1.FindImplementationForInterfaceMember(m2).ToTestDisplayString()); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"Test2.M1 2", verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_044(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"void M1() {} " + declModifiers + @"int M2() => 1; } class Test1 : Test2, I1 { " + implModifiers + @"new public int M1() { return 0; } " + implModifiers + @"new public ref int M2() { throw null; } "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); System.Console.WriteLine(x.M2()); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); System.Console.WriteLine(T.M2()); } "; } source1 += @" } class Test2 : I1 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test2.M1""); } " + implModifiers + @"public int M2() => 2; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); var m2 = compilation1.GetMember<MethodSymbol>("I1.M2"); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Equal("void Test2.M1()", test1.FindImplementationForInterfaceMember(m1).ToTestDisplayString()); Assert.Equal("System.Int32 Test2.M2()", test1.FindImplementationForInterfaceMember(m2).ToTestDisplayString()); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"Test2.M1 2", verify: Verify(isStatic), symbolValidator: (m) => { var test1Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); } [Theory] [CombinatorialData] public void MethodImplementation_051(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation1.VerifyDiagnostics( // (4,10): error CS8501: Target runtime doesn't support default interface implementation. // void M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(4, 10) ); } else { compilation1.VerifyDiagnostics( // (4,25): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual void M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(4, 25) ); } Assert.True(m1.IsMetadataVirtual()); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: isStatic ? TestOptions.Regular11 : TestOptions.Regular8); m1 = compilation3.GetMember<MethodSymbol>("I1.M1"); var test2 = compilation3.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8929: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2").WithLocation(2, 15) ); } } [Theory] [CombinatorialData] public void MethodImplementation_052(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net60, parseOptions: TestOptions.RegularPreview); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" class Test2 : I1 {} "; foreach (var reference in new[] { compilation1.EmitToImageReference(), compilation1.ToMetadataReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: isStatic ? TestOptions.Regular11 : TestOptions.Regular8); var m1 = compilation3.GetMember<MethodSymbol>("I1.M1"); var test2 = compilation3.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8929: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2").WithLocation(2, 15) ); } } } [Theory] [CombinatorialData] public void MethodImplementation_053(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular11, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" public interface I2 { void M2(); } class Test2 : I2 { public void M2() {} } "; foreach (var reference in new[] { compilation1.EmitToImageReference(), compilation1.ToMetadataReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var m1 = compilation3.GetMember<MethodSymbol>("I1.M1"); var test2 = compilation3.GetTypeByMetadataName("Test2"); Assert.Null(test2.FindImplementationForInterfaceMember(m1)); compilation3.VerifyDiagnostics(); } } [Theory] [CombinatorialData] public void MethodImplementation_061(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, skipUsesIsNullable: true); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation1.VerifyDiagnostics( // (4,10): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // void M1() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M1").WithArguments("default interface implementation", "8.0").WithLocation(4, 10), // (4,10): error CS8701: Target runtime doesn't support default interface implementation. // void M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(4, 10) ); } else { compilation1.VerifyDiagnostics( // (4,25): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual void M1() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("virtual", "10.0", "11.0").WithLocation(4, 25), // (4,25): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual void M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(4, 25) ); } Assert.True(m1.IsMetadataVirtual()); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3); m1 = compilation3.GetMember<MethodSymbol>("I1.M1"); var test2 = compilation3.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8706: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2").WithLocation(2, 15) ); } } [Theory] [CombinatorialData] public void MethodImplementation_071(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: isStatic ? TargetFramework.Net60 : TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation1.VerifyDiagnostics( // (4,10): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // void M1() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M1").WithArguments("default interface implementation", "8.0").WithLocation(4, 10) ); } else { compilation1.VerifyDiagnostics( // (4,25): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual void M1() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("virtual", "10.0", "11.0").WithLocation(4, 25) ); } Assert.True(m1.IsMetadataVirtual()); var source2 = @" class Test2 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular11, targetFramework: isStatic ? TargetFramework.Net60 : TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); m1 = compilation2.GetMember<MethodSymbol>("I1.M1"); var test2 = compilation2.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: (m) => { var test2Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test2"); Assert.Equal("I1", test2Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); }); var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: isStatic ? TargetFramework.Net60 : TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); m1 = compilation3.GetMember<MethodSymbol>("I1.M1"); test2 = compilation3.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8706: 'I1.M1()' cannot implement interface member 'I1.M1()' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.M1()", "I1.M1()", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15) ); } } [Theory] [CombinatorialData] public void MethodImplementation_081(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"I1 M1() { throw null; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular11); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); if (!isStatic) { compilation1.VerifyDiagnostics( // (4,8): error CS8501: Target runtime doesn't support default interface implementation. // I1 M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(4, 8) ); } else { compilation1.VerifyDiagnostics( // (4,23): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual I1 M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(4, 23) ); } Assert.True(m1.IsMetadataVirtual()); } [Fact] public void MethodImplementation_091() { var source1 = @" public interface I1 { static void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsStatic); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); compilation1.VerifyDiagnostics( // (4,17): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static void M1() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M1").WithArguments("default interface implementation", "8.0").WithLocation(4, 17) ); Assert.False(m1.IsMetadataVirtual()); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular8, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (4,17): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static void M1() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "M1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 17) ); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics(); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics(); } [Theory] [CombinatorialData] public void MethodImplementation_101(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"void M1() { System.Console.WriteLine(""M1""); } } public interface I2 : I1 {} class Test1 : I2 { "; if (!isStatic) { source1 += @" static void Main() { I1 x = new Test1(); x.M1(); } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source1 += @" } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular11, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var m1 = compilation1.GetMember<MethodSymbol>("I1.M1"); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); compilation1.VerifyDiagnostics(); Assert.True(m1.IsMetadataVirtual()); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var result = (PEMethodSymbol)i1.GetMember("M1"); Assert.True(result.IsMetadataVirtual()); Assert.False(result.IsAbstract); Assert.True(result.IsVirtual); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); int rva; ((PEModuleSymbol)m).Module.GetMethodDefPropsOrThrow(result.Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); var test1Result = m.GlobalNamespace.GetTypeMember("Test1"); var interfaces = test1Result.InterfacesNoUseSiteDiagnostics().ToArray(); Assert.Equal(2, interfaces.Length); Assert.Equal("I2", interfaces[0].ToTestDisplayString()); Assert.Equal("I1", interfaces[1].ToTestDisplayString()); }); var source2 = @" class Test2 : I2 { "; if (!isStatic) { source2 += @" static void Main() { I1 x = new Test2(); x.M1(); } "; } else { source2 += @" static void Main() { Test<Test2>(); } static void Test<T>() where T : I1 { T.M1(); } "; } source2 += @" } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular11, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); m1 = compilation2.GetMember<MethodSymbol>("I1.M1"); var test2 = compilation2.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var test2Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test2"); var interfaces = test2Result.InterfacesNoUseSiteDiagnostics().ToArray(); Assert.Equal(2, interfaces.Length); Assert.Equal("I2", interfaces[0].ToTestDisplayString()); Assert.Equal("I1", interfaces[1].ToTestDisplayString()); }); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular11, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); m1 = compilation3.GetMember<MethodSymbol>("I1.M1"); test2 = compilation3.GetTypeByMetadataName("Test2"); Assert.Same(m1, test2.FindImplementationForInterfaceMember(m1)); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: Execute(isStatic) ? "M1" : null, verify: Verify(isStatic), symbolValidator: (m) => { var test2Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test2"); var interfaces = test2Result.InterfacesNoUseSiteDiagnostics().ToArray(); Assert.Equal(2, interfaces.Length); Assert.Equal("I2", interfaces[0].ToTestDisplayString()); Assert.Equal("I1", interfaces[1].ToTestDisplayString()); }); } [Fact] public void MethodImplementation_111() { var source1 = @" #nullable enable public interface I1<T> { void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2 : I1<string> { } "; var source2 = @" #nullable enable class Test1 : I2, I1<string?> { static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I1<string?> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7) ); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" I1.M1 I1.M1 ", verify: VerifyOnMonoOrCoreClr); } } [Fact] public void MethodImplementation_112() { var source1 = @" #nullable enable public interface I1<T> { void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2 : I1<string> { } "; var source2 = @" #nullable enable class Test1 : I1<string?>, I2 { static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I1<System.String?>", "I2", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I1<System.String>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[0].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I1<System.String>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I1<string?>, I2 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string>", "Test1").WithLocation(4, 7) ); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" I1.M1 I1.M1 ", verify: VerifyOnMonoOrCoreClr); } } [Fact] public void MethodImplementation_113() { var source1 = @" #nullable enable public interface I1<T> { void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2 : I1<string> { } public interface I3 : I1<string?> { } "; var source2 = @" #nullable enable class Test1 : I2, I3 { static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7) ); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" I1.M1 I1.M1 ", verify: VerifyOnMonoOrCoreClr); } } [Fact] public void MethodImplementation_114() { var source1 = @" #nullable enable public interface I1<T> { void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2 : I1<string> { } public interface I3 : I1<string?> { } "; var source2 = @" #nullable enable class Test1 : I3, I2 { static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I3", "I1<System.String?>", "I2", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I1<System.String>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I1<System.String>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I3, I2 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string>", "Test1").WithLocation(4, 7) ); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" I1.M1 I1.M1 ", verify: VerifyOnMonoOrCoreClr); } } [Theory] [CombinatorialData] public void PropertyImplementation_101(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 { get { System.Console.WriteLine(""get P1""); return 0; } } } class Test1 : I1 { "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Test1(); _ = i1.P1; } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { _ = T.P1; } "; } source1 += @" } "; ValidatePropertyImplementation_101(source1, isStatic); } private void ValidatePropertyImplementation_101(string source1, bool isStatic = false) { ValidatePropertyImplementation_101(source1, "P1", haveGet: true, haveSet: false, accessCode: @" _ = i1.P1; ", expectedOutput: "get P1", isStatic: isStatic); } private void ValidatePropertyImplementation_101(string source1, string propertyName, bool haveGet, bool haveSet, string accessCode, string expectedOutput, bool isStatic = false) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { ValidatePropertyImplementationTest1_101(m, propertyName, haveGet, haveSet, isStatic); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: Execute(isStatic) ? expectedOutput : null, verify: Verify(isStatic), symbolValidator: Validate1); var source2 = @" class Test2 : I1 { "; if (!isStatic) { source2 += @" static void Main() { I1 i1 = new Test2(); " + accessCode + @" } "; } else { source2 += @" static void Main() { Test<Test2>(); } static void Test<i1>() where i1 : I1 { " + accessCode + @" } "; } source2 += @" } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate2(ModuleSymbol m) { ValidatePropertyImplementationTest2_101(m, propertyName, haveGet, haveSet); } Validate2(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: Execute(isStatic) ? expectedOutput : null, verify: Verify(isStatic), symbolValidator: Validate2); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate2(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: Execute(isStatic) ? expectedOutput : null, verify: Verify(isStatic), symbolValidator: Validate2); } private static void ValidatePropertyImplementationTest1_101(ModuleSymbol m, string propertyName, bool haveGet, bool haveSet, bool isStatic) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var p1 = i1.GetMember<PropertySymbol>(propertyName); Assert.Equal(!haveSet, p1.IsReadOnly); Assert.Equal(!haveGet, p1.IsWriteOnly); if (haveGet) { ValidateAccessor(p1.GetMethod); } else { Assert.Null(p1.GetMethod); } if (haveSet) { ValidateAccessor(p1.SetMethod); } else { Assert.Null(p1.SetMethod); } void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.Equal(isStatic, accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.Equal(isStatic, p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); if (m is PEModuleSymbol peModule) { int rva; if (haveGet) { peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)p1.GetMethod).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } if (haveSet) { peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)p1.SetMethod).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } } var test1 = m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); if (haveGet) { Assert.Same(p1.GetMethod, test1.FindImplementationForInterfaceMember(p1.GetMethod)); } if (haveSet) { Assert.Same(p1.SetMethod, test1.FindImplementationForInterfaceMember(p1.SetMethod)); } } private static void ValidatePropertyImplementationTest2_101(ModuleSymbol m, string propertyName, bool haveGet, bool haveSet) { var test2 = m.GlobalNamespace.GetTypeMember("Test2"); Assert.Equal("I1", test2.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); var p1 = test2.InterfacesNoUseSiteDiagnostics().Single().GetMember<PropertySymbol>(propertyName); Assert.Same(p1, test2.FindImplementationForInterfaceMember(p1)); if (haveGet) { var getP1 = p1.GetMethod; Assert.Same(getP1, test2.FindImplementationForInterfaceMember(getP1)); } if (haveSet) { var setP1 = p1.SetMethod; Assert.Same(setP1, test2.FindImplementationForInterfaceMember(setP1)); } } [Theory] [CombinatorialData] public void PropertyImplementation_102(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 { get { System.Console.WriteLine(""get P1""); return 0; } set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Test1(); i1.P1 = i1.P1; } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.P1 = T.P1; } "; } source1 += @" } "; ValidatePropertyImplementation_102(source1, isStatic); } private void ValidatePropertyImplementation_102(string source1, bool isStatic = false) { ValidatePropertyImplementation_101(source1, "P1", haveGet: true, haveSet: true, accessCode: @" i1.P1 = i1.P1; ", expectedOutput: @"get P1 set P1", isStatic: isStatic); } [Theory] [CombinatorialData] public void PropertyImplementation_103(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 { set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Test1(); i1.P1 = 1; } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { T.P1 = 1; } "; } source1 += @" } "; ValidatePropertyImplementation_103(source1, isStatic); } private void ValidatePropertyImplementation_103(string source1, bool isStatic = false) { ValidatePropertyImplementation_101(source1, "P1", haveGet: false, haveSet: true, accessCode: @" i1.P1 = 1; ", expectedOutput: "set P1", isStatic: isStatic); } [Theory] [CombinatorialData] public void PropertyImplementation_104(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 => Test1.GetInt(); } class Test1 : I1 { public static int GetInt() { System.Console.WriteLine(""get P1""); return 0; } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Test1(); _ = i1.P1; } "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { _ = T.P1; } "; } source1 += @" } "; ValidatePropertyImplementation_101(source1, isStatic); } [Fact] public void PropertyImplementation_105() { { var source1 = @" public interface I1 { int P1 {add; remove;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,13): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 13), // (4,18): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 18), // (4,9): error CS0548: 'I1.P1': property or indexer must have at least one accessor // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 9), // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "int P1 {add; remove;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsStatic); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static abstract int P1 {add; remove;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,13): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 29), // (4,18): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 34), // (4,9): error CS0548: 'I1.P1': property or indexer must have at least one accessor // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 25), // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "static abstract int P1 {add; remove;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.True(p1.IsStatic); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static virtual int P1 {add; remove;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular11, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,13): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 28), // (4,18): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 33), // (4,9): error CS0548: 'I1.P1': property or indexer must have at least one accessor // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 24), // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int P1 {add; remove;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "static virtual int P1 {add; remove;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.True(p1.IsStatic); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } } [Fact] public void PropertyImplementation_106() { { var source1 = @" public interface I1 { int P1 {get; set;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int P1 {get; set;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "int P1 {get; set;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.True(p1.GetMethod.IsAbstract); Assert.True(p1.SetMethod.IsAbstract); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static abstract int P1 {get; set;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // static abstract int P1 {get; set;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "static abstract int P1 {get; set;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.True(p1.GetMethod.IsAbstract); Assert.True(p1.SetMethod.IsAbstract); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static virtual int P1 {get; set;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int P1 {get; set;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "static virtual int P1 {get; set;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsVirtual); Assert.True(p1.GetMethod.IsVirtual); Assert.True(p1.SetMethod.IsVirtual); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } } [Fact] public void PropertyImplementation_107() { { var source1 = @" public interface I1 { int P1 {add; remove;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,13): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 13), // (4,18): error CS1014: A get, set or init accessor expected // int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 18), // (4,9): error CS8053: Instance properties in interfaces cannot have initializers. // int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P1").WithLocation(4, 9), // (4,9): error CS0548: 'I1.P1': property or indexer must have at least one accessor // int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 9) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static abstract int P1 {add; remove;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,29): error CS1014: A get or set accessor expected // static abstract int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 29), // (4,34): error CS1014: A get or set accessor expected // static abstract int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 34), // (4,25): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers. // static abstract int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P1").WithLocation(4, 25), // (4,25): error CS0548: 'I1.P1': property or indexer must have at least one accessor // static abstract int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 25) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static virtual int P1 {add; remove;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,28): error CS1014: A get or set accessor expected // static virtual int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 28), // (4,33): error CS1014: A get or set accessor expected // static virtual int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 33), // (4,24): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers. // static virtual int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P1").WithLocation(4, 24), // (4,24): error CS0548: 'I1.P1': property or indexer must have at least one accessor // static virtual int P1 {add; remove;} = 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 24) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsVirtual); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } } [Fact] public void PropertyImplementation_108() { { var source1 = @" public interface I1 { int P1 {get; set;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,9): error CS8053: Instance properties in interfaces cannot have initializers.. // int P1 {get; set;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P1").WithLocation(4, 9) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.True(p1.GetMethod.IsAbstract); Assert.True(p1.SetMethod.IsAbstract); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static abstract int P1 {get; set;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,25): error CS8050: Only auto-implemented properties, or properties that use the 'field' keyword, can have initializers. // static abstract int P1 {get; set;} = 0; Diagnostic(ErrorCode.ERR_InitializerOnNonAutoProperty, "P1").WithLocation(4, 25) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsAbstract); Assert.True(p1.GetMethod.IsAbstract); Assert.True(p1.SetMethod.IsAbstract); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } { var source1 = @" public interface I1 { static virtual int P1 {get; set;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics(); var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); Assert.True(p1.IsVirtual); Assert.True(p1.GetMethod.IsVirtual); Assert.True(p1.SetMethod.IsVirtual); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } } [Theory] [CombinatorialData] public void PropertyImplementation_109A(bool isStatic, [CSharp13_CSharp14_Preview] LanguageVersion langVer) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 { get { System.Console.WriteLine(""get P1""); return 0; } set; } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(langVer), targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); bool useCSharp13 = langVer == LanguageVersion.CSharp13; switch (isStatic, useCSharp13) { case (true, true): compilation1.VerifyDiagnostics( // (4,24): error CS9260: Feature 'field keyword' is not available in C# 13.0. Please use language version 14.0 or greater. // static virtual int P1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion13, "P1").WithArguments("field keyword", "14.0").WithLocation(4, 24)); break; case (true, false): compilation1.VerifyDiagnostics( // (6,9): warning CS9266: The 'get' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // get Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); break; case (false, true): compilation1.VerifyDiagnostics( // (4,9): error CS9260: Feature 'field keyword' is not available in C# 13.0. Please use language version 14.0 or greater. // int P1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion13, "P1").WithArguments("field keyword", "14.0").WithLocation(4, 9), // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9)); break; case (false, false): // See also earlier LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-04-18.md, // we don't want to allow only one accessor to have an implementation. compilation1.VerifyDiagnostics( // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9), // (6,9): warning CS9266: The 'get' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // get Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); break; } var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); var getP1 = p1.GetMethod; var setP1 = p1.SetMethod; Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); var field1 = ((SourcePropertySymbolBase)p1).BackingField; Assert.Equal("System.Int32 I1.<P1>k__BackingField", field1?.ToTestDisplayString()); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(getP1.IsAbstract); Assert.True(getP1.IsVirtual); Assert.False(setP1.IsAbstract); Assert.True(setP1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(getP1, test1.FindImplementationForInterfaceMember(getP1)); Assert.Same(setP1, test1.FindImplementationForInterfaceMember(setP1)); Assert.True(getP1.IsMetadataVirtual()); Assert.True(setP1.IsMetadataVirtual()); } [Theory] [CombinatorialData] public void PropertyImplementation_109B([CSharp13_CSharp14_Preview] LanguageVersion langVer) { var source1 = @" public interface I1 { static int P1 { get { System.Console.WriteLine(""get P1""); return 0; } set; } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(langVer), targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); bool useCSharp13 = langVer == LanguageVersion.CSharp13; if (useCSharp13) { compilation1.VerifyDiagnostics( // (4,16): error CS9260: Feature 'field keyword' is not available in C# 13.0. Please use language version 14.0 or greater. // static int P1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion13, "P1").WithArguments("field keyword", "14.0").WithLocation(4, 16)); } else { compilation1.VerifyDiagnostics( // (6,9): warning CS9266: The 'get' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // get Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "get").WithArguments("get", "I1.P1").WithLocation(6, 9)); } var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); var getP1 = p1.GetMethod; var setP1 = p1.SetMethod; Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); var field1 = ((SourcePropertySymbolBase)p1).BackingField; Assert.Equal("System.Int32 I1.<P1>k__BackingField", field1?.ToTestDisplayString()); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(getP1.IsAbstract); Assert.False(getP1.IsVirtual); Assert.False(setP1.IsAbstract); Assert.False(setP1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test1.FindImplementationForInterfaceMember(getP1)); Assert.Null(test1.FindImplementationForInterfaceMember(setP1)); Assert.False(getP1.IsMetadataVirtual()); Assert.False(setP1.IsMetadataVirtual()); } [Theory] [CombinatorialData] public void PropertyImplementation_110A(bool isStatic, [CSharp13_CSharp14_Preview] LanguageVersion langVer) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 { get; set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(langVer), targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); bool useCSharp13 = langVer == LanguageVersion.CSharp13; switch (isStatic, useCSharp13) { case (true, true): compilation1.VerifyDiagnostics( // (4,24): error CS9260: Feature 'field keyword' is not available in C# 13.0. Please use language version 14.0 or greater. // static virtual int P1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion13, "P1").WithArguments("field keyword", "14.0").WithLocation(4, 24)); break; case (true, false): compilation1.VerifyDiagnostics( // (7,9): warning CS9266: The 'set' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // set => System.Console.WriteLine("set P1"); Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); break; case (false, true): compilation1.VerifyDiagnostics( // (4,9): error CS9260: Feature 'field keyword' is not available in C# 13.0. Please use language version 14.0 or greater. // int P1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion13, "P1").WithArguments("field keyword", "14.0").WithLocation(4, 9), // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9)); break; case (false, false): // See also earlier LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-04-18.md, // we don't want to allow only one accessor to have an implementation. compilation1.VerifyDiagnostics( // (4,9): error CS0525: Interfaces cannot contain instance fields // int P1 Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "P1").WithLocation(4, 9), // (7,9): warning CS9266: The 'set' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // set => System.Console.WriteLine("set P1"); Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); break; } var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); var getP1 = p1.GetMethod; var setP1 = p1.SetMethod; Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); var field1 = ((SourcePropertySymbolBase)p1).BackingField; Assert.Equal("System.Int32 I1.<P1>k__BackingField", field1?.ToTestDisplayString()); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(getP1.IsAbstract); Assert.True(getP1.IsVirtual); Assert.False(setP1.IsAbstract); Assert.True(setP1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(getP1, test1.FindImplementationForInterfaceMember(getP1)); Assert.Same(setP1, test1.FindImplementationForInterfaceMember(setP1)); Assert.True(getP1.IsMetadataVirtual()); Assert.True(setP1.IsMetadataVirtual()); } [Theory] [CombinatorialData] public void PropertyImplementation_110B([CSharp13_CSharp14_Preview] LanguageVersion langVer) { var source1 = @" public interface I1 { static int P1 { get; set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular.WithLanguageVersion(langVer), targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); bool useCSharp13 = langVer == LanguageVersion.CSharp13; if (useCSharp13) { compilation1.VerifyDiagnostics( // (4,16): error CS9260: Feature 'field keyword' is not available in C# 13.0. Please use language version 14.0 or greater. // static int P1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion13, "P1").WithArguments("field keyword", "14.0").WithLocation(4, 16)); } else { compilation1.VerifyDiagnostics( // (7,9): warning CS9266: The 'set' accessor of property 'I1.P1' should use 'field' because the other accessor is using it. // set => System.Console.WriteLine("set P1"); Diagnostic(ErrorCode.WRN_AccessorDoesNotUseBackingField, "set").WithArguments("set", "I1.P1").WithLocation(7, 9)); } var p1 = compilation1.GetMember<PropertySymbol>("I1.P1"); var getP1 = p1.GetMethod; var setP1 = p1.SetMethod; Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); var field1 = ((SourcePropertySymbolBase)p1).BackingField; Assert.Equal("System.Int32 I1.<P1>k__BackingField", field1?.ToTestDisplayString()); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(getP1.IsAbstract); Assert.False(getP1.IsVirtual); Assert.False(setP1.IsAbstract); Assert.False(setP1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test1.FindImplementationForInterfaceMember(getP1)); Assert.Null(test1.FindImplementationForInterfaceMember(setP1)); Assert.False(getP1.IsMetadataVirtual()); Assert.False(setP1.IsMetadataVirtual()); } [Theory] [CombinatorialData] public void PropertyImplementation_201(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P2 => 2; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P4 { get => 4; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P6 { set => System.Console.WriteLine(6); } " + declModifiers + @"int P7 { get { return 7;} set {System.Console.WriteLine(71);} } " + declModifiers + @"int P8 { get { return 8;} set {System.Console.WriteLine(81);} } } class Base { " + implModifiers + @"int P1 => 10; " + implModifiers + @"int P3 { get => 30; } " + implModifiers + @"int P5 { set => System.Console.WriteLine(50); } " + implModifiers + @"int P7 { get { return 70;} set {} } } class Derived : Base, I1 { " + implModifiers + @"int P2 => 20; " + implModifiers + @"int P4 { get => 40; } " + implModifiers + @"int P6 { set => System.Console.WriteLine(60); } " + implModifiers + @"int P8 { get { return 80;} set {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" System.Console.WriteLine(i1.P1); System.Console.WriteLine(i1.P2); System.Console.WriteLine(i1.P3); System.Console.WriteLine(i1.P4); i1.P5 = 0; i1.P6 = 0; System.Console.WriteLine(i1.P7); i1.P7 = 0; System.Console.WriteLine(i1.P8); i1.P8 = 0; } } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); ValidatePropertyImplementation_201(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"1 2 3 4 5 6 7 71 8 81 ", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidatePropertyImplementation_201(m); }); } private static void ValidatePropertyImplementation_201(ModuleSymbol m) { var p1 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P1"); var p2 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P2"); var p3 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P3"); var p4 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P4"); var p5 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P5"); var p6 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P6"); var p7 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P7"); var p8 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P8"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Same(p1, derived.FindImplementationForInterfaceMember(p1)); Assert.Same(p2, derived.FindImplementationForInterfaceMember(p2)); Assert.Same(p3, derived.FindImplementationForInterfaceMember(p3)); Assert.Same(p4, derived.FindImplementationForInterfaceMember(p4)); Assert.Same(p5, derived.FindImplementationForInterfaceMember(p5)); Assert.Same(p6, derived.FindImplementationForInterfaceMember(p6)); Assert.Same(p7, derived.FindImplementationForInterfaceMember(p7)); Assert.Same(p8, derived.FindImplementationForInterfaceMember(p8)); Assert.Same(p1.GetMethod, derived.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Same(p2.GetMethod, derived.FindImplementationForInterfaceMember(p2.GetMethod)); Assert.Same(p3.GetMethod, derived.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Same(p4.GetMethod, derived.FindImplementationForInterfaceMember(p4.GetMethod)); Assert.Same(p5.SetMethod, derived.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Same(p6.SetMethod, derived.FindImplementationForInterfaceMember(p6.SetMethod)); Assert.Same(p7.GetMethod, derived.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Same(p8.GetMethod, derived.FindImplementationForInterfaceMember(p8.GetMethod)); Assert.Same(p7.SetMethod, derived.FindImplementationForInterfaceMember(p7.SetMethod)); Assert.Same(p8.SetMethod, derived.FindImplementationForInterfaceMember(p8.SetMethod)); } [Theory] [CombinatorialData] public void PropertyImplementation_202(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P2 => 2; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P4 { get => 4; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P6 { set => System.Console.WriteLine(6); } " + declModifiers + @"int P7 { get { return 7;} set {System.Console.WriteLine(71);} } " + declModifiers + @"int P8 { get { return 8;} set {System.Console.WriteLine(81);} } } class Base : Test { " + implModifiers + @"int P1 => 10; " + implModifiers + @"int P3 { get => 30; } " + implModifiers + @"int P5 { set => System.Console.WriteLine(50); } " + implModifiers + @"int P7 { get { return 70;} set {} } } class Derived : Base, I1 { " + implModifiers + @"int P2 => 20; " + implModifiers + @"int P4 { get => 40; } " + implModifiers + @"int P6 { set => System.Console.WriteLine(60); } " + implModifiers + @"int P8 { get { return 80;} set {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" System.Console.WriteLine(i1.P1); System.Console.WriteLine(i1.P2); System.Console.WriteLine(i1.P3); System.Console.WriteLine(i1.P4); i1.P5 = 0; i1.P6 = 0; System.Console.WriteLine(i1.P7); i1.P7 = 0; System.Console.WriteLine(i1.P8); i1.P8 = 0; } } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); ValidatePropertyImplementation_201(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"1 2 3 4 5 6 7 71 8 81 ", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidatePropertyImplementation_201(m); }); } [Theory] [CombinatorialData] public void PropertyImplementation_203(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P2 => 2; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P4 { get => 4; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P6 { set => System.Console.WriteLine(6); } " + declModifiers + @"int P7 { get { return 7;} set {} } " + declModifiers + @"int P8 { get { return 8;} set {} } } class Base : Test { " + implModifiers + @"int P1 => 10; " + implModifiers + @"int P3 { get => 30; } " + implModifiers + @"int P5 { set => System.Console.WriteLine(50); } " + implModifiers + @"int P7 { get { return 70;} set {} } } class Derived : Base, I1 { " + implModifiers + @"int P2 => 20; " + implModifiers + @"int P4 { get => 40; } " + implModifiers + @"int P6 { set => System.Console.WriteLine(60); } " + implModifiers + @"int P8 { get { return 80;} set {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" System.Console.WriteLine(i1.P1); System.Console.WriteLine(i1.P2); System.Console.WriteLine(i1.P3); System.Console.WriteLine(i1.P4); i1.P5 = 0; i1.P6 = 0; System.Console.WriteLine(i1.P7); i1.P7 = 0; System.Console.WriteLine(i1.P8); i1.P8 = 0; } } class Test : I1 { " + implModifiers + @"int I1.P1 => 100; " + implModifiers + @"int I1.P2 => 200; " + implModifiers + @"int I1.P3 { get => 300; } " + implModifiers + @"int I1.P4 { get => 400; } " + implModifiers + @"int I1.P5 { set => System.Console.WriteLine(500); } " + implModifiers + @"int I1.P6 { set => System.Console.WriteLine(600); } " + implModifiers + @"int I1.P7 { get { return 700;} set {System.Console.WriteLine(701);} } " + implModifiers + @"int I1.P8 { get { return 800;} set {System.Console.WriteLine(801);} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var p1 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P1"); var p2 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P2"); var p3 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P3"); var p4 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P4"); var p5 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P5"); var p6 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P6"); var p7 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P7"); var p8 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P8"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("System.Int32 Test.I1.P1 { get; }", derived.FindImplementationForInterfaceMember(p1).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P2 { get; }", derived.FindImplementationForInterfaceMember(p2).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P3 { get; }", derived.FindImplementationForInterfaceMember(p3).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P4 { get; }", derived.FindImplementationForInterfaceMember(p4).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P5 { set; }", derived.FindImplementationForInterfaceMember(p5).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P6 { set; }", derived.FindImplementationForInterfaceMember(p6).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P7 { get; set; }", derived.FindImplementationForInterfaceMember(p7).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P8 { get; set; }", derived.FindImplementationForInterfaceMember(p8).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P1.get", derived.FindImplementationForInterfaceMember(p1.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P2.get", derived.FindImplementationForInterfaceMember(p2.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P3.get", derived.FindImplementationForInterfaceMember(p3.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P4.get", derived.FindImplementationForInterfaceMember(p4.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.P5.set", derived.FindImplementationForInterfaceMember(p5.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.P6.set", derived.FindImplementationForInterfaceMember(p6.SetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P7.get", derived.FindImplementationForInterfaceMember(p7.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.P8.get", derived.FindImplementationForInterfaceMember(p8.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.P7.set", derived.FindImplementationForInterfaceMember(p7.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.P8.set", derived.FindImplementationForInterfaceMember(p8.SetMethod).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"100 200 300 400 500 600 700 701 800 801 ", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void PropertyImplementation_204(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P2 => 2; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P4 { get => 4; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P6 { set => System.Console.WriteLine(6); } " + declModifiers + @"int P7 { get { return 7;} set {} } " + declModifiers + @"int P8 { get { return 8;} set {} } } class Base : Test { " + implModifiers + @"new int P1 => 10; " + implModifiers + @"new int P3 { get => 30; } " + implModifiers + @"new int P5 { set => System.Console.WriteLine(50); } " + implModifiers + @"new int P7 { get { return 70;} set {} } } class Derived : Base, I1 { " + implModifiers + @"new int P2 => 20; " + implModifiers + @"new int P4 { get => 40; } " + implModifiers + @"new int P6 { set => System.Console.WriteLine(60); } " + implModifiers + @"new int P8 { get { return 80;} set {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" System.Console.WriteLine(i1.P1); System.Console.WriteLine(i1.P2); System.Console.WriteLine(i1.P3); System.Console.WriteLine(i1.P4); i1.P5 = 0; i1.P6 = 0; System.Console.WriteLine(i1.P7); i1.P7 = 0; System.Console.WriteLine(i1.P8); i1.P8 = 0; } } class Test : I1 { " + implModifiers + @"public int P1 => 100; " + implModifiers + @"public int P2 => 200; " + implModifiers + @"public int P3 { get => 300; } " + implModifiers + @"public int P4 { get => 400; } " + implModifiers + @"public int P5 { set => System.Console.WriteLine(500); } " + implModifiers + @"public int P6 { set => System.Console.WriteLine(600); } " + implModifiers + @"public int P7 { get { return 700;} set {System.Console.WriteLine(701);} } " + implModifiers + @"public int P8 { get { return 800;} set {System.Console.WriteLine(801);} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var p1 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P1"); var p2 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P2"); var p3 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P3"); var p4 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P4"); var p5 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P5"); var p6 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P6"); var p7 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P7"); var p8 = m.GlobalNamespace.GetMember<PropertySymbol>("I1.P8"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("System.Int32 Test.P1 { get; }", derived.FindImplementationForInterfaceMember(p1).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P2 { get; }", derived.FindImplementationForInterfaceMember(p2).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P3 { get; }", derived.FindImplementationForInterfaceMember(p3).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P4 { get; }", derived.FindImplementationForInterfaceMember(p4).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P5 { set; }", derived.FindImplementationForInterfaceMember(p5).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P6 { set; }", derived.FindImplementationForInterfaceMember(p6).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P7 { get; set; }", derived.FindImplementationForInterfaceMember(p7).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P8 { get; set; }", derived.FindImplementationForInterfaceMember(p8).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P1.get", derived.FindImplementationForInterfaceMember(p1.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P2.get", derived.FindImplementationForInterfaceMember(p2.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P3.get", derived.FindImplementationForInterfaceMember(p3.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P4.get", derived.FindImplementationForInterfaceMember(p4.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.P5.set", derived.FindImplementationForInterfaceMember(p5.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.P6.set", derived.FindImplementationForInterfaceMember(p6.SetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P7.get", derived.FindImplementationForInterfaceMember(p7.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.P8.get", derived.FindImplementationForInterfaceMember(p8.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.P7.set", derived.FindImplementationForInterfaceMember(p7.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.P8.set", derived.FindImplementationForInterfaceMember(p8.SetMethod).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"100 200 300 400 500 600 700 701 800 801 ", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void PropertyImplementation_501(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P7 { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); if (!isStatic) { compilation1.VerifyDiagnostics( // (4,15): error CS8501: Target runtime doesn't support default interface implementation. // int P1 => 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "1").WithLocation(4, 15), // (6,7): error CS8501: Target runtime doesn't support default interface implementation. // { get => 3; } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(6, 7), // (8,7): error CS8501: Target runtime doesn't support default interface implementation. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(8, 7), // (11,9): error CS8501: Target runtime doesn't support default interface implementation. // get { return 7;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(11, 9), // (12,9): error CS8501: Target runtime doesn't support default interface implementation. // set {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(12, 9) ); } else { compilation1.VerifyDiagnostics( // (4,30): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual int P1 => 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "1").WithLocation(4, 30), // (6,7): error CS8919: Target runtime doesn't support static abstract members in interfaces. // { get => 3; } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "get").WithLocation(6, 7), // (8,7): error CS8919: Target runtime doesn't support static abstract members in interfaces. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "set").WithLocation(8, 7), // (11,9): error CS8919: Target runtime doesn't support static abstract members in interfaces. // get { return 7;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "get").WithLocation(11, 9), // (12,9): error CS8919: Target runtime doesn't support static abstract members in interfaces. // set {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "set").WithLocation(12, 9) ); } ValidatePropertyImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8929: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2").WithLocation(2, 15) ); } ValidatePropertyImplementation_501(compilation3.SourceModule, "Test2"); } private static void ValidatePropertyImplementation_501(ModuleSymbol m, string typeName) { var derived = m.GlobalNamespace.GetTypeMember(typeName); var i1 = derived.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.ToTestDisplayString()); var p1 = i1.GetMember<PropertySymbol>("P1"); var p3 = i1.GetMember<PropertySymbol>("P3"); var p5 = i1.GetMember<PropertySymbol>("P5"); var p7 = i1.GetMember<PropertySymbol>("P7"); Assert.True(p1.IsVirtual); Assert.True(p3.IsVirtual); Assert.True(p5.IsVirtual); Assert.True(p7.IsVirtual); Assert.False(p1.IsAbstract); Assert.False(p3.IsAbstract); Assert.False(p5.IsAbstract); Assert.False(p7.IsAbstract); Assert.Same(p1, derived.FindImplementationForInterfaceMember(p1)); Assert.Same(p3, derived.FindImplementationForInterfaceMember(p3)); Assert.Same(p5, derived.FindImplementationForInterfaceMember(p5)); Assert.Same(p7, derived.FindImplementationForInterfaceMember(p7)); Assert.True(p1.GetMethod.IsVirtual); Assert.True(p3.GetMethod.IsVirtual); Assert.True(p5.SetMethod.IsVirtual); Assert.True(p7.GetMethod.IsVirtual); Assert.True(p7.SetMethod.IsVirtual); Assert.True(p1.GetMethod.IsMetadataVirtual()); Assert.True(p3.GetMethod.IsMetadataVirtual()); Assert.True(p5.SetMethod.IsMetadataVirtual()); Assert.True(p7.GetMethod.IsMetadataVirtual()); Assert.True(p7.SetMethod.IsMetadataVirtual()); Assert.False(p1.GetMethod.IsAbstract); Assert.False(p3.GetMethod.IsAbstract); Assert.False(p5.SetMethod.IsAbstract); Assert.False(p7.GetMethod.IsAbstract); Assert.False(p7.SetMethod.IsAbstract); Assert.Same(p1.GetMethod, derived.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Same(p3.GetMethod, derived.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Same(p5.SetMethod, derived.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Same(p7.GetMethod, derived.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Same(p7.SetMethod, derived.FindImplementationForInterfaceMember(p7.SetMethod)); } [Theory] [CombinatorialData] public void PropertyImplementation_502(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P7 { get { return 7;} set {} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8929: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2").WithLocation(2, 15) ); } ValidatePropertyImplementation_501(compilation3.SourceModule, "Test2"); } [Theory] [CombinatorialData] public void PropertyImplementation_503(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P7 { get { return 7;} set {} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" public interface I2 { void M2(); } class Test2 : I2 { public void M2() {} } "; var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, targetFramework: TargetFramework.Mscorlib461Extended, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var test2 = compilation3.GetTypeByMetadataName("Test2"); var i1 = compilation3.GetTypeByMetadataName("I1"); Assert.Equal("I1", i1.ToTestDisplayString()); var p1 = i1.GetMember<PropertySymbol>("P1"); var p3 = i1.GetMember<PropertySymbol>("P3"); var p5 = i1.GetMember<PropertySymbol>("P5"); var p7 = i1.GetMember<PropertySymbol>("P7"); Assert.Null(test2.FindImplementationForInterfaceMember(p1)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p7)); Assert.Null(test2.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p7.SetMethod)); compilation3.VerifyDiagnostics(); } [Fact] public void PropertyImplementation_601() { { var source1 = @" public interface I1 { int P1 => 1; int P3 { get => 3; } int P5 { set => System.Console.WriteLine(5); } int P7 { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); Assert.False(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,15): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P1 => 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "1").WithArguments("default interface implementation", "8.0").WithLocation(4, 15), // (4,15): error CS8701: Target runtime doesn't support default interface implementation. // int P1 => 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "1").WithLocation(4, 15), // (5,14): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P3 { get => 3; } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(5, 14), // (5,14): error CS8701: Target runtime doesn't support default interface implementation. // int P3 { get => 3; } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(5, 14), // (6,14): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(6, 14), // (6,14): error CS8701: Target runtime doesn't support default interface implementation. // int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(6, 14), // (7,14): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(7, 14), // (7,14): error CS8701: Target runtime doesn't support default interface implementation. // int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(7, 14), // (7,31): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(7, 31), // (7,31): error CS8701: Target runtime doesn't support default interface implementation. // int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(7, 31) ); ValidatePropertyImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2").WithLocation(2, 15) ); ValidatePropertyImplementation_501(compilation3.SourceModule, "Test2"); } { var source1 = @" public interface I1 { static virtual int P1 => 1; static virtual int P3 { get => 3; } static virtual int P5 { set => System.Console.WriteLine(5); } static virtual int P7 { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.Regular10, skipUsesIsNullable: true); compilation1.VerifyDiagnostics( // (4,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P1 => 1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("virtual", "10.0", "11.0").WithLocation(4, 24), // (4,30): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual int P1 => 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "1").WithLocation(4, 30), // (5,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P3 { get => 3; } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("virtual", "10.0", "11.0").WithLocation(5, 24), // (5,29): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual int P3 { get => 3; } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "get").WithLocation(5, 29), // (6,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P5").WithArguments("virtual", "10.0", "11.0").WithLocation(6, 24), // (6,29): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "set").WithLocation(6, 29), // (7,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P7").WithArguments("virtual", "10.0", "11.0").WithLocation(7, 24), // (7,29): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "get").WithLocation(7, 29), // (7,46): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static virtual int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "set").WithLocation(7, 46) ); ValidatePropertyImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.Regular10); compilation3.VerifyDiagnostics( // (2,15): error CS8706: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2").WithLocation(2, 15) ); ValidatePropertyImplementation_501(compilation3.SourceModule, "Test2"); } } [Theory] [CombinatorialData] public void PropertyImplementation_701(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"int P1 => 1; " + declModifiers + @"int P3 { get => 3; } " + declModifiers + @"int P5 { set => System.Console.WriteLine(5); } " + declModifiers + @"int P7 { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (!isStatic) { compilation1.VerifyDiagnostics( // (4,15): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P1 => 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "1").WithArguments("default interface implementation", "8.0").WithLocation(4, 15), // (5,14): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P3 { get => 3; } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(5, 14), // (6,14): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(6, 14), // (7,14): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(7, 14), // (7,31): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(7, 31) ); } else { compilation1.VerifyDiagnostics( // (4,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P1 => 1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("virtual", "10.0", "11.0").WithLocation(4, 24), // (5,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P3 { get => 3; } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("virtual", "10.0", "11.0").WithLocation(5, 24), // (6,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P5").WithArguments("virtual", "10.0", "11.0").WithLocation(6, 24), // (7,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P7").WithArguments("virtual", "10.0", "11.0").WithLocation(7, 24) ); } ValidatePropertyImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidatePropertyImplementation_501(compilation2.SourceModule, "Test2"); CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: (m) => { var test2Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test2"); Assert.Equal("I1", test2Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidatePropertyImplementation_501(m, "Test2"); }); var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8706: 'I1.P1.get' cannot implement interface member 'I1.P1.get' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P1.get", "I1.P1.get", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P3.get' cannot implement interface member 'I1.P3.get' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P3.get", "I1.P3.get", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P5.set' cannot implement interface member 'I1.P5.set' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P5.set", "I1.P5.set", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P7.get' cannot implement interface member 'I1.P7.get' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.get", "I1.P7.get", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8706: 'I1.P7.set' cannot implement interface member 'I1.P7.set' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.P7.set", "I1.P7.set", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15) ); } ValidatePropertyImplementation_501(compilation3.SourceModule, "Test2"); } [Fact] public void PropertyImplementation_901() { var source1 = @" public interface I1 { static int P1 => 1; static int P3 { get => 3; } static int P5 { set => System.Console.WriteLine(5); } static int P7 { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static int P1 => 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "P1").WithArguments("default interface implementation", "8.0").WithLocation(4, 16), // (5,16): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static int P3 { get => 3; } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "P3").WithArguments("default interface implementation", "8.0").WithLocation(5, 16), // (6,16): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static int P5 { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "P5").WithArguments("default interface implementation", "8.0").WithLocation(6, 16), // (7,16): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static int P7 { get { return 7;} set {} } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "P7").WithArguments("default interface implementation", "8.0").WithLocation(7, 16) ); var derived = compilation1.SourceModule.GlobalNamespace.GetTypeMember("Test1"); var i1 = derived.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.ToTestDisplayString()); var p1 = i1.GetMember<PropertySymbol>("P1"); var p3 = i1.GetMember<PropertySymbol>("P3"); var p5 = i1.GetMember<PropertySymbol>("P5"); var p7 = i1.GetMember<PropertySymbol>("P7"); Assert.True(p1.IsStatic); Assert.True(p3.IsStatic); Assert.True(p5.IsStatic); Assert.True(p7.IsStatic); Assert.False(p1.IsVirtual); Assert.False(p3.IsVirtual); Assert.False(p5.IsVirtual); Assert.False(p7.IsVirtual); Assert.False(p1.IsAbstract); Assert.False(p3.IsAbstract); Assert.False(p5.IsAbstract); Assert.False(p7.IsAbstract); Assert.Null(derived.FindImplementationForInterfaceMember(p1)); Assert.Null(derived.FindImplementationForInterfaceMember(p3)); Assert.Null(derived.FindImplementationForInterfaceMember(p5)); Assert.Null(derived.FindImplementationForInterfaceMember(p7)); Assert.True(p1.GetMethod.IsStatic); Assert.True(p3.GetMethod.IsStatic); Assert.True(p5.SetMethod.IsStatic); Assert.True(p7.GetMethod.IsStatic); Assert.True(p7.SetMethod.IsStatic); Assert.False(p1.GetMethod.IsVirtual); Assert.False(p3.GetMethod.IsVirtual); Assert.False(p5.SetMethod.IsVirtual); Assert.False(p7.GetMethod.IsVirtual); Assert.False(p7.SetMethod.IsVirtual); Assert.False(p1.GetMethod.IsMetadataVirtual()); Assert.False(p3.GetMethod.IsMetadataVirtual()); Assert.False(p5.SetMethod.IsMetadataVirtual()); Assert.False(p7.GetMethod.IsMetadataVirtual()); Assert.False(p7.SetMethod.IsMetadataVirtual()); Assert.False(p1.GetMethod.IsAbstract); Assert.False(p3.GetMethod.IsAbstract); Assert.False(p5.SetMethod.IsAbstract); Assert.False(p7.GetMethod.IsAbstract); Assert.False(p7.SetMethod.IsAbstract); Assert.Null(derived.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Null(derived.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Null(derived.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Null(derived.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Null(derived.FindImplementationForInterfaceMember(p7.SetMethod)); } [Fact] public void IndexerImplementation_101() { var source1 = @" public interface I1 { int this[int i] { get { System.Console.WriteLine(""get P1""); return 0; } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); _ = i1[0]; } } "; ValidateIndexerImplementation_101(source1); } private void ValidateIndexerImplementation_101(string source1) { ValidatePropertyImplementation_101(source1, "this[]", haveGet: true, haveSet: false, accessCode: @" _ = i1[0]; ", expectedOutput: "get P1"); } [Fact] public void IndexerImplementation_102() { var source1 = @" public interface I1 { int this[int i] { get { System.Console.WriteLine(""get P1""); return 0; } set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1[0] = i1[0]; } } "; ValidateIndexerImplementation_102(source1); } private void ValidateIndexerImplementation_102(string source1) { ValidatePropertyImplementation_101(source1, "this[]", haveGet: true, haveSet: true, accessCode: @" i1[0] = i1[0]; ", expectedOutput: @"get P1 set P1"); } [Fact] public void IndexerImplementation_103() { var source1 = @" public interface I1 { int this[int i] { set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1[0] = 1; } } "; ValidateIndexerImplementation_103(source1); } private void ValidateIndexerImplementation_103(string source1) { ValidatePropertyImplementation_101(source1, "this[]", haveGet: false, haveSet: true, accessCode: @" i1[0] = 1; ", expectedOutput: "set P1"); } [Fact] public void IndexerImplementation_104() { var source1 = @" public interface I1 { int this[int i] => Test1.GetInt(); } class Test1 : I1 { public static int GetInt() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); _ = i1[0]; } } "; ValidateIndexerImplementation_101(source1); } [Fact] public void IndexerImplementation_105() { var source1 = @" public interface I1 { int this[int i] {add; remove;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,22): error CS1014: A get, set or init accessor expected // int this[int i] {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 22), // (4,27): error CS1014: A get, set or init accessor expected // int this[int i] {add; remove;} => 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 27), // (4,9): error CS0548: 'I1.this[int]': property or indexer must have at least one accessor // int this[int i] {add; remove;} => 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "this").WithArguments("I1.this[int]").WithLocation(4, 9), // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int this[int i] {add; remove;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "int this[int i] {add; remove;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.this[]"); Assert.True(p1.IsAbstract); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } [Fact] public void IndexerImplementation_106() { var source1 = @" public interface I1 { int this[int i] {get; set;} => 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,5): error CS8057: Block bodies and expression bodies cannot both be provided. // int this[int i] {get; set;} => 0; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "int this[int i] {get; set;} => 0;").WithLocation(4, 5) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.this[]"); Assert.True(p1.IsAbstract); Assert.True(p1.GetMethod.IsAbstract); Assert.True(p1.SetMethod.IsAbstract); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } [Fact] public void IndexerImplementation_107() { var source1 = @" public interface I1 { int this[int i] {add; remove;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,36): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // int this[int i] {add; remove;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 36), // (4,22): error CS1014: A get, set or init accessor expected // int this[int i] {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "add").WithLocation(4, 22), // (4,27): error CS1014: A get, set or init accessor expected // int this[int i] {add; remove;} = 0; Diagnostic(ErrorCode.ERR_GetOrSetExpected, "remove").WithLocation(4, 27), // (4,9): error CS0548: 'I1.this[int]': property or indexer must have at least one accessor // int this[int i] {add; remove;} = 0; Diagnostic(ErrorCode.ERR_PropertyWithNoAccessors, "this").WithArguments("I1.this[int]").WithLocation(4, 9) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.this[]"); Assert.True(p1.IsAbstract); Assert.Null(p1.GetMethod); Assert.Null(p1.SetMethod); Assert.True(p1.IsReadOnly); Assert.True(p1.IsWriteOnly); } [Fact] public void IndexerImplementation_108() { var source1 = @" public interface I1 { int this[int i] {get; set;} = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,33): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // int this[int i] {get; set;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 33) ); var p1 = compilation1.GetMember<PropertySymbol>("I1.this[]"); Assert.True(p1.IsAbstract); Assert.True(p1.GetMethod.IsAbstract); Assert.True(p1.SetMethod.IsAbstract); Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); } [Fact] public void IndexerImplementation_109() { var source1 = @" public interface I1 { int this[int i] { get { System.Console.WriteLine(""get P1""); return 0; } set; } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); // According to LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-04-18.md, // we don't want to allow only one accessor to have an implementation. compilation1.VerifyDiagnostics( // (11,9): error CS0501: 'I1.this[int].set' must declare a body because it is not marked abstract, extern, or partial // set; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.this[int].set") ); var p1 = compilation1.GetMember<PropertySymbol>("I1.this[]"); var getP1 = p1.GetMethod; var setP1 = p1.SetMethod; Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(getP1.IsAbstract); Assert.True(getP1.IsVirtual); Assert.False(setP1.IsAbstract); Assert.True(setP1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(getP1, test1.FindImplementationForInterfaceMember(getP1)); Assert.Same(setP1, test1.FindImplementationForInterfaceMember(setP1)); Assert.True(getP1.IsMetadataVirtual()); Assert.True(setP1.IsMetadataVirtual()); } [Fact] public void IndexerImplementation_110() { var source1 = @" public interface I1 { int this[int i] { get; set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); // According to LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-04-18.md, // we don't want to allow only one accessor to have an implementation. compilation1.VerifyDiagnostics( // (6,9): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial // get; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get") ); var p1 = compilation1.GetMember<PropertySymbol>("I1.this[]"); var getP1 = p1.GetMethod; var setP1 = p1.SetMethod; Assert.False(p1.IsReadOnly); Assert.False(p1.IsWriteOnly); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(getP1.IsAbstract); Assert.True(getP1.IsVirtual); Assert.False(setP1.IsAbstract); Assert.True(setP1.IsVirtual); var test1 = compilation1.GetTypeByMetadataName("Test1"); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(getP1, test1.FindImplementationForInterfaceMember(getP1)); Assert.Same(setP1, test1.FindImplementationForInterfaceMember(setP1)); Assert.True(getP1.IsMetadataVirtual()); Assert.True(setP1.IsMetadataVirtual()); } [Fact] public void IndexerImplementation_201() { var source1 = @" interface I1 { int this[sbyte i] => 1; int this[byte i] => 2; int this[short i] { get => 3; } int this[ushort i] { get => 4; } int this[int i] { set => System.Console.WriteLine(5); } int this[uint i] { set => System.Console.WriteLine(6); } int this[long i] { get { return 7;} set {System.Console.WriteLine(71);} } int this[ulong i] { get { return 8;} set {System.Console.WriteLine(81);} } } class Base { int this[sbyte i] => 10; int this[short i] { get => 30; } int this[int i] { set => System.Console.WriteLine(50); } int this[long i] { get { return 70;} set {} } } class Derived : Base, I1 { int this[byte i] => 20; int this[ushort i] { get => 40; } int this[uint i] { set => System.Console.WriteLine(60); } int this[ulong i] { get { return 80;} set {} } static void Main() { I1 i1 = new Derived(); System.Console.WriteLine(i1[(sbyte)0]); System.Console.WriteLine(i1[(byte)0]); System.Console.WriteLine(i1[(short)0]); System.Console.WriteLine(i1[(ushort)0]); i1[(int)0] = 0; i1[(uint)0] = 0; System.Console.WriteLine(i1[(long)0]); i1[(long)0] = 0; System.Console.WriteLine(i1[(ulong)0]); i1[(ulong)0] = 0; } } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); ValidateIndexerImplementation_201(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"1 2 3 4 5 6 7 71 8 81 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidateIndexerImplementation_201(m); }); } private static void ValidateIndexerImplementation_201(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var indexers = i1.GetMembers("this[]"); var p1 = (PropertySymbol)indexers[0]; var p2 = (PropertySymbol)indexers[1]; var p3 = (PropertySymbol)indexers[2]; var p4 = (PropertySymbol)indexers[3]; var p5 = (PropertySymbol)indexers[4]; var p6 = (PropertySymbol)indexers[5]; var p7 = (PropertySymbol)indexers[6]; var p8 = (PropertySymbol)indexers[7]; var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Same(p1, derived.FindImplementationForInterfaceMember(p1)); Assert.Same(p2, derived.FindImplementationForInterfaceMember(p2)); Assert.Same(p3, derived.FindImplementationForInterfaceMember(p3)); Assert.Same(p4, derived.FindImplementationForInterfaceMember(p4)); Assert.Same(p5, derived.FindImplementationForInterfaceMember(p5)); Assert.Same(p6, derived.FindImplementationForInterfaceMember(p6)); Assert.Same(p7, derived.FindImplementationForInterfaceMember(p7)); Assert.Same(p8, derived.FindImplementationForInterfaceMember(p8)); Assert.Same(p1.GetMethod, derived.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Same(p2.GetMethod, derived.FindImplementationForInterfaceMember(p2.GetMethod)); Assert.Same(p3.GetMethod, derived.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Same(p4.GetMethod, derived.FindImplementationForInterfaceMember(p4.GetMethod)); Assert.Same(p5.SetMethod, derived.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Same(p6.SetMethod, derived.FindImplementationForInterfaceMember(p6.SetMethod)); Assert.Same(p7.GetMethod, derived.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Same(p8.GetMethod, derived.FindImplementationForInterfaceMember(p8.GetMethod)); Assert.Same(p7.SetMethod, derived.FindImplementationForInterfaceMember(p7.SetMethod)); Assert.Same(p8.SetMethod, derived.FindImplementationForInterfaceMember(p8.SetMethod)); } [Fact] public void IndexerImplementation_202() { var source1 = @" interface I1 { int this[sbyte i] => 1; int this[byte i] => 2; int this[short i] { get => 3; } int this[ushort i] { get => 4; } int this[int i] { set => System.Console.WriteLine(5); } int this[uint i] { set => System.Console.WriteLine(6); } int this[long i] { get { return 7;} set {System.Console.WriteLine(71);} } int this[ulong i] { get { return 8;} set {System.Console.WriteLine(81);} } } class Base : Test { int this[sbyte i] => 10; int this[short i] { get => 30; } int this[int i] { set => System.Console.WriteLine(50); } int this[long i] { get { return 70;} set {} } } class Derived : Base, I1 { int this[byte i] => 20; int this[ushort i] { get => 40; } int this[uint i] { set => System.Console.WriteLine(60); } int this[ulong i] { get { return 80;} set {} } static void Main() { I1 i1 = new Derived(); System.Console.WriteLine(i1[(sbyte)0]); System.Console.WriteLine(i1[(byte)0]); System.Console.WriteLine(i1[(short)0]); System.Console.WriteLine(i1[(ushort)0]); i1[(int)0] = 0; i1[(uint)0] = 0; System.Console.WriteLine(i1[(long)0]); i1[(long)0] = 0; System.Console.WriteLine(i1[(ulong)0]); i1[(ulong)0] = 0; } } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); ValidateIndexerImplementation_201(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"1 2 3 4 5 6 7 71 8 81 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidateIndexerImplementation_201(m); }); } [Fact] public void IndexerImplementation_203() { var source1 = @" interface I1 { int this[sbyte i] => 1; int this[byte i] => 2; int this[short i] { get => 3; } int this[ushort i] { get => 4; } int this[int i] { set => System.Console.WriteLine(5); } int this[uint i] { set => System.Console.WriteLine(6); } int this[long i] { get { return 7;} set {} } int this[ulong i] { get { return 8;} set {} } } class Base : Test { int this[sbyte i] => 10; int this[short i] { get => 30; } int this[int i] { set => System.Console.WriteLine(50); } int this[long i] { get { return 70;} set {} } } class Derived : Base, I1 { int this[byte i] => 20; int this[ushort i] { get => 40; } int this[uint i] { set => System.Console.WriteLine(60); } int this[ulong i] { get { return 80;} set {} } static void Main() { I1 i1 = new Derived(); System.Console.WriteLine(i1[(sbyte)0]); System.Console.WriteLine(i1[(byte)0]); System.Console.WriteLine(i1[(short)0]); System.Console.WriteLine(i1[(ushort)0]); i1[(int)0] = 0; i1[(uint)0] = 0; System.Console.WriteLine(i1[(long)0]); i1[(long)0] = 0; System.Console.WriteLine(i1[(ulong)0]); i1[(ulong)0] = 0; } } class Test : I1 { int I1.this[sbyte i] => 100; int I1.this[byte i] => 200; int I1.this[short i] { get => 300; } int I1.this[ushort i] { get => 400; } int I1.this[int i] { set => System.Console.WriteLine(500); } int I1.this[uint i] { set => System.Console.WriteLine(600); } int I1.this[long i] { get { return 700;} set {System.Console.WriteLine(701);} } int I1.this[ulong i] { get { return 800;} set {System.Console.WriteLine(801);} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var indexers = i1.GetMembers("this[]"); var p1 = (PropertySymbol)indexers[0]; var p2 = (PropertySymbol)indexers[1]; var p3 = (PropertySymbol)indexers[2]; var p4 = (PropertySymbol)indexers[3]; var p5 = (PropertySymbol)indexers[4]; var p6 = (PropertySymbol)indexers[5]; var p7 = (PropertySymbol)indexers[6]; var p8 = (PropertySymbol)indexers[7]; var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); string name = m is PEModuleSymbol ? "Item" : "this"; Assert.Equal("System.Int32 Test.I1." + name + "[System.SByte i] { get; }", derived.FindImplementationForInterfaceMember(p1).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.Byte i] { get; }", derived.FindImplementationForInterfaceMember(p2).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.Int16 i] { get; }", derived.FindImplementationForInterfaceMember(p3).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.UInt16 i] { get; }", derived.FindImplementationForInterfaceMember(p4).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.Int32 i] { set; }", derived.FindImplementationForInterfaceMember(p5).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.UInt32 i] { set; }", derived.FindImplementationForInterfaceMember(p6).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.Int64 i] { get; set; }", derived.FindImplementationForInterfaceMember(p7).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1." + name + "[System.UInt64 i] { get; set; }", derived.FindImplementationForInterfaceMember(p8).ToTestDisplayString()); if (m is PEModuleSymbol) { Assert.Equal("System.Int32 Test.I1.get_Item(System.SByte i)", derived.FindImplementationForInterfaceMember(p1.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.get_Item(System.Byte i)", derived.FindImplementationForInterfaceMember(p2.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.get_Item(System.Int16 i)", derived.FindImplementationForInterfaceMember(p3.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.get_Item(System.UInt16 i)", derived.FindImplementationForInterfaceMember(p4.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.set_Item(System.Int32 i, System.Int32 value)", derived.FindImplementationForInterfaceMember(p5.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.set_Item(System.UInt32 i, System.Int32 value)", derived.FindImplementationForInterfaceMember(p6.SetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.get_Item(System.Int64 i)", derived.FindImplementationForInterfaceMember(p7.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.get_Item(System.UInt64 i)", derived.FindImplementationForInterfaceMember(p8.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.set_Item(System.Int64 i, System.Int32 value)", derived.FindImplementationForInterfaceMember(p7.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.set_Item(System.UInt64 i, System.Int32 value)", derived.FindImplementationForInterfaceMember(p8.SetMethod).ToTestDisplayString()); } else { Assert.Equal("System.Int32 Test.I1.this[System.SByte i].get", derived.FindImplementationForInterfaceMember(p1.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.this[System.Byte i].get", derived.FindImplementationForInterfaceMember(p2.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.this[System.Int16 i].get", derived.FindImplementationForInterfaceMember(p3.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.this[System.UInt16 i].get", derived.FindImplementationForInterfaceMember(p4.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.this[System.Int32 i].set", derived.FindImplementationForInterfaceMember(p5.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.this[System.UInt32 i].set", derived.FindImplementationForInterfaceMember(p6.SetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.this[System.Int64 i].get", derived.FindImplementationForInterfaceMember(p7.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.I1.this[System.UInt64 i].get", derived.FindImplementationForInterfaceMember(p8.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.this[System.Int64 i].set", derived.FindImplementationForInterfaceMember(p7.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.this[System.UInt64 i].set", derived.FindImplementationForInterfaceMember(p8.SetMethod).ToTestDisplayString()); } } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"100 200 300 400 500 600 700 701 800 801 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Fact] public void IndexerImplementation_204() { var source1 = @" interface I1 { int this[sbyte i] => 1; int this[byte i] => 2; int this[short i] { get => 3; } int this[ushort i] { get => 4; } int this[int i] { set => System.Console.WriteLine(5); } int this[uint i] { set => System.Console.WriteLine(6); } int this[long i] { get { return 7;} set {} } int this[ulong i] { get { return 8;} set {} } } class Base : Test { new int this[sbyte i] => 10; new int this[short i] { get => 30; } new int this[int i] { set => System.Console.WriteLine(50); } new int this[long i] { get { return 70;} set {} } } class Derived : Base, I1 { new int this[byte i] => 20; new int this[ushort i] { get => 40; } new int this[uint i] { set => System.Console.WriteLine(60); } new int this[ulong i] { get { return 80;} set {} } static void Main() { I1 i1 = new Derived(); System.Console.WriteLine(i1[(sbyte)0]); System.Console.WriteLine(i1[(byte)0]); System.Console.WriteLine(i1[(short)0]); System.Console.WriteLine(i1[(ushort)0]); i1[(int)0] = 0; i1[(uint)0] = 0; System.Console.WriteLine(i1[(long)0]); i1[(long)0] = 0; System.Console.WriteLine(i1[(ulong)0]); i1[(ulong)0] = 0; } } class Test : I1 { public int this[sbyte i] => 100; public int this[byte i] => 200; public int this[short i] { get => 300; } public int this[ushort i] { get => 400; } public int this[int i] { set => System.Console.WriteLine(500); } public int this[uint i] { set => System.Console.WriteLine(600); } public int this[long i] { get { return 700;} set {System.Console.WriteLine(701);} } public int this[ulong i] { get { return 800;} set {System.Console.WriteLine(801);} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var indexers = i1.GetMembers("this[]"); var p1 = (PropertySymbol)indexers[0]; var p2 = (PropertySymbol)indexers[1]; var p3 = (PropertySymbol)indexers[2]; var p4 = (PropertySymbol)indexers[3]; var p5 = (PropertySymbol)indexers[4]; var p6 = (PropertySymbol)indexers[5]; var p7 = (PropertySymbol)indexers[6]; var p8 = (PropertySymbol)indexers[7]; var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("System.Int32 Test.this[System.SByte i] { get; }", derived.FindImplementationForInterfaceMember(p1).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Byte i] { get; }", derived.FindImplementationForInterfaceMember(p2).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Int16 i] { get; }", derived.FindImplementationForInterfaceMember(p3).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.UInt16 i] { get; }", derived.FindImplementationForInterfaceMember(p4).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Int32 i] { set; }", derived.FindImplementationForInterfaceMember(p5).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.UInt32 i] { set; }", derived.FindImplementationForInterfaceMember(p6).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Int64 i] { get; set; }", derived.FindImplementationForInterfaceMember(p7).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.UInt64 i] { get; set; }", derived.FindImplementationForInterfaceMember(p8).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.SByte i].get", derived.FindImplementationForInterfaceMember(p1.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Byte i].get", derived.FindImplementationForInterfaceMember(p2.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Int16 i].get", derived.FindImplementationForInterfaceMember(p3.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.UInt16 i].get", derived.FindImplementationForInterfaceMember(p4.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.this[System.Int32 i].set", derived.FindImplementationForInterfaceMember(p5.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.this[System.UInt32 i].set", derived.FindImplementationForInterfaceMember(p6.SetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.Int64 i].get", derived.FindImplementationForInterfaceMember(p7.GetMethod).ToTestDisplayString()); Assert.Equal("System.Int32 Test.this[System.UInt64 i].get", derived.FindImplementationForInterfaceMember(p8.GetMethod).ToTestDisplayString()); Assert.Equal("void Test.this[System.Int64 i].set", derived.FindImplementationForInterfaceMember(p7.SetMethod).ToTestDisplayString()); Assert.Equal("void Test.this[System.UInt64 i].set", derived.FindImplementationForInterfaceMember(p8.SetMethod).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"100 200 300 400 500 600 700 701 800 801 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Fact] public void IndexerImplementation_501() { var source1 = @" public interface I1 { int this[sbyte i] => 1; int this[short i] { get => 3; } int this[int i] { set => System.Console.WriteLine(5); } int this[long i] { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular, skipUsesIsNullable: true); Assert.False(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,26): error CS8501: Target runtime doesn't support default interface implementation. // int this[sbyte i] => 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "1").WithLocation(4, 26), // (6,7): error CS8501: Target runtime doesn't support default interface implementation. // { get => 3; } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(6, 7), // (8,7): error CS8501: Target runtime doesn't support default interface implementation. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(8, 7), // (11,9): error CS8501: Target runtime doesn't support default interface implementation. // get { return 7;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(11, 9), // (12,9): error CS8501: Target runtime doesn't support default interface implementation. // set {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(12, 9) ); ValidateIndexerImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.this[long].set' cannot implement interface member 'I1.this[long].set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].set", "I1.this[long].set", "Test2"), // (2,15): error CS8502: 'I1.this[sbyte].get' cannot implement interface member 'I1.this[sbyte].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[sbyte].get", "I1.this[sbyte].get", "Test2"), // (2,15): error CS8502: 'I1.this[short].get' cannot implement interface member 'I1.this[short].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[short].get", "I1.this[short].get", "Test2"), // (2,15): error CS8502: 'I1.this[int].set' cannot implement interface member 'I1.this[int].set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[int].set", "I1.this[int].set", "Test2"), // (2,15): error CS8502: 'I1.this[long].get' cannot implement interface member 'I1.this[long].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].get", "I1.this[long].get", "Test2") ); ValidateIndexerImplementation_501(compilation3.SourceModule, "Test2"); } private static void ValidateIndexerImplementation_501(ModuleSymbol m, string typeName) { var derived = m.GlobalNamespace.GetTypeMember(typeName); var i1 = derived.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.ToTestDisplayString()); var indexers = i1.GetMembers("this[]"); var p1 = (PropertySymbol)indexers[0]; var p3 = (PropertySymbol)indexers[1]; var p5 = (PropertySymbol)indexers[2]; var p7 = (PropertySymbol)indexers[3]; Assert.True(p1.IsVirtual); Assert.True(p3.IsVirtual); Assert.True(p5.IsVirtual); Assert.True(p7.IsVirtual); Assert.False(p1.IsAbstract); Assert.False(p3.IsAbstract); Assert.False(p5.IsAbstract); Assert.False(p7.IsAbstract); Assert.Same(p1, derived.FindImplementationForInterfaceMember(p1)); Assert.Same(p3, derived.FindImplementationForInterfaceMember(p3)); Assert.Same(p5, derived.FindImplementationForInterfaceMember(p5)); Assert.Same(p7, derived.FindImplementationForInterfaceMember(p7)); Assert.True(p1.GetMethod.IsVirtual); Assert.True(p3.GetMethod.IsVirtual); Assert.True(p5.SetMethod.IsVirtual); Assert.True(p7.GetMethod.IsVirtual); Assert.True(p7.SetMethod.IsVirtual); Assert.True(p1.GetMethod.IsMetadataVirtual()); Assert.True(p3.GetMethod.IsMetadataVirtual()); Assert.True(p5.SetMethod.IsMetadataVirtual()); Assert.True(p7.GetMethod.IsMetadataVirtual()); Assert.True(p7.SetMethod.IsMetadataVirtual()); Assert.False(p1.GetMethod.IsAbstract); Assert.False(p3.GetMethod.IsAbstract); Assert.False(p5.SetMethod.IsAbstract); Assert.False(p7.GetMethod.IsAbstract); Assert.False(p7.SetMethod.IsAbstract); Assert.Same(p1.GetMethod, derived.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Same(p3.GetMethod, derived.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Same(p5.SetMethod, derived.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Same(p7.GetMethod, derived.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Same(p7.SetMethod, derived.FindImplementationForInterfaceMember(p7.SetMethod)); } [Fact] public void IndexerImplementation_502() { var source1 = @" public interface I1 { int this[sbyte i] => 1; int this[short i] { get => 3; } int this[int i] { set => System.Console.WriteLine(5); } int this[long i] { get { return 7;} set {} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.this[short].get' cannot implement interface member 'I1.this[short].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[short].get", "I1.this[short].get", "Test2"), // (2,15): error CS8502: 'I1.this[int].set' cannot implement interface member 'I1.this[int].set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[int].set", "I1.this[int].set", "Test2"), // (2,15): error CS8502: 'I1.this[long].get' cannot implement interface member 'I1.this[long].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].get", "I1.this[long].get", "Test2"), // (2,15): error CS8502: 'I1.this[long].set' cannot implement interface member 'I1.this[long].set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].set", "I1.this[long].set", "Test2"), // (2,15): error CS8502: 'I1.this[sbyte].get' cannot implement interface member 'I1.this[sbyte].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[sbyte].get", "I1.this[sbyte].get", "Test2") ); ValidateIndexerImplementation_501(compilation3.SourceModule, "Test2"); } [Fact] public void IndexerImplementation_503() { var source1 = @" public interface I1 { int this[sbyte i] => 1; int this[short i] { get => 3; } int this[int i] { set => System.Console.WriteLine(5); } int this[long i] { get { return 7;} set {} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" public interface I2 { void M2(); } class Test2 : I2 { public void M2() {} } "; var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var test2 = compilation3.GetTypeByMetadataName("Test2"); var i1 = compilation3.GetTypeByMetadataName("I1"); Assert.Equal("I1", i1.ToTestDisplayString()); var indexers = i1.GetMembers("this[]"); var p1 = (PropertySymbol)indexers[0]; var p3 = (PropertySymbol)indexers[1]; var p5 = (PropertySymbol)indexers[2]; var p7 = (PropertySymbol)indexers[3]; Assert.Null(test2.FindImplementationForInterfaceMember(p1)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p7)); Assert.Null(test2.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p3.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p5.SetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p7.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p7.SetMethod)); compilation3.VerifyDiagnostics(); } [Fact] public void IndexerImplementation_601() { var source1 = @" public interface I1 { int this[sbyte i] => 1; int this[short i] { get => 3; } int this[int i] { set => System.Console.WriteLine(5); } int this[long i] { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); Assert.False(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,26): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int this[sbyte i] => 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "1").WithArguments("default interface implementation", "8.0").WithLocation(4, 26), // (4,26): error CS8701: Target runtime doesn't support default interface implementation. // int this[sbyte i] => 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "1").WithLocation(4, 26), // (6,7): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // { get => 3; } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(6, 7), // (6,7): error CS8701: Target runtime doesn't support default interface implementation. // { get => 3; } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(6, 7), // (8,7): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(8, 7), // (8,7): error CS8701: Target runtime doesn't support default interface implementation. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(8, 7), // (11,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // get { return 7;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(11, 9), // (11,9): error CS8701: Target runtime doesn't support default interface implementation. // get { return 7;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(11, 9), // (12,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // set {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(12, 9), // (12,9): error CS8701: Target runtime doesn't support default interface implementation. // set {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(12, 9) ); ValidateIndexerImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.this[long].set' cannot implement interface member 'I1.this[long].set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].set", "I1.this[long].set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.this[long].set' cannot implement interface member 'I1.this[long].set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].set", "I1.this[long].set", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[sbyte].get' cannot implement interface member 'I1.this[sbyte].get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[sbyte].get", "I1.this[sbyte].get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.this[sbyte].get' cannot implement interface member 'I1.this[sbyte].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[sbyte].get", "I1.this[sbyte].get", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[short].get' cannot implement interface member 'I1.this[short].get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[short].get", "I1.this[short].get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.this[short].get' cannot implement interface member 'I1.this[short].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[short].get", "I1.this[short].get", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[int].set' cannot implement interface member 'I1.this[int].set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[int].set", "I1.this[int].set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.this[int].set' cannot implement interface member 'I1.this[int].set' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[int].set", "I1.this[int].set", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[long].get' cannot implement interface member 'I1.this[long].get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].get", "I1.this[long].get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.this[long].get' cannot implement interface member 'I1.this[long].get' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].get", "I1.this[long].get", "Test2").WithLocation(2, 15) ); ValidateIndexerImplementation_501(compilation3.SourceModule, "Test2"); } [Fact] public void IndexerImplementation_701() { var source1 = @" public interface I1 { int this[sbyte i] => 1; int this[short i] { get => 3; } int this[int i] { set => System.Console.WriteLine(5); } int this[long i] { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,26): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int this[sbyte i] => 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "1").WithArguments("default interface implementation", "8.0").WithLocation(4, 26), // (6,7): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // { get => 3; } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(6, 7), // (8,7): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(8, 7), // (11,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // get { return 7;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(11, 9), // (12,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // set {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(12, 9) ); ValidateIndexerImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateIndexerImplementation_501(compilation2.SourceModule, "Test2"); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => { var test2Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test2"); Assert.Equal("I1", test2Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidateIndexerImplementation_501(m, "Test2"); }); var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.this[long].set' cannot implement interface member 'I1.this[long].set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].set", "I1.this[long].set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[sbyte].get' cannot implement interface member 'I1.this[sbyte].get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[sbyte].get", "I1.this[sbyte].get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[short].get' cannot implement interface member 'I1.this[short].get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[short].get", "I1.this[short].get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[int].set' cannot implement interface member 'I1.this[int].set' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[int].set", "I1.this[int].set", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.this[long].get' cannot implement interface member 'I1.this[long].get' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.this[long].get", "I1.this[long].get", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15) ); ValidateIndexerImplementation_501(compilation3.SourceModule, "Test2"); } [Fact] public void IndexerImplementation_901() { var source1 = @" public interface I1 { static int this[sbyte i] => 1; static int this[short i] { get => 3; } static int this[int i] { set => System.Console.WriteLine(5); } static int this[long i] { get { return 7;} set {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS0106: The modifier 'static' is not valid for this item // static int this[sbyte i] => 1; Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(4, 16), // (4,33): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static int this[sbyte i] => 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "1").WithArguments("default interface implementation", "8.0").WithLocation(4, 33), // (5,16): error CS0106: The modifier 'static' is not valid for this item // static int this[short i] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(5, 16), // (6,7): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // { get => 3; } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(6, 7), // (7,16): error CS0106: The modifier 'static' is not valid for this item // static int this[int i] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 16), // (8,7): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // { set => System.Console.WriteLine(5); } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(8, 7), // (9,16): error CS0106: The modifier 'static' is not valid for this item // static int this[long i] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(9, 16), // (11,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // get { return 7;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(11, 9), // (12,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // set {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(12, 9) ); ValidateIndexerImplementation_501(compilation1.SourceModule, "Test1"); } [Theory] [CombinatorialData] public void EventImplementation_101(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { add { System.Console.WriteLine(""add E1""); } } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (4,25): error CS0065: 'I1.E1': event property must have both add and remove accessors // event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 25 + declModifiers.Length) }, haveAdd: true, haveRemove: false, isStatic: isStatic); } private void ValidateEventImplementation_101(string source1, DiagnosticDescription[] expected, bool haveAdd, bool haveRemove, bool isStatic = false) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics(expected); ValidateEventImplementationTest1_101(compilation1.SourceModule, haveAdd, haveRemove, isStatic); var source2 = @" class Test2 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate2(ModuleSymbol m) { ValidateEventImplementationTest2_101(m, haveAdd, haveRemove); } Validate2(compilation2.SourceModule); compilation2.VerifyDiagnostics(); Assert.NotEmpty(expected); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate2); } private static void ValidateEventImplementationTest1_101(ModuleSymbol m, bool haveAdd, bool haveRemove, bool isStatic = false) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var e1 = i1.GetMember<EventSymbol>("E1"); var addE1 = e1.AddMethod; var rmvE1 = e1.RemoveMethod; if (haveAdd) { ValidateAccessor(addE1); } else { Assert.Null(addE1); } if (haveRemove) { ValidateAccessor(rmvE1); } else { Assert.Null(rmvE1); } void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.Equal(isStatic, accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } Assert.False(e1.IsAbstract); Assert.True(e1.IsVirtual); Assert.False(e1.IsSealed); Assert.Equal(isStatic, e1.IsStatic); Assert.False(e1.IsExtern); Assert.False(e1.IsOverride); Assert.Equal(Accessibility.Public, e1.DeclaredAccessibility); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); if (m is PEModuleSymbol peModule) { int rva; if (haveAdd) { peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)addE1).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } if (haveRemove) { peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)rmvE1).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } } var test1 = m.GlobalNamespace.GetTypeMember("Test1"); Assert.Equal("I1", test1.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Assert.Same(e1, test1.FindImplementationForInterfaceMember(e1)); if (haveAdd) { Assert.Same(addE1, test1.FindImplementationForInterfaceMember(addE1)); } if (haveRemove) { Assert.Same(rmvE1, test1.FindImplementationForInterfaceMember(rmvE1)); } } private static void ValidateEventImplementationTest2_101(ModuleSymbol m, bool haveAdd, bool haveRemove) { var test2 = m.GlobalNamespace.GetTypeMember("Test2"); Assert.Equal("I1", test2.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); var e1 = test2.InterfacesNoUseSiteDiagnostics().Single().GetMember<EventSymbol>("E1"); Assert.Same(e1, test2.FindImplementationForInterfaceMember(e1)); if (haveAdd) { var addP1 = e1.AddMethod; Assert.Same(addP1, test2.FindImplementationForInterfaceMember(addP1)); } if (haveRemove) { var rmvP1 = e1.RemoveMethod; Assert.Same(rmvP1, test2.FindImplementationForInterfaceMember(rmvP1)); } } [Theory] [CombinatorialData] public void EventImplementation_102(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { add => System.Console.WriteLine(""add E1""); remove => System.Console.WriteLine(""remove E1""); } } class Test1 : I1 { "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Test1(); "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" i1.E1 += null; i1.E1 -= null; } } "; ValidateEventImplementation_102(source1, isStatic); } private void ValidateEventImplementation_102(string source1, bool isStatic = false) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { ValidateEventImplementationTest1_101(m, haveAdd: true, haveRemove: true, isStatic: isStatic); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"add E1 remove E1 ", verify: Verify(isStatic), symbolValidator: Validate1); var source2 = @" class Test2 : I1 { "; if (!isStatic) { source2 += @" static void Main() { I1 i1 = new Test2(); "; } else { source2 += @" static void Main() { Test<Test2>(); } static void Test<i1>() where i1 : I1 { "; } source2 += @" i1.E1 += null; i1.E1 -= null; } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate2(ModuleSymbol m) { ValidateEventImplementationTest2_101(m, haveAdd: true, haveRemove: true); } Validate2(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic) ? null : @"add E1 remove E1 ", verify: Verify(isStatic), symbolValidator: Validate2); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate2(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic) ? null : @"add E1 remove E1 ", verify: Verify(isStatic), symbolValidator: Validate2); } [Theory] [CombinatorialData] public void EventImplementation_103(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { remove { System.Console.WriteLine(""remove E1""); } } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (4,25): error CS0065: 'I1.E1': event property must have both add and remove accessors // event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 25 + declModifiers.Length) }, haveAdd: false, haveRemove: true, isStatic: isStatic); } [Theory] [CombinatorialData] public void EventImplementation_104(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { add; } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (6,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 12), // (4,25): error CS0065: 'I1.E1': event property must have both add and remove accessors // event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 25 + declModifiers.Length) }, haveAdd: true, haveRemove: false, isStatic: isStatic); } [Theory] [CombinatorialData] public void EventImplementation_105(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { remove; } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (6,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 15), // (4,25): error CS0065: 'I1.E1': event property must have both add and remove accessors // event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 25 + declModifiers.Length) }, haveAdd: false, haveRemove: true, isStatic: isStatic); } [Fact] public void EventImplementation_106() { var source1 = @" public interface I1 { event System.Action E1 { } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (4,25): error CS0065: 'I1.E1': event property must have both add and remove accessors // event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 25) }, haveAdd: false, haveRemove: false); } [Theory] [CombinatorialData] public void EventImplementation_107(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { add; remove; } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (6,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 12), // (7,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(7, 15) }, haveAdd: true, haveRemove: true, isStatic: isStatic); } [Theory] [CombinatorialData] public void EventImplementation_108(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { get; set; } => 0; } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (8,7): error CS1519: Invalid token '=>' in class, record, struct, or interface member declaration // } => 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=>").WithArguments("=>").WithLocation(8, 7), // (6,9): error CS1055: An add or remove accessor expected // get; Diagnostic(ErrorCode.ERR_AddOrRemoveExpected, "get").WithLocation(6, 9), // (7,9): error CS1055: An add or remove accessor expected // set; Diagnostic(ErrorCode.ERR_AddOrRemoveExpected, "set").WithLocation(7, 9), // (4,25): error CS0065: 'I1.E1': event property must have both add and remove accessors // event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1") }, haveAdd: false, haveRemove: false, isStatic: isStatic); } [Theory] [CombinatorialData] public void EventImplementation_109(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { add => throw null; remove; } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (7,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(7, 15) }, haveAdd: true, haveRemove: true, isStatic: isStatic); } [Theory] [CombinatorialData] public void EventImplementation_110(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E1 { add; remove => throw null; } } class Test1 : I1 {} "; ValidateEventImplementation_101(source1, new[] { // (6,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 12) }, haveAdd: true, haveRemove: true, isStatic: isStatic); } [Theory] [CombinatorialData] public void EventImplementation_201(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"event System.Action E7 { add {System.Console.WriteLine(""add E7"");} remove {System.Console.WriteLine(""remove E7"");} } " + declModifiers + @"event System.Action E8 { add {System.Console.WriteLine(""add E8"");} remove {System.Console.WriteLine(""remove E8"");} } } class Base { " + implModifiers + @"event System.Action E7; } class Derived : Base, I1 { " + implModifiers + @"event System.Action E8 { add {} remove {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" i1.E7 += null; i1.E7 -= null; i1.E8 += null; i1.E8 -= null; } } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,25): warning CS0067: The event 'Base.E7' is never used // event System.Action E7; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E7").WithArguments("Base.E7").WithLocation(10, 25 + implModifiers.Length) ); ValidateEventImplementation_201(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : @"add E7 remove E7 add E8 remove E8", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidateEventImplementation_201(m); }); } private static void ValidateEventImplementation_201(ModuleSymbol m) { var e7 = m.GlobalNamespace.GetMember<EventSymbol>("I1.E7"); var e8 = m.GlobalNamespace.GetMember<EventSymbol>("I1.E8"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Same(e7, derived.FindImplementationForInterfaceMember(e7)); Assert.Same(e8, derived.FindImplementationForInterfaceMember(e8)); Assert.Same(e7.AddMethod, derived.FindImplementationForInterfaceMember(e7.AddMethod)); Assert.Same(e8.AddMethod, derived.FindImplementationForInterfaceMember(e8.AddMethod)); Assert.Same(e7.RemoveMethod, derived.FindImplementationForInterfaceMember(e7.RemoveMethod)); Assert.Same(e8.RemoveMethod, derived.FindImplementationForInterfaceMember(e8.RemoveMethod)); } [Theory] [CombinatorialData] public void EventImplementation_202(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"event System.Action E7 { add {System.Console.WriteLine(""add E7"");} remove {System.Console.WriteLine(""remove E7"");} } " + declModifiers + @"event System.Action E8 { add {System.Console.WriteLine(""add E8"");} remove {System.Console.WriteLine(""remove E8"");} } } class Base : Test { " + implModifiers + @"event System.Action E7; } class Derived : Base, I1 { " + implModifiers + @"event System.Action E8 { add {} remove {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" i1.E7 += null; i1.E7 -= null; i1.E8 += null; i1.E8 -= null; } } class Test : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,25): warning CS0067: The event 'Base.E7' is never used // event System.Action E7; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E7").WithArguments("Base.E7").WithLocation(10, 25 + implModifiers.Length) ); ValidateEventImplementation_201(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"add E7 remove E7 add E8 remove E8", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidateEventImplementation_201(m); }); } [Theory] [CombinatorialData] public void EventImplementation_203(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"event System.Action E7 { add {} remove {} } " + declModifiers + @"event System.Action E8 { add {} remove {} } } class Base : Test { " + implModifiers + @"event System.Action E7; } class Derived : Base, I1 { " + implModifiers + @"event System.Action E8 { add {} remove {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" i1.E7 += null; i1.E7 -= null; i1.E8 += null; i1.E8 -= null; } } class Test : I1 { " + implModifiers + @"event System.Action I1.E7 { add {System.Console.WriteLine(""add E7"");} remove {System.Console.WriteLine(""remove E7"");} } " + implModifiers + @"event System.Action I1.E8 { add {System.Console.WriteLine(""add E8"");} remove {System.Console.WriteLine(""remove E8"");} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,25): warning CS0067: The event 'Base.E7' is never used // event System.Action E7; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E7").WithArguments("Base.E7").WithLocation(10, 25 + implModifiers.Length) ); void Validate(ModuleSymbol m) { var e7 = m.GlobalNamespace.GetMember<EventSymbol>("I1.E7"); var e8 = m.GlobalNamespace.GetMember<EventSymbol>("I1.E8"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("event System.Action Test.I1.E7", derived.FindImplementationForInterfaceMember(e7).ToTestDisplayString()); Assert.Equal("event System.Action Test.I1.E8", derived.FindImplementationForInterfaceMember(e8).ToTestDisplayString()); Assert.Equal("void Test.I1.E7.add", derived.FindImplementationForInterfaceMember(e7.AddMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.E8.add", derived.FindImplementationForInterfaceMember(e8.AddMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.E7.remove", derived.FindImplementationForInterfaceMember(e7.RemoveMethod).ToTestDisplayString()); Assert.Equal("void Test.I1.E8.remove", derived.FindImplementationForInterfaceMember(e8.RemoveMethod).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"add E7 remove E7 add E8 remove E8", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void EventImplementation_204(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" interface I1 { " + declModifiers + @"event System.Action E7 { add {} remove {} } " + declModifiers + @"event System.Action E8 { add {} remove {} } } class Base : Test { " + implModifiers + @"new event System.Action E7; } class Derived : Base, I1 { " + implModifiers + @"new event System.Action E8 { add {} remove {} } "; if (!isStatic) { source1 += @" static void Main() { I1 i1 = new Derived(); "; } else { source1 += @" static void Main() { Test<Derived>(); } static void Test<i1>() where i1 : I1 { "; } source1 += @" i1.E7 += null; i1.E7 -= null; i1.E8 += null; i1.E8 -= null; } } class Test : I1 { " + implModifiers + @"public event System.Action E7 { add {System.Console.WriteLine(""add E7"");} remove {System.Console.WriteLine(""remove E7"");} } " + implModifiers + @"public event System.Action E8 { add {System.Console.WriteLine(""add E8"");} remove {System.Console.WriteLine(""remove E8"");} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,29): warning CS0067: The event 'Base.E7' is never used // new event System.Action E7; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E7").WithArguments("Base.E7").WithLocation(10, 29 + implModifiers.Length) ); void Validate(ModuleSymbol m) { var e7 = m.GlobalNamespace.GetMember<EventSymbol>("I1.E7"); var e8 = m.GlobalNamespace.GetMember<EventSymbol>("I1.E8"); var derived = m.ContainingAssembly.GetTypeByMetadataName("Derived"); Assert.Equal("event System.Action Test.E7", derived.FindImplementationForInterfaceMember(e7).ToTestDisplayString()); Assert.Equal("event System.Action Test.E8", derived.FindImplementationForInterfaceMember(e8).ToTestDisplayString()); Assert.Equal("void Test.E7.add", derived.FindImplementationForInterfaceMember(e7.AddMethod).ToTestDisplayString()); Assert.Equal("void Test.E8.add", derived.FindImplementationForInterfaceMember(e8.AddMethod).ToTestDisplayString()); Assert.Equal("void Test.E7.remove", derived.FindImplementationForInterfaceMember(e7.RemoveMethod).ToTestDisplayString()); Assert.Equal("void Test.E8.remove", derived.FindImplementationForInterfaceMember(e8.RemoveMethod).ToTestDisplayString()); } Validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, hasImplementationOfVirtualInDerivedType: true) ? null : @"add E7 remove E7 add E8 remove E8", verify: Verify(isStatic), symbolValidator: (m) => { var derivedResult = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Derived"); Assert.Equal("I1", derivedResult.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); Validate(m); }); } [Theory] [CombinatorialData] public void EventImplementation_501(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E7 { add {} remove {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); if (!isStatic) { compilation1.VerifyDiagnostics( // (6,9): error CS8501: Target runtime doesn't support default interface implementation. // add {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(6, 9), // (7,9): error CS8501: Target runtime doesn't support default interface implementation. // remove {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(7, 9) ); } else { compilation1.VerifyDiagnostics( // (6,9): error CS8919: Target runtime doesn't support static abstract members in interfaces. // add {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "add").WithLocation(6, 9), // (7,9): error CS8919: Target runtime doesn't support static abstract members in interfaces. // remove {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "remove").WithLocation(7, 9) ); } ValidateEventImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8929: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2").WithLocation(2, 15) ); } ValidateEventImplementation_501(compilation3.SourceModule, "Test2"); } private static void ValidateEventImplementation_501(ModuleSymbol m, string typeName) { var derived = m.GlobalNamespace.GetTypeMember(typeName); var i1 = derived.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.ToTestDisplayString()); var e7 = i1.GetMember<EventSymbol>("E7"); Assert.True(e7.IsVirtual); Assert.False(e7.IsAbstract); Assert.Same(e7, derived.FindImplementationForInterfaceMember(e7)); Assert.True(e7.AddMethod.IsVirtual); Assert.True(e7.RemoveMethod.IsVirtual); Assert.True(e7.AddMethod.IsMetadataVirtual()); Assert.True(e7.RemoveMethod.IsMetadataVirtual()); Assert.False(e7.AddMethod.IsAbstract); Assert.False(e7.RemoveMethod.IsAbstract); Assert.Same(e7.AddMethod, derived.FindImplementationForInterfaceMember(e7.AddMethod)); Assert.Same(e7.RemoveMethod, derived.FindImplementationForInterfaceMember(e7.RemoveMethod)); } [Theory] [CombinatorialData] public void EventImplementation_502(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E7 { add {} remove {} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8502: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2").WithLocation(2, 15), // (2,15): error CS8502: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8929: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2").WithLocation(2, 15), // (2,15): error CS8929: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2").WithLocation(2, 15) ); } ValidateEventImplementation_501(compilation3.SourceModule, "Test2"); } [Theory] [CombinatorialData] public void EventImplementation_503(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E7 { add {} remove {} } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" public interface I2 { void M2(); } class Test2 : I2 { public void M2() {} } "; var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); var test2 = compilation3.GetTypeByMetadataName("Test2"); var i1 = compilation3.GetTypeByMetadataName("I1"); Assert.Equal("I1", i1.ToTestDisplayString()); var e7 = i1.GetMember<EventSymbol>("E7"); Assert.Null(test2.FindImplementationForInterfaceMember(e7)); Assert.Null(test2.FindImplementationForInterfaceMember(e7.AddMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(e7.RemoveMethod)); compilation3.VerifyDiagnostics(); } [Fact] public void EventImplementation_601() { { var source1 = @" public interface I1 { event System.Action E7 { add {} remove {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true); Assert.False(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (6,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // add {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(6, 9), // (6,9): error CS8701: Target runtime doesn't support default interface implementation. // add {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(6, 9), // (7,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // remove {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(7, 9), // (7,9): error CS8701: Target runtime doesn't support default interface implementation. // remove {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(7, 9) ); ValidateEventImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular7_3); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2").WithLocation(2, 15), // (2,15): error CS8506: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8502: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because the target runtime doesn't support default interface implementation. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2").WithLocation(2, 15) ); ValidateEventImplementation_501(compilation3.SourceModule, "Test2"); } { var source1 = @" public interface I1 { static virtual event System.Action E7 { add {} remove {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.Regular10, skipUsesIsNullable: true); compilation1.VerifyDiagnostics( // (4,40): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual event System.Action E7 Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "E7").WithArguments("virtual", "10.0", "11.0").WithLocation(4, 40), // (6,9): error CS8919: Target runtime doesn't support static abstract members in interfaces. // add {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "add").WithLocation(6, 9), // (7,9): error CS8919: Target runtime doesn't support static abstract members in interfaces. // remove {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "remove").WithLocation(7, 9) ); ValidateEventImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.Regular10); compilation3.VerifyDiagnostics( // (2,15): error CS8706: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2").WithLocation(2, 15), // (2,15): error CS8706: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8929: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because the target runtime doesn't support static abstract members in interfaces. // class Test2 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2").WithLocation(2, 15) ); ValidateEventImplementation_501(compilation3.SourceModule, "Test2"); } } [Theory] [CombinatorialData] public void EventImplementation_701(bool isStatic) { string declModifiers = isStatic ? "static virtual " : ""; var source1 = @" public interface I1 { " + declModifiers + @"event System.Action E7 { add {} remove {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (!isStatic) { compilation1.VerifyDiagnostics( // (6,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // add {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(6, 9), // (7,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // remove {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(7, 9) ); } else { compilation1.VerifyDiagnostics( // (4,40): error CS8703: The modifier 'virtual' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static virtual event System.Action E7 Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "E7").WithArguments("virtual", "10.0", "11.0").WithLocation(4, 40) ); } ValidateEventImplementation_501(compilation1.SourceModule, "Test1"); var source2 = @" class Test2 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateEventImplementation_501(compilation2.SourceModule, "Test2"); CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: (m) => { var test2Result = (PENamedTypeSymbol)m.GlobalNamespace.GetTypeMember("Test2"); Assert.Equal("I1", test2Result.InterfacesNoUseSiteDiagnostics().Single().ToTestDisplayString()); ValidateEventImplementation_501(m, "Test2"); }); var compilation3 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (!isStatic) { compilation3.VerifyDiagnostics( // (2,15): error CS8506: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15), // (2,15): error CS8506: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2", "default interface implementation", "7.3", "8.0").WithLocation(2, 15) ); } else { compilation3.VerifyDiagnostics( // (2,15): error CS8706: 'I1.E7.add' cannot implement interface member 'I1.E7.add' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.add", "I1.E7.add", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15), // (2,15): error CS8706: 'I1.E7.remove' cannot implement interface member 'I1.E7.remove' in type 'Test2' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test2 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.E7.remove", "I1.E7.remove", "Test2", "static abstract members in interfaces", "10.0", "11.0").WithLocation(2, 15) ); } ValidateEventImplementation_501(compilation3.SourceModule, "Test2"); } [Fact] public void EventImplementation_901() { var source1 = @" public interface I1 { static event System.Action E7 { add {} remove {} } } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,32): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static event System.Action E7 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "E7").WithArguments("default interface implementation", "8.0").WithLocation(4, 32) ); var derived = compilation1.GlobalNamespace.GetTypeMember("Test1"); var i1 = derived.InterfacesNoUseSiteDiagnostics().Single(); Assert.Equal("I1", i1.ToTestDisplayString()); var e7 = i1.GetMember<EventSymbol>("E7"); Assert.False(e7.IsVirtual); Assert.False(e7.IsAbstract); Assert.True(e7.IsStatic); Assert.Null(derived.FindImplementationForInterfaceMember(e7)); Assert.False(e7.AddMethod.IsVirtual); Assert.False(e7.RemoveMethod.IsVirtual); Assert.False(e7.AddMethod.IsMetadataVirtual()); Assert.False(e7.RemoveMethod.IsMetadataVirtual()); Assert.False(e7.AddMethod.IsAbstract); Assert.False(e7.RemoveMethod.IsAbstract); Assert.True(e7.AddMethod.IsStatic); Assert.True(e7.RemoveMethod.IsStatic); Assert.Null(derived.FindImplementationForInterfaceMember(e7.AddMethod)); Assert.Null(derived.FindImplementationForInterfaceMember(e7.RemoveMethod)); } [Fact] public void BaseIsNotAllowed_01() { var source1 = @" public interface I1 { void M1() { base.GetHashCode(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (6,9): error CS0174: A base class is required for a 'base' reference // base.GetHashCode(); Diagnostic(ErrorCode.ERR_NoBaseClass, "base").WithLocation(6, 9) ); } [Fact] public void ThisIsAllowed_01() { var source1 = @" public interface I1 { void M1() { System.Console.WriteLine(""I1.M1""); } int P1 { get { System.Console.WriteLine(""I1.get_P1""); return 0; } set => System.Console.WriteLine(""I1.set_P1""); } event System.Action E1 { add => System.Console.WriteLine(""I1.add_E1""); remove => System.Console.WriteLine(""I1.remove_E1""); } } public interface I2 : I1 { void M2() { System.Console.WriteLine(""I2.M2""); System.Console.WriteLine(this.GetHashCode()); this.M1(); this.P1 = this.P1; this.E1 += null; this.E1 -= null; this.M3(); this.P3 = this.P3; this.E3 += null; this.E3 -= null; } int P2 { get { System.Console.WriteLine(""I2.get_P2""); System.Console.WriteLine(this.GetHashCode()); this.M1(); this.P1 = this.P1; this.E1 += null; this.E1 -= null; this.M3(); this.P3 = this.P3; this.E3 += null; this.E3 -= null; return 0; } set { System.Console.WriteLine(""I2.set_P2""); System.Console.WriteLine(this.GetHashCode()); this.M1(); this.P1 = this.P1; this.E1 += null; this.E1 -= null; this.M3(); this.P3 = this.P3; this.E3 += null; this.E3 -= null; } } event System.Action E2 { add { System.Console.WriteLine(""I2.add_E2""); System.Console.WriteLine(this.GetHashCode()); this.M1(); this.P1 = this.P1; this.E1 += null; this.E1 -= null; this.M3(); this.P3 = this.P3; this.E3 += null; this.E3 -= null; } remove { System.Console.WriteLine(""I2.remove_E2""); System.Console.WriteLine(this.GetHashCode()); this.M1(); this.P1 = this.P1; this.E1 += null; this.E1 -= null; this.M3(); this.P3 = this.P3; this.E3 += null; this.E3 -= null; } } void M3() { System.Console.WriteLine(""I2.M3""); } int P3 { get { System.Console.WriteLine(""I2.get_P3""); return 0; } set => System.Console.WriteLine(""I2.set_P3""); } event System.Action E3 { add => System.Console.WriteLine(""I2.add_E3""); remove => System.Console.WriteLine(""I2.remove_E3""); } } class Test1 : I2 { static void Main() { I2 x = new Test1(); x.M2(); x.P2 = x.P2; x.E2 += null; x.E2 -= null; } public override int GetHashCode() { return 123; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"I2.M2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.get_P2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.set_P2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.add_E2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.remove_E2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 ", verify: VerifyOnMonoOrCoreClr); } [Fact] public void ThisIsAllowed_02() { var source1 = @" public interface I1 { public int F1; } public interface I2 : I1 { void M2() { this.F1 = this.F2; } int P2 { get { this.F1 = this.F2; return 0; } set { this.F1 = this.F2; } } event System.Action E2 { add { this.F1 = this.F2; } remove { this.F1 = this.F2; } } public int F2; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS0525: Interfaces cannot contain fields // public int F1; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16), // (39,16): error CS0525: Interfaces cannot contain fields // public int F2; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F2").WithLocation(39, 16) ); } [Fact] public void ImplicitThisIsAllowed_01() { var source1 = @" public interface I1 { void M1() { System.Console.WriteLine(""I1.M1""); } int P1 { get { System.Console.WriteLine(""I1.get_P1""); return 0; } set => System.Console.WriteLine(""I1.set_P1""); } event System.Action E1 { add => System.Console.WriteLine(""I1.add_E1""); remove => System.Console.WriteLine(""I1.remove_E1""); } } public interface I2 : I1 { void M2() { System.Console.WriteLine(""I2.M2""); System.Console.WriteLine(GetHashCode()); M1(); P1 = P1; E1 += null; E1 -= null; M3(); P3 = P3; E3 += null; E3 -= null; } int P2 { get { System.Console.WriteLine(""I2.get_P2""); System.Console.WriteLine(GetHashCode()); M1(); P1 = P1; E1 += null; E1 -= null; M3(); P3 = P3; E3 += null; E3 -= null; return 0; } set { System.Console.WriteLine(""I2.set_P2""); System.Console.WriteLine(GetHashCode()); M1(); P1 = P1; E1 += null; E1 -= null; M3(); P3 = P3; E3 += null; E3 -= null; } } event System.Action E2 { add { System.Console.WriteLine(""I2.add_E2""); System.Console.WriteLine(GetHashCode()); M1(); P1 = P1; E1 += null; E1 -= null; M3(); P3 = P3; E3 += null; E3 -= null; } remove { System.Console.WriteLine(""I2.remove_E2""); System.Console.WriteLine(GetHashCode()); M1(); P1 = P1; E1 += null; E1 -= null; M3(); P3 = P3; E3 += null; E3 -= null; } } void M3() { System.Console.WriteLine(""I2.M3""); } int P3 { get { System.Console.WriteLine(""I2.get_P3""); return 0; } set => System.Console.WriteLine(""I2.set_P3""); } event System.Action E3 { add => System.Console.WriteLine(""I2.add_E3""); remove => System.Console.WriteLine(""I2.remove_E3""); } } class Test1 : I2 { static void Main() { I2 x = new Test1(); x.M2(); x.P2 = x.P2; x.E2 += null; x.E2 -= null; } public override int GetHashCode() { return 123; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"I2.M2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.get_P2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.set_P2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.add_E2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 I2.remove_E2 123 I1.M1 I1.get_P1 I1.set_P1 I1.add_E1 I1.remove_E1 I2.M3 I2.get_P3 I2.set_P3 I2.add_E3 I2.remove_E3 ", verify: VerifyOnMonoOrCoreClr); } [Fact] public void ImplicitThisIsAllowed_02() { var source1 = @" public interface I1 { public int F1; } public interface I2 : I1 { void M2() { F1 = F2; } int P2 { get { F1 = F2; return 0; } set { F1 = F2; } } event System.Action E2 { add { F1 = F2; } remove { F1 = F2; } } public int F2; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS0525: Interfaces cannot contain fields // public int F1; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16), // (39,16): error CS0525: Interfaces cannot contain fields // public int F2; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F2").WithLocation(39, 16) ); } [Fact] public void MethodModifiers_01() { var source1 = @" public interface I1 { public void M01(); protected void M02(); protected internal void M03(); internal void M04(); private void M05(); static void M06(); virtual void M07(); sealed void M08(); override void M09(); abstract void M10(); extern void M11(); async void M12(); private protected void M13(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (12,19): error CS0106: The modifier 'override' is not valid for this item // override void M09(); Diagnostic(ErrorCode.ERR_BadMemberFlag, "M09").WithArguments("override").WithLocation(12, 19), // (15,16): error CS1994: The 'async' modifier can only be used in methods that have a body. // async void M12(); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M12").WithLocation(15, 16), // (8,18): error CS0501: 'I1.M05()' must declare a body because it is not marked abstract, extern, or partial // private void M05(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M05").WithArguments("I1.M05()").WithLocation(8, 18), // (9,17): error CS0501: 'I1.M06()' must declare a body because it is not marked abstract, extern, or partial // static void M06(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M06").WithArguments("I1.M06()").WithLocation(9, 17), // (10,18): error CS0501: 'I1.M07()' must declare a body because it is not marked abstract, extern, or partial // virtual void M07(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M07").WithArguments("I1.M07()").WithLocation(10, 18), // (11,17): error CS0501: 'I1.M08()' must declare a body because it is not marked abstract, extern, or partial // sealed void M08(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M08").WithArguments("I1.M08()").WithLocation(11, 17), // (14,17): warning CS0626: Method, operator, or accessor 'I1.M11()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void M11(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M11").WithArguments("I1.M11()").WithLocation(14, 17) ); ValidateSymbolsMethodModifiers_01(compilation1); } private static void ValidateSymbolsMethodModifiers_01(CSharpCompilation compilation1) { var i1 = compilation1.GetTypeByMetadataName("I1"); var m01 = i1.GetMember<MethodSymbol>("M01"); Assert.True(m01.IsAbstract); Assert.False(m01.IsVirtual); Assert.True(m01.IsMetadataVirtual()); Assert.False(m01.IsSealed); Assert.False(m01.IsStatic); Assert.False(m01.IsExtern); Assert.False(m01.IsAsync); Assert.False(m01.IsOverride); Assert.Equal(Accessibility.Public, m01.DeclaredAccessibility); var m02 = i1.GetMember<MethodSymbol>("M02"); Assert.True(m02.IsAbstract); Assert.False(m02.IsVirtual); Assert.True(m02.IsMetadataVirtual()); Assert.False(m02.IsSealed); Assert.False(m02.IsStatic); Assert.False(m02.IsExtern); Assert.False(m02.IsAsync); Assert.False(m02.IsOverride); Assert.Equal(Accessibility.Protected, m02.DeclaredAccessibility); var m03 = i1.GetMember<MethodSymbol>("M03"); Assert.True(m03.IsAbstract); Assert.False(m03.IsVirtual); Assert.True(m03.IsMetadataVirtual()); Assert.False(m03.IsSealed); Assert.False(m03.IsStatic); Assert.False(m03.IsExtern); Assert.False(m03.IsAsync); Assert.False(m03.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, m03.DeclaredAccessibility); var m04 = i1.GetMember<MethodSymbol>("M04"); Assert.True(m04.IsAbstract); Assert.False(m04.IsVirtual); Assert.True(m04.IsMetadataVirtual()); Assert.False(m04.IsSealed); Assert.False(m04.IsStatic); Assert.False(m04.IsExtern); Assert.False(m04.IsAsync); Assert.False(m04.IsOverride); Assert.Equal(Accessibility.Internal, m04.DeclaredAccessibility); var m05 = i1.GetMember<MethodSymbol>("M05"); Assert.False(m05.IsAbstract); Assert.False(m05.IsVirtual); Assert.False(m05.IsMetadataVirtual()); Assert.False(m05.IsSealed); Assert.False(m05.IsStatic); Assert.False(m05.IsExtern); Assert.False(m05.IsAsync); Assert.False(m05.IsOverride); Assert.Equal(Accessibility.Private, m05.DeclaredAccessibility); var m06 = i1.GetMember<MethodSymbol>("M06"); Assert.False(m06.IsAbstract); Assert.False(m06.IsVirtual); Assert.False(m06.IsMetadataVirtual()); Assert.False(m06.IsSealed); Assert.True(m06.IsStatic); Assert.False(m06.IsExtern); Assert.False(m06.IsAsync); Assert.False(m06.IsOverride); Assert.Equal(Accessibility.Public, m06.DeclaredAccessibility); var m07 = i1.GetMember<MethodSymbol>("M07"); Assert.False(m07.IsAbstract); Assert.True(m07.IsVirtual); Assert.True(m07.IsMetadataVirtual()); Assert.False(m07.IsSealed); Assert.False(m07.IsStatic); Assert.False(m07.IsExtern); Assert.False(m07.IsAsync); Assert.False(m07.IsOverride); Assert.Equal(Accessibility.Public, m07.DeclaredAccessibility); var m08 = i1.GetMember<MethodSymbol>("M08"); Assert.False(m08.IsAbstract); Assert.False(m08.IsVirtual); Assert.False(m08.IsMetadataVirtual()); Assert.False(m08.IsSealed); Assert.False(m08.IsStatic); Assert.False(m08.IsExtern); Assert.False(m08.IsAsync); Assert.False(m08.IsOverride); Assert.Equal(Accessibility.Public, m08.DeclaredAccessibility); var m09 = i1.GetMember<MethodSymbol>("M09"); Assert.True(m09.IsAbstract); Assert.False(m09.IsVirtual); Assert.True(m09.IsMetadataVirtual()); Assert.False(m09.IsSealed); Assert.False(m09.IsStatic); Assert.False(m09.IsExtern); Assert.False(m09.IsAsync); Assert.False(m09.IsOverride); Assert.Equal(Accessibility.Public, m09.DeclaredAccessibility); var m10 = i1.GetMember<MethodSymbol>("M10"); Assert.True(m10.IsAbstract); Assert.False(m10.IsVirtual); Assert.True(m10.IsMetadataVirtual()); Assert.False(m10.IsSealed); Assert.False(m10.IsStatic); Assert.False(m10.IsExtern); Assert.False(m10.IsAsync); Assert.False(m10.IsOverride); Assert.Equal(Accessibility.Public, m10.DeclaredAccessibility); var m11 = i1.GetMember<MethodSymbol>("M11"); Assert.False(m11.IsAbstract); Assert.True(m11.IsVirtual); Assert.True(m11.IsMetadataVirtual()); Assert.False(m11.IsSealed); Assert.False(m11.IsStatic); Assert.True(m11.IsExtern); Assert.False(m11.IsAsync); Assert.False(m11.IsOverride); Assert.Equal(Accessibility.Public, m11.DeclaredAccessibility); var m12 = i1.GetMember<MethodSymbol>("M12"); Assert.True(m12.IsAbstract); Assert.False(m12.IsVirtual); Assert.True(m12.IsMetadataVirtual()); Assert.False(m12.IsSealed); Assert.False(m12.IsStatic); Assert.False(m12.IsExtern); Assert.True(m12.IsAsync); Assert.False(m12.IsOverride); Assert.Equal(Accessibility.Public, m12.DeclaredAccessibility); var m13 = i1.GetMember<MethodSymbol>("M13"); Assert.True(m13.IsAbstract); Assert.False(m13.IsVirtual); Assert.True(m13.IsMetadataVirtual()); Assert.False(m13.IsSealed); Assert.False(m13.IsStatic); Assert.False(m13.IsExtern); Assert.False(m13.IsAsync); Assert.False(m13.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, m13.DeclaredAccessibility); } [Fact] public void MethodModifiers_02() { var source1 = @" public interface I1 { public void M01(); protected void M02(); protected internal void M03(); internal void M04(); private void M05(); static void M06(); virtual void M07(); sealed void M08(); override void M09(); abstract void M10(); extern void M11(); async void M12(); private protected void M13(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,17): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public void M01(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M01").WithArguments("public", "7.3", "8.0").WithLocation(4, 17), // (5,20): error CS8703: The modifier 'protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // protected void M02(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M02").WithArguments("protected", "7.3", "8.0").WithLocation(5, 20), // (6,29): error CS8703: The modifier 'protected internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // protected internal void M03(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M03").WithArguments("protected internal", "7.3", "8.0").WithLocation(6, 29), // (7,19): error CS8503: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal void M04(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M04").WithArguments("internal", "7.3", "8.0").WithLocation(7, 19), // (8,18): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private void M05(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M05").WithArguments("private", "7.3", "8.0").WithLocation(8, 18), // (9,17): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static void M06(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M06").WithArguments("static", "7.3", "8.0").WithLocation(9, 17), // (10,18): error CS8503: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual void M07(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M07").WithArguments("virtual", "7.3", "8.0").WithLocation(10, 18), // (11,17): error CS8503: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // sealed void M08(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M08").WithArguments("sealed", "7.3", "8.0").WithLocation(11, 17), // (12,19): error CS0106: The modifier 'override' is not valid for this item // override void M09(); Diagnostic(ErrorCode.ERR_BadMemberFlag, "M09").WithArguments("override").WithLocation(12, 19), // (13,19): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // abstract void M10(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M10").WithArguments("abstract", "7.3", "8.0").WithLocation(13, 19), // (14,17): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern void M11(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M11").WithArguments("extern", "7.3", "8.0").WithLocation(14, 17), // (15,16): error CS8503: The modifier 'async' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // async void M12(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M12").WithArguments("async", "7.3", "8.0").WithLocation(15, 16), // (15,16): error CS1994: The 'async' modifier can only be used in methods that have a body. // async void M12(); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M12").WithLocation(15, 16), // (8,18): error CS0501: 'I1.M05()' must declare a body because it is not marked abstract, extern, or partial // private void M05(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M05").WithArguments("I1.M05()").WithLocation(8, 18), // (9,17): error CS0501: 'I1.M06()' must declare a body because it is not marked abstract, extern, or partial // static void M06(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M06").WithArguments("I1.M06()").WithLocation(9, 17), // (10,18): error CS0501: 'I1.M07()' must declare a body because it is not marked abstract, extern, or partial // virtual void M07(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M07").WithArguments("I1.M07()").WithLocation(10, 18), // (11,17): error CS0501: 'I1.M08()' must declare a body because it is not marked abstract, extern, or partial // sealed void M08(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M08").WithArguments("I1.M08()").WithLocation(11, 17), // (14,17): warning CS0626: Method, operator, or accessor 'I1.M11()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void M11(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M11").WithArguments("I1.M11()").WithLocation(14, 17), // (16,28): error CS8703: The modifier 'private protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private protected void M13(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M13").WithArguments("private protected", "7.3", "8.0").WithLocation(16, 28) ); ValidateSymbolsMethodModifiers_01(compilation1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (5,20): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected void M02(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M02").WithLocation(5, 20), // (6,29): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal void M03(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M03").WithLocation(6, 29), // (8,18): error CS0501: 'I1.M05()' must declare a body because it is not marked abstract, extern, or partial // private void M05(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M05").WithArguments("I1.M05()").WithLocation(8, 18), // (9,17): error CS0501: 'I1.M06()' must declare a body because it is not marked abstract, extern, or partial // static void M06(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M06").WithArguments("I1.M06()").WithLocation(9, 17), // (10,18): error CS0501: 'I1.M07()' must declare a body because it is not marked abstract, extern, or partial // virtual void M07(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M07").WithArguments("I1.M07()").WithLocation(10, 18), // (11,17): error CS0501: 'I1.M08()' must declare a body because it is not marked abstract, extern, or partial // sealed void M08(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M08").WithArguments("I1.M08()").WithLocation(11, 17), // (12,19): error CS0106: The modifier 'override' is not valid for this item // override void M09(); Diagnostic(ErrorCode.ERR_BadMemberFlag, "M09").WithArguments("override").WithLocation(12, 19), // (14,17): error CS8701: Target runtime doesn't support default interface implementation. // extern void M11(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M11").WithLocation(14, 17), // (14,17): warning CS0626: Method, operator, or accessor 'I1.M11()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void M11(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M11").WithArguments("I1.M11()").WithLocation(14, 17), // (15,16): error CS1994: The 'async' modifier can only be used in methods that have a body. // async void M12(); Diagnostic(ErrorCode.ERR_BadAsyncLacksBody, "M12").WithLocation(15, 16), // (16,28): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected void M13(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M13").WithLocation(16, 28) ); ValidateSymbolsMethodModifiers_01(compilation2); } [Fact] [WorkItem(33083, "https://github.com/dotnet/roslyn/issues/33083")] public void MethodModifiers_03() { var source1 = @" public interface I1 { public virtual void M1() { System.Console.WriteLine(""M1""); } } "; ValidateMethodImplementation_011(source1); } [Fact] public void MethodModifiers_04() { var source1 = @" public interface I1 { public abstract void M1(); void M2(); } class Test1 : I1 { public void M1() { System.Console.WriteLine(""M1""); } public void M2() { System.Console.WriteLine(""M2""); } static void Main() { I1 x = new Test1(); x.M1(); x.M2(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: @"M1 M2", symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var methodName in new[] { "M1", "M2" }) { var m1 = i1.GetMember<MethodSymbol>(methodName); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Same(test1.GetMember(methodName), test1.FindImplementationForInterfaceMember(m1)); } } } [Fact] public void MethodModifiers_05() { var source1 = @" public interface I1 { public abstract void M1(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3); compilation1.VerifyDiagnostics( // (4,26): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "7.3", "8.0").WithLocation(4, 26), // (4,26): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("public", "7.3", "8.0").WithLocation(4, 26) ); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); } [Fact] public void MethodModifiers_06() { var source1 = @" public interface I1 { public static void M1() { System.Console.WriteLine(""M1""); } internal static void M2() { System.Console.WriteLine(""M2""); M3(); } private static void M3() { System.Console.WriteLine(""M3""); } } class Test1 : I1 { static void Main() { I1.M1(); I1.M2(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M1 M2 M3", symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var tuple in new[] { (name: "M1", access: Accessibility.Public), (name: "M2", access: Accessibility.Internal), (name: "M3", access: Accessibility.Private) }) { var m1 = i1.GetMember<MethodSymbol>(tuple.name); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.True(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(tuple.access, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } } } [Fact] public void MethodModifiers_07() { var source1 = @" public interface I1 { abstract static void M1(); virtual static void M2() { } sealed static void M3() { } static void M4() { } } class Test1 : I1 { void I1.M4() {} void I1.M1() {} void I1.M2() {} void I1.M3() {} } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,26): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // abstract static void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "9.0", "11.0").WithLocation(4, 26), // (6,25): error CS8703: The modifier 'virtual' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // virtual static void M2() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M2").WithArguments("virtual", "9.0", "11.0").WithLocation(6, 25), // (10,24): error CS8703: The modifier 'sealed' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // sealed static void M3() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M3").WithArguments("sealed", "9.0", "11.0").WithLocation(10, 24), // (27,15): error CS0535: 'Test2' does not implement interface member 'I1.M1()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(27, 15), // (22,13): error CS0539: 'Test1.M1()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M1() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("Test1.M1()").WithLocation(22, 13), // (23,13): error CS0539: 'Test1.M2()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M2() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M2").WithArguments("Test1.M2()").WithLocation(23, 13), // (24,13): error CS0539: 'Test1.M3()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M3() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test1.M3()").WithLocation(24, 13), // (21,13): error CS0539: 'Test1.M4()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M4() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test1.M4()").WithLocation(21, 13), // (19,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(19, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.True(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.False(m2.IsAbstract); Assert.True(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.True(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); var m3 = i1.GetMember<MethodSymbol>("M3"); Assert.False(m3.IsAbstract); Assert.False(m3.IsVirtual); Assert.False(m3.IsMetadataVirtual()); Assert.False(m3.IsSealed); Assert.True(m3.IsStatic); Assert.False(m3.IsExtern); Assert.False(m3.IsAsync); Assert.False(m3.IsOverride); Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m3)); } [Fact] public void MethodModifiers_08() { var source1 = @" public interface I1 { private void M1() { System.Console.WriteLine(""M1""); } void M4() { System.Console.WriteLine(""M4""); M1(); } } class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M4(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M4 M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } } [Fact] public void MethodModifiers_09() { var source1 = @" public interface I1 { abstract private void M1(); virtual private void M2() { } sealed private void M3() { } } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,25): error CS0238: 'I1.M3()' cannot be sealed because it is not an override // sealed private void M3() Diagnostic(ErrorCode.ERR_SealedNonOverride, "M3").WithArguments("I1.M3()").WithLocation(10, 25), // (6,26): error CS0621: 'I1.M2()': virtual or abstract members cannot be private // virtual private void M2() Diagnostic(ErrorCode.ERR_VirtualPrivate, "M2").WithArguments("I1.M2()").WithLocation(6, 26), // (4,27): error CS0621: 'I1.M1()': virtual or abstract members cannot be private // abstract private void M1(); Diagnostic(ErrorCode.ERR_VirtualPrivate, "M1").WithArguments("I1.M1()").WithLocation(4, 27), // (15,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(15, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.False(m2.IsAbstract); Assert.True(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.False(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Private, m2.DeclaredAccessibility); Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); var m3 = i1.GetMember<MethodSymbol>("M3"); Assert.False(m3.IsAbstract); Assert.False(m3.IsVirtual); Assert.False(m3.IsMetadataVirtual()); Assert.True(m3.IsSealed); Assert.False(m3.IsStatic); Assert.False(m3.IsExtern); Assert.False(m3.IsAsync); Assert.False(m3.IsOverride); Assert.Equal(Accessibility.Private, m3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m3)); } [Theory] [CombinatorialData] public void MethodModifiers_10_01(bool isStatic) { string declModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + declModifiers + @" internal abstract void M1(); "; if (!isStatic) { source1 += @" void M2() {M1();} "; } else { source1 += @" static void M2<T>() where T : I1 { T.M1(); } "; } source1 += @" } "; var source2 = @" class Test1 : I1 { " + declModifiers + @" public void M1() { System.Console.WriteLine(""M1""); } "; if (!isStatic) { source2 += @" static void Main() { I1 x = new Test1(); x.M2(); } "; } else { source2 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { I1.M2<T>(); } "; } source2 += @" } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (!isStatic) { compilation1.VerifyDiagnostics( // (14,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(14, 17) ); } else { compilation1.VerifyDiagnostics( // (4,28): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // internal abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "9.0", "11.0").WithLocation(4, 28), // (9,9): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // T.M1(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "T").WithArguments("static abstract members in interfaces", "11.0").WithLocation(9, 9) ); } ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.Internal, isStatic: isStatic); compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: isStatic ? TestOptions.Regular11 : TestOptions.Regular10, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : "M1", verify: Verify(isStatic), symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, Accessibility.Internal, isStatic: isStatic)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.Internal, isStatic: isStatic); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Internal, isStatic: isStatic); var source3 = @" class Test2 : I1 { } "; foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (5,17): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(5, 17) ); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.Internal, isStatic: isStatic); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular10, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (5,17): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(5, 17) ); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.Internal, isStatic: isStatic); var compilation5 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.M1()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(2, 15) ); ValidateI1M1NotImplemented(compilation5, "Test2"); } } private static void ValidateI1M1NotImplemented(CSharpCompilation compilation, string className) { var test2 = compilation.GetTypeByMetadataName(className); var i1 = compilation.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.Null(test2.FindImplementationForInterfaceMember(m1)); } private static void ValidateMethodModifiersImplicit_10(ModuleSymbol m, Accessibility accessibility, bool isStatic = false) { ValidateMethodModifiers_10(m, implementedByBase: false, isExplicit: false, accessibility, isStatic: isStatic); } private static void ValidateMethodModifiersExplicit_10(ModuleSymbol m, Accessibility accessibility) { ValidateMethodModifiers_10(m, implementedByBase: false, isExplicit: true, accessibility); } private static void ValidateMethodModifiersImplicitInTest2_10(ModuleSymbol m, Accessibility accessibility) { ValidateMethodModifiers_10(m, implementedByBase: true, isExplicit: false, accessibility); } private static void ValidateMethodModifiersExplicitInTest2_10(ModuleSymbol m, Accessibility accessibility) { ValidateMethodModifiers_10(m, implementedByBase: true, isExplicit: true, accessibility); } private static void ValidateMethodModifiers_10(ModuleSymbol m, bool implementedByBase, bool isExplicit, Accessibility accessibility, bool isStatic = false) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var m1 = i1.GetMember<MethodSymbol>("M1"); ValidateMethodModifiers_10(m1, accessibility, isStatic: isStatic); var implementation = (implementedByBase ? test1.BaseTypeNoUseSiteDiagnostics : test1).GetMember<MethodSymbol>((isExplicit ? "I1." : "") + "M1"); Assert.NotNull(implementation); Assert.Same(implementation, test1.FindImplementationForInterfaceMember(m1)); Assert.Equal(!isStatic, implementation.IsMetadataVirtual()); } private static void ValidateMethodModifiers_10(MethodSymbol m1, Accessibility accessibility, bool isStatic = false) { Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(accessibility, m1.DeclaredAccessibility); } [Fact] public void MethodModifiers_10_02() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallM1(new Test1()); } public virtual void M1() { System.Console.WriteLine(""Test1.M1""); } } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (9,25): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(9, 25) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,25): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(9, 25) ) ); } private static DiagnosticDescription[] ExpectedDiagnostics(params DiagnosticDescription[] array) => array; private void ValidateMethodModifiers_10_02(string source1, string source2, Accessibility accessibility, params DiagnosticDescription[] expectedIn9) { ValidateMethodModifiers_10_02(source1, source2, accessibility, expectedIn9, expectedIn9AcrossAssemblyBoundaries: expectedIn9, expectedAcrossAssemblyBoundaries: Array.Empty<DiagnosticDescription>()); } private void ValidateMethodModifiers_10_02(string source1, string source2, Accessibility accessibility, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { ValidateMethodModifiers_10_02(source1, source2, accessibility, expectedIn9, expectedIn9AcrossAssemblyBoundaries: expectedIn9, expectedAcrossAssemblyBoundaries); } private void ValidateMethodModifiers_10_02(string source1, string source2, Accessibility accessibility, DiagnosticDescription[] expectedIn9, DiagnosticDescription[] expectedIn9AcrossAssemblyBoundaries, DiagnosticDescription[] expectedAcrossAssemblyBoundaries, bool isStatic = false) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expectedIn9); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, accessibility, isStatic: isStatic); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic) ? null : "Test1.M1", verify: Verify(isStatic), symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, accessibility, isStatic: isStatic)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, accessibility, isStatic: isStatic); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), accessibility, isStatic: isStatic); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9AcrossAssemblyBoundaries); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, accessibility, isStatic: isStatic); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic) ? null : "Test1.M1", verify: Verify(isStatic), symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, accessibility, isStatic: isStatic)).VerifyDiagnostics(); } ValidateMethodModifiersImplicit_10(compilation3.SourceModule, accessibility, isStatic: isStatic); } } [Fact] public void MethodModifiers_10_03() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallM1(new Test1()); } void I1.M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicit_10(m, Accessibility.Internal)); ValidateMethodModifiersExplicit_10(compilation1.SourceModule, Accessibility.Internal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Internal); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation3.VerifyDiagnostics( // (9,13): error CS0122: 'I1.M1()' is inaccessible due to its protection level // void I1.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(9, 13) ); ValidateMethodModifiersExplicit_10(compilation3.SourceModule, Accessibility.Internal); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation4.VerifyDiagnostics( // (9,13): error CS0122: 'I1.M1()' is inaccessible due to its protection level // void I1.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(9, 13) ); ValidateMethodModifiersExplicit_10(compilation4.SourceModule, Accessibility.Internal); } [Fact] public void MethodModifiers_10_04() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } public class Test2 : I1 { void I1.M1() { System.Console.WriteLine(""Test2.M1""); } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallM1(new Test1()); } public void M1() { System.Console.WriteLine(""Test1.M1""); } } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (9,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(9, 17) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,17): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(9, 17) ) ); } [Fact] public void MethodModifiers_10_05() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } public class Test2 : I1 { void I1.M1() { System.Console.WriteLine(""Test2.M1""); } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallM1(new Test1()); } public virtual void M1() { System.Console.WriteLine(""Test1.M1""); } } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (9,25): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(9, 25) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,25): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(9, 25) ) ); } [Fact] public void MethodModifiers_10_06() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } public class Test2 : I1 { void I1.M1() { System.Console.WriteLine(""Test2.M1""); } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallM1(new Test3()); } public abstract void M1(); } class Test3 : Test1 { public override void M1() { System.Console.WriteLine(""Test1.M1""); } } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (9,26): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract void M1(); Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(9, 26) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,26): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public abstract void M1(); Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(9, 26) ) ); } [Fact] public void MethodModifiers_10_07() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } public class Test2 : I1 { void I1.M1() { System.Console.WriteLine(""Test2.M1""); } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallM1(new Test1()); } public void M1() { System.Console.WriteLine(""Test1.M1""); } } public interface I2 { void M1(); } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (9,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(9, 17) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,17): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(9, 17) ) ); } [Fact] public void MethodModifiers_10_08() { var source1 = @" public interface I1 { internal abstract void M1(); } public class TestHelper { public static void CallM1(I1 x) {x.M1();} } public class Test2 : I1 { void I1.M1() { System.Console.WriteLine(""Test2.M1""); } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallM1(new Test1()); } public virtual int M1() { System.Console.WriteLine(""Test1.M1""); return 0; } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: "Test2.M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicitInTest2_10(m, Accessibility.Internal)); ValidateMethodModifiersExplicitInTest2_10(compilation1.SourceModule, Accessibility.Internal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Internal); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation3, expectedOutput: "Test2.M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicitInTest2_10(m, Accessibility.Internal)); ValidateMethodModifiersExplicitInTest2_10(compilation3.SourceModule, Accessibility.Internal); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation4, expectedOutput: "Test2.M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicitInTest2_10(m, Accessibility.Internal)); ValidateMethodModifiersExplicitInTest2_10(compilation4.SourceModule, Accessibility.Internal); } [Fact] public void MethodModifiers_10_09() { var source1 = @" public interface I1 { internal abstract void M1(); void M2() {M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public virtual int M1() { System.Console.WriteLine(""M1""); return 0; } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (9,15): error CS0738: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implement 'I1.M1()' because it does not have the matching return type of 'void'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "void").WithLocation(9, 15) ); ValidateI1M1NotImplemented(compilation1, "Test1"); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Internal); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implement 'I1.M1()' because it does not have the matching return type of 'void'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "void").WithLocation(2, 15) ); ValidateI1M1NotImplemented(compilation3, "Test1"); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics( // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implement 'I1.M1()' because it does not have the matching return type of 'void'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "void").WithLocation(2, 15) ); ValidateI1M1NotImplemented(compilation4, "Test1"); } [Fact] public void MethodModifiers_10_10() { var source1 = @" public interface I1 { internal abstract void M1(); void M2() {M1();} } "; var source2 = @" class Test2 : I1 { public void M1() { System.Console.WriteLine(""M1""); } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (11,17): error CS8704: 'Test2' does not implement interface member 'I1.M1()'. 'Test2.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test2", "I1.M1()", "Test2.M1()", "9.0", "10.0").WithLocation(11, 17) ); ValidateMethodModifiersImplicitInTest2_10(compilation1.SourceModule, Accessibility.Internal); compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicitInTest2_10(m, Accessibility.Internal)).VerifyDiagnostics(); ValidateMethodModifiersImplicitInTest2_10(compilation1.SourceModule, Accessibility.Internal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Internal); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { foreach (var parseOptions in new[] { TestOptions.Regular9, TestOptions.Regular }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: parseOptions, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics( // (4,17): error CS9044: 'Test2' does not implement interface member 'I1.M1()'. 'Test2.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test2", "I1.M1()", "Test2.M1()").WithLocation(4, 17) ); ValidateMethodModifiersImplicitInTest2_10(compilation3.SourceModule, Accessibility.Internal); } } } [Fact] public void MethodModifiers_10_11() { var source1 = @" public interface I1 { internal abstract void M1(); void M2() {M1();} } public class Test2 : I1 { public void M1() { System.Console.WriteLine(""M1""); } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp, assemblyName: "MethodModifiers_10_11"); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicitInTest2_10(m, Accessibility.Internal)).VerifyDiagnostics(); ValidateMethodModifiersImplicitInTest2_10(compilation3.SourceModule, Accessibility.Internal); compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicitInTest2_10(m, Accessibility.Internal)).VerifyDiagnostics(); ValidateMethodModifiersImplicitInTest2_10(compilation3.SourceModule, Accessibility.Internal); } [Fact] public void MethodModifiers_11() { var source1 = @" public interface I1 { internal abstract void M1(); } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(7, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } [Fact] public void MethodModifiers_12() { var source1 = @" public interface I1 { public sealed void M1() { System.Console.WriteLine(""M1""); } } class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M1(); } public void M1() { System.Console.WriteLine(""Test1.M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); } [Fact] public void MethodModifiers_13() { var source1 = @" public interface I1 { public sealed void M1() { System.Console.WriteLine(""M1""); } abstract sealed void M2(); virtual sealed void M3() { } public sealed void M4(); } class Test1 : I1 { void I1.M1() {} void I1.M2() {} void I1.M3() {} void I1.M4() {} } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (15,24): error CS0501: 'I1.M4()' must declare a body because it is not marked abstract, extern, or partial // public sealed void M4(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M4").WithArguments("I1.M4()").WithLocation(15, 24), // (9,26): error CS0238: 'I1.M2()' cannot be sealed because it is not an override // abstract sealed void M2(); Diagnostic(ErrorCode.ERR_SealedNonOverride, "M2").WithArguments("I1.M2()").WithLocation(9, 26), // (11,25): error CS0238: 'I1.M3()' cannot be sealed because it is not an override // virtual sealed void M3() Diagnostic(ErrorCode.ERR_SealedNonOverride, "M3").WithArguments("I1.M3()").WithLocation(11, 25), // (23,13): error CS0539: 'Test1.M4()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M4() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test1.M4()").WithLocation(23, 13), // (20,13): error CS0539: 'Test1.M1()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M1() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("Test1.M1()").WithLocation(20, 13), // (21,13): error CS0539: 'Test1.M2()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M2() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M2").WithArguments("Test1.M2()").WithLocation(21, 13), // (22,13): error CS0539: 'Test1.M3()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M3() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test1.M3()").WithLocation(22, 13) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); Assert.Null(test2.FindImplementationForInterfaceMember(m1)); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.True(m2.IsAbstract); Assert.False(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.True(m2.IsSealed); Assert.False(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m2)); Assert.Null(test2.FindImplementationForInterfaceMember(m2)); var m3 = i1.GetMember<MethodSymbol>("M3"); Assert.False(m3.IsAbstract); Assert.True(m3.IsVirtual); Assert.True(m3.IsMetadataVirtual()); Assert.True(m3.IsSealed); Assert.False(m3.IsStatic); Assert.False(m3.IsExtern); Assert.False(m3.IsAsync); Assert.False(m3.IsOverride); Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m3)); Assert.Null(test2.FindImplementationForInterfaceMember(m3)); var m4 = i1.GetMember<MethodSymbol>("M4"); Assert.False(m4.IsAbstract); Assert.False(m4.IsVirtual); Assert.False(m4.IsMetadataVirtual()); Assert.False(m4.IsSealed); Assert.False(m4.IsStatic); Assert.False(m4.IsExtern); Assert.False(m4.IsAsync); Assert.False(m4.IsOverride); Assert.Equal(Accessibility.Public, m4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m4)); Assert.Null(test2.FindImplementationForInterfaceMember(m4)); } [Fact] public void MethodModifiers_14() { var source1 = @" public interface I1 { abstract virtual void M2(); virtual abstract void M3() { } } class Test1 : I1 { void I1.M2() {} void I1.M3() {} } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (6,27): error CS0500: 'I1.M3()' cannot declare a body because it is marked abstract // virtual abstract void M3() Diagnostic(ErrorCode.ERR_AbstractHasBody, "M3").WithArguments("I1.M3()").WithLocation(6, 27), // (6,27): error CS0503: The abstract method 'I1.M3()' cannot be marked virtual // virtual abstract void M3() Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "M3").WithArguments("method", "I1.M3()").WithLocation(6, 27), // (4,27): error CS0503: The abstract method 'I1.M2()' cannot be marked virtual // abstract virtual void M2(); Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "M2").WithArguments("method", "I1.M2()").WithLocation(4, 27), // (17,15): error CS0535: 'Test2' does not implement interface member 'I1.M3()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M3()").WithLocation(17, 15), // (17,15): error CS0535: 'Test2' does not implement interface member 'I1.M2()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M2()").WithLocation(17, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var i1 = compilation1.GetTypeByMetadataName("I1"); foreach (var methodName in new[] { "M2", "M3" }) { var m2 = i1.GetMember<MethodSymbol>(methodName); Assert.True(m2.IsAbstract); Assert.True(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.False(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); Assert.Same(test1.GetMember("I1." + methodName), test1.FindImplementationForInterfaceMember(m2)); Assert.Null(test2.FindImplementationForInterfaceMember(m2)); } } [Fact] public void MethodModifiers_15() { var source1 = @" public interface I1 { extern void M1(); virtual extern void M2(); static extern void M3(); private extern void M4(); extern sealed void M5(); } class Test1 : I1 { } class Test2 : I1 { void I1.M1() {} void I1.M2() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var test2 = m.GlobalNamespace.GetTypeMember("Test2"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); bool isSource = !(m is PEModuleSymbol); Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.Equal(isSource, m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.False(m2.IsAbstract); Assert.True(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.False(m2.IsStatic); Assert.Equal(isSource, m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); var m3 = i1.GetMember<MethodSymbol>("M3"); Assert.False(m3.IsAbstract); Assert.False(m3.IsVirtual); Assert.False(m3.IsMetadataVirtual()); Assert.False(m3.IsSealed); Assert.True(m3.IsStatic); Assert.Equal(isSource, m3.IsExtern); Assert.False(m3.IsAsync); Assert.False(m3.IsOverride); Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m3)); Assert.Null(test2.FindImplementationForInterfaceMember(m3)); var m4 = i1.GetMember<MethodSymbol>("M4"); Assert.False(m4.IsAbstract); Assert.False(m4.IsVirtual); Assert.False(m4.IsMetadataVirtual()); Assert.False(m4.IsSealed); Assert.False(m4.IsStatic); Assert.Equal(isSource, m4.IsExtern); Assert.False(m4.IsAsync); Assert.False(m4.IsOverride); Assert.Equal(Accessibility.Private, m4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m4)); Assert.Null(test2.FindImplementationForInterfaceMember(m4)); var m5 = i1.GetMember<MethodSymbol>("M5"); Assert.False(m5.IsAbstract); Assert.False(m5.IsVirtual); Assert.False(m5.IsMetadataVirtual()); Assert.False(m5.IsSealed); Assert.False(m5.IsStatic); Assert.Equal(isSource, m5.IsExtern); Assert.False(m5.IsAsync); Assert.False(m5.IsOverride); Assert.Equal(Accessibility.Public, m5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m5)); Assert.Null(test2.FindImplementationForInterfaceMember(m5)); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (4,17): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("extern", "7.3", "8.0").WithLocation(4, 17), // (5,25): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern void M2(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M2").WithArguments("extern", "7.3", "8.0").WithLocation(5, 25), // (5,25): error CS8503: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern void M2(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M2").WithArguments("virtual", "7.3", "8.0").WithLocation(5, 25), // (6,24): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static extern void M3(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M3").WithArguments("static", "7.3", "8.0").WithLocation(6, 24), // (6,24): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static extern void M3(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M3").WithArguments("extern", "7.3", "8.0").WithLocation(6, 24), // (7,25): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern void M4(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M4").WithArguments("private", "7.3", "8.0").WithLocation(7, 25), // (7,25): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern void M4(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M4").WithArguments("extern", "7.3", "8.0").WithLocation(7, 25), // (8,24): error CS8503: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed void M5(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M5").WithArguments("sealed", "7.3", "8.0").WithLocation(8, 24), // (8,24): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed void M5(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M5").WithArguments("extern", "7.3", "8.0").WithLocation(8, 24), // (4,17): warning CS0626: Method, operator, or accessor 'I1.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.M1()").WithLocation(4, 17), // (5,25): warning CS0626: Method, operator, or accessor 'I1.M2()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern void M2(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M2").WithArguments("I1.M2()").WithLocation(5, 25), // (6,24): warning CS0626: Method, operator, or accessor 'I1.M3()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern void M3(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 24), // (7,25): warning CS0626: Method, operator, or accessor 'I1.M4()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern void M4(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 25), // (8,24): warning CS0626: Method, operator, or accessor 'I1.M5()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed void M5(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M5").WithArguments("I1.M5()").WithLocation(8, 24) ); Validate(compilation2.SourceModule); var compilation3 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular14, skipUsesIsNullable: true); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (4,17): error CS8501: Target runtime doesn't support default interface implementation. // extern void M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(4, 17), // (5,25): error CS8501: Target runtime doesn't support default interface implementation. // virtual extern void M2(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M2").WithLocation(5, 25), // (6,24): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static extern void M3(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "M3").WithArguments("static members in interfaces", "15.0").WithLocation(6, 24), // (7,25): error CS8501: Target runtime doesn't support default interface implementation. // private extern void M4(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M4").WithLocation(7, 25), // (8,24): error CS8501: Target runtime doesn't support default interface implementation. // extern sealed void M5(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M5").WithLocation(8, 24), // (4,17): warning CS0626: Method, operator, or accessor 'I1.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.M1()").WithLocation(4, 17), // (5,25): warning CS0626: Method, operator, or accessor 'I1.M2()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern void M2(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M2").WithArguments("I1.M2()").WithLocation(5, 25), // (6,24): warning CS0626: Method, operator, or accessor 'I1.M3()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern void M3(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 24), // (7,25): warning CS0626: Method, operator, or accessor 'I1.M4()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern void M4(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 25), // (8,24): warning CS0626: Method, operator, or accessor 'I1.M5()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed void M5(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M5").WithArguments("I1.M5()").WithLocation(8, 24) ); Validate(compilation3.SourceModule); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular15, skipUsesIsNullable: true); Assert.False(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var expected = new[] { // (4,17): error CS8501: Target runtime doesn't support default interface implementation. // extern void M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(4, 17), // (5,25): error CS8501: Target runtime doesn't support default interface implementation. // virtual extern void M2(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M2").WithLocation(5, 25), // (7,25): error CS8501: Target runtime doesn't support default interface implementation. // private extern void M4(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M4").WithLocation(7, 25), // (8,24): error CS8501: Target runtime doesn't support default interface implementation. // extern sealed void M5(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M5").WithLocation(8, 24), // (4,17): warning CS0626: Method, operator, or accessor 'I1.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.M1()").WithLocation(4, 17), // (5,25): warning CS0626: Method, operator, or accessor 'I1.M2()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern void M2(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M2").WithArguments("I1.M2()").WithLocation(5, 25), // (6,24): warning CS0626: Method, operator, or accessor 'I1.M3()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern void M3(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 24), // (7,25): warning CS0626: Method, operator, or accessor 'I1.M4()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern void M4(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 25), // (8,24): warning CS0626: Method, operator, or accessor 'I1.M5()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed void M5(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M5").WithArguments("I1.M5()").WithLocation(8, 24) }; compilation4.VerifyDiagnostics(expected); Validate(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); Assert.False(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics(expected); Validate(compilation5.SourceModule); } [Fact] public void MethodModifiers_16() { var source1 = @" public interface I1 { abstract extern void M1(); extern void M2() {} static extern void M3(); private extern void M4(); extern sealed void M5(); } class Test1 : I1 { } class Test2 : I1 { void I1.M1() {} void I1.M2() {} void I1.M3() {} void I1.M4() {} void I1.M5() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,26): error CS0180: 'I1.M1()' cannot be both extern and abstract // abstract extern void M1(); Diagnostic(ErrorCode.ERR_AbstractAndExtern, "M1").WithArguments("I1.M1()").WithLocation(4, 26), // (5,17): error CS0179: 'I1.M2()' cannot be extern and declare a body // extern void M2() {} Diagnostic(ErrorCode.ERR_ExternHasBody, "M2").WithArguments("I1.M2()").WithLocation(5, 17), // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(11, 15), // (19,13): error CS0539: 'Test2.M3()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M3() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test2.M3()").WithLocation(19, 13), // (20,13): error CS0539: 'Test2.M4()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M4() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test2.M4()").WithLocation(20, 13), // (21,13): error CS0539: 'Test2.M5()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M5() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M5").WithArguments("Test2.M5()").WithLocation(21, 13), // (6,24): warning CS0626: Method, operator, or accessor 'I1.M3()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern void M3(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 24), // (7,25): warning CS0626: Method, operator, or accessor 'I1.M4()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern void M4(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 25), // (8,24): warning CS0626: Method, operator, or accessor 'I1.M5()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed void M5(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M5").WithArguments("I1.M5()").WithLocation(8, 24) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.True(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.False(m2.IsAbstract); Assert.True(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.False(m2.IsStatic); Assert.True(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Public, m2.DeclaredAccessibility); Assert.Same(m2, test1.FindImplementationForInterfaceMember(m2)); Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); var m3 = i1.GetMember<MethodSymbol>("M3"); Assert.Null(test2.FindImplementationForInterfaceMember(m3)); var m4 = i1.GetMember<MethodSymbol>("M4"); Assert.Null(test2.FindImplementationForInterfaceMember(m4)); var m5 = i1.GetMember<MethodSymbol>("M5"); Assert.Null(test2.FindImplementationForInterfaceMember(m5)); } [Fact] public void MethodModifiers_17() { var source1 = @" public interface I1 { abstract void M1() {} abstract private void M2() {} abstract static void M3() {} static extern void M4() {} override sealed void M5() {} } class Test1 : I1 { } class Test2 : I1 { void I1.M1() {} void I1.M2() {} void I1.M3() {} void I1.M4() {} void I1.M5() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,19): error CS0500: 'I1.M1()' cannot declare a body because it is marked abstract // abstract void M1() {} Diagnostic(ErrorCode.ERR_AbstractHasBody, "M1").WithArguments("I1.M1()").WithLocation(4, 19), // (5,27): error CS0500: 'I1.M2()' cannot declare a body because it is marked abstract // abstract private void M2() {} Diagnostic(ErrorCode.ERR_AbstractHasBody, "M2").WithArguments("I1.M2()").WithLocation(5, 27), // (6,26): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // abstract static void M3() {} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M3").WithArguments("abstract", "9.0", "11.0").WithLocation(6, 26), // (6,26): error CS0500: 'I1.M3()' cannot declare a body because it is marked abstract // abstract static void M3() {} Diagnostic(ErrorCode.ERR_AbstractHasBody, "M3").WithArguments("I1.M3()").WithLocation(6, 26), // (7,24): error CS0179: 'I1.M4()' cannot be extern and declare a body // static extern void M4() {} Diagnostic(ErrorCode.ERR_ExternHasBody, "M4").WithArguments("I1.M4()").WithLocation(7, 24), // (8,26): error CS0106: The modifier 'override' is not valid for this item // override sealed void M5() {} Diagnostic(ErrorCode.ERR_BadMemberFlag, "M5").WithArguments("override").WithLocation(8, 26), // (5,27): error CS0621: 'I1.M2()': virtual or abstract members cannot be private // abstract private void M2() {} Diagnostic(ErrorCode.ERR_VirtualPrivate, "M2").WithArguments("I1.M2()").WithLocation(5, 27), // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(11, 15), // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M2()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M2()").WithLocation(11, 15), // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.M3()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M3()").WithLocation(11, 15), // (18,13): error CS0122: 'I1.M2()' is inaccessible due to its protection level // void I1.M2() {} Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("I1.M2()").WithLocation(18, 13), // (19,13): error CS0539: 'Test2.M3()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M3() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M3").WithArguments("Test2.M3()").WithLocation(19, 13), // (20,13): error CS0539: 'Test2.M4()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M4() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M4").WithArguments("Test2.M4()").WithLocation(20, 13), // (21,13): error CS0539: 'Test2.M5()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M5() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M5").WithArguments("Test2.M5()").WithLocation(21, 13), // (15,15): error CS0535: 'Test2' does not implement interface member 'I1.M3()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M3()").WithLocation(15, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); Assert.Same(test2.GetMember("I1.M1"), test2.FindImplementationForInterfaceMember(m1)); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.True(m2.IsAbstract); Assert.False(m2.IsVirtual); Assert.True(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.False(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Private, m2.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m2)); Assert.Same(test2.GetMember("I1.M2"), test2.FindImplementationForInterfaceMember(m2)); var m3 = i1.GetMember<MethodSymbol>("M3"); Assert.True(m3.IsAbstract); Assert.False(m3.IsVirtual); Assert.True(m3.IsMetadataVirtual()); Assert.False(m3.IsSealed); Assert.True(m3.IsStatic); Assert.False(m3.IsExtern); Assert.False(m3.IsAsync); Assert.False(m3.IsOverride); Assert.Equal(Accessibility.Public, m3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m3)); Assert.Null(test2.FindImplementationForInterfaceMember(m3)); var m4 = i1.GetMember<MethodSymbol>("M4"); Assert.False(m4.IsAbstract); Assert.False(m4.IsVirtual); Assert.False(m4.IsMetadataVirtual()); Assert.False(m4.IsSealed); Assert.True(m4.IsStatic); Assert.True(m4.IsExtern); Assert.False(m4.IsAsync); Assert.False(m4.IsOverride); Assert.Equal(Accessibility.Public, m4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m4)); Assert.Null(test2.FindImplementationForInterfaceMember(m4)); var m5 = i1.GetMember<MethodSymbol>("M5"); Assert.False(m5.IsAbstract); Assert.False(m5.IsVirtual); Assert.False(m5.IsMetadataVirtual()); Assert.False(m5.IsSealed); Assert.False(m5.IsStatic); Assert.False(m5.IsExtern); Assert.False(m5.IsAsync); Assert.False(m5.IsOverride); Assert.Equal(Accessibility.Public, m5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m5)); Assert.Null(test2.FindImplementationForInterfaceMember(m5)); } [Fact] [WorkItem(34658, "https://github.com/dotnet/roslyn/issues/34658")] public void MethodModifiers_18() { var source1 = @" using System.Threading; using System.Threading.Tasks; public interface I1 { public static async Task M1() { await Task.Factory.StartNew(() => System.Console.WriteLine(""M1"")); } } class Test1 : I1 { static void Main() { I1.M1().Wait(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.True(m1.IsStatic); Assert.False(m1.IsExtern); Assert.Equal(!(m is PEModuleSymbol), m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Public, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } } [Fact] public void MethodModifiers_20() { var source1 = @" public interface I1 { internal void M1() { System.Console.WriteLine(""M1""); } void M2() {M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var m1 = i1.GetMember<MethodSymbol>("M1"); ValidateMethod(m1); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); } void ValidateMethod(MethodSymbol m1) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Internal, m1.DeclaredAccessibility); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); ValidateMethod(m1); } var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation4, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation4.SourceModule); } [Fact] public void MethodModifiers_21() { var source1 = @" public interface I1 { private static void M1() {} internal static void M2() {} public static void M3() {} static void M4() {} } class Test1 { static void Main() { I1.M1(); I1.M2(); I1.M3(); I1.M4(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (17,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level // I1.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(17, 12) ); var source2 = @" class Test2 { static void Main() { I1.M1(); I1.M2(); I1.M3(); I1.M4(); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics( // (6,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level // I1.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(6, 12), // (7,12): error CS0122: 'I1.M2()' is inaccessible due to its protection level // I1.M2(); Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("I1.M2()").WithLocation(7, 12) ); } [Fact] public void MethodModifiers_22() { var source1 = @" public partial interface I1 { static partial void M1(); [Test2(1)] static partial void M2(); static partial void Main() { M1(); M2(); new System.Action(M2).Invoke(); } } public partial interface I1 { [Test2(2)] static partial void M2() { System.Console.WriteLine(""M2""); } static partial void Main(); } class Test1 : I1 { } [System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = true)] class Test2 : System.Attribute { public Test2(int x) {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M2 M2"); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.True(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); Assert.True(m1.IsPartialMember()); Assert.Null(m1.PartialImplementationPart); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.False(m2.IsAbstract); Assert.False(m2.IsVirtual); Assert.False(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.True(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Private, m2.DeclaredAccessibility); Assert.True(m2.IsPartialMember()); Assert.Equal(2, m2.GetAttributes().Length); Assert.Equal("Test2(1)", m2.GetAttributes()[0].ToString()); Assert.Equal("Test2(2)", m2.GetAttributes()[1].ToString()); var m2Impl = m2.PartialImplementationPart; Assert.False(m2Impl.IsAbstract); Assert.False(m2Impl.IsVirtual); Assert.False(m2Impl.IsMetadataVirtual()); Assert.False(m2Impl.IsSealed); Assert.True(m2Impl.IsStatic); Assert.False(m2Impl.IsExtern); Assert.False(m2Impl.IsAsync); Assert.False(m2Impl.IsOverride); Assert.Equal(Accessibility.Private, m2Impl.DeclaredAccessibility); Assert.True(m2Impl.IsPartialMember()); Assert.Same(m2, m2Impl.PartialDefinitionPart); Assert.Equal(2, m2Impl.GetAttributes().Length); Assert.Equal("Test2(1)", m2Impl.GetAttributes()[0].ToString()); Assert.Equal("Test2(2)", m2Impl.GetAttributes()[1].ToString()); } [Fact] public void MethodModifiers_23() { var source1 = @" public partial interface I1 { partial void M1(); [Test2(1)] partial void M2(); void M3() { M1(); M2(); new System.Action(M2).Invoke(); } } public partial interface I1 { [Test2(2)] partial void M2() { System.Console.WriteLine(""M2""); } } class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M3(); } } [System.AttributeUsage(System.AttributeTargets.All, AllowMultiple = true)] class Test2 : System.Attribute { public Test2(int x) {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M2 M2", verify: VerifyOnMonoOrCoreClr); var i1 = compilation1.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); Assert.True(m1.IsPartialMember()); Assert.Null(m1.PartialImplementationPart); var m2 = i1.GetMember<MethodSymbol>("M2"); Assert.False(m2.IsAbstract); Assert.False(m2.IsVirtual); Assert.False(m2.IsMetadataVirtual()); Assert.False(m2.IsSealed); Assert.False(m2.IsStatic); Assert.False(m2.IsExtern); Assert.False(m2.IsAsync); Assert.False(m2.IsOverride); Assert.Equal(Accessibility.Private, m2.DeclaredAccessibility); Assert.True(m2.IsPartialMember()); Assert.Equal(2, m2.GetAttributes().Length); Assert.Equal("Test2(1)", m2.GetAttributes()[0].ToString()); Assert.Equal("Test2(2)", m2.GetAttributes()[1].ToString()); var m2Impl = m2.PartialImplementationPart; Assert.False(m2Impl.IsAbstract); Assert.False(m2Impl.IsVirtual); Assert.False(m2Impl.IsMetadataVirtual()); Assert.False(m2Impl.IsSealed); Assert.False(m2Impl.IsStatic); Assert.False(m2Impl.IsExtern); Assert.False(m2Impl.IsAsync); Assert.False(m2Impl.IsOverride); Assert.Equal(Accessibility.Private, m2Impl.DeclaredAccessibility); Assert.True(m2Impl.IsPartialMember()); Assert.Same(m2, m2Impl.PartialDefinitionPart); Assert.Equal(2, m2Impl.GetAttributes().Length); Assert.Equal("Test2(1)", m2Impl.GetAttributes()[0].ToString()); Assert.Equal("Test2(2)", m2Impl.GetAttributes()[1].ToString()); } [Fact] public void MethodModifiers_24() { var source1 = @" public partial interface I1 { static partial void M1(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3); compilation1.VerifyDiagnostics( // (4,25): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static partial void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "7.3", "8.0").WithLocation(4, 25), // (4,25): error CS8703: The modifier 'partial' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static partial void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("partial", "7.3", "8.0").WithLocation(4, 25) ); } [Fact] public void MethodModifiers_25() { var source1 = @" public partial interface I1 { partial void M1(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,18): error CS8703: The modifier 'partial' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // partial void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("partial", "7.3", "8.0").WithLocation(4, 18) ); } [Fact] public void MethodModifiers_26_01() { var source1 = @" public partial interface I1 { static partial int M1(); public static partial void M2(); internal static partial void M3(); private static partial void M4(); static partial void M5(out int x); static partial void M6(); static void M7() {} static partial void M8() {} static partial void M9(); static partial void M10(); } public partial interface I1 { static void M6() {} static partial void M7(); static partial void M8() {} static partial void M9(); static extern partial void M10(); protected static partial void M11(); protected internal static partial void M12(); private protected static partial void M13(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularWithExtendedPartialMethods, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,24): error CS8794: Partial method 'I1.M1()' must have accessibility modifiers because it has a non-void return type. // static partial int M1(); Diagnostic(ErrorCode.ERR_PartialMethodWithNonVoidReturnMustHaveAccessMods, "M1").WithArguments("I1.M1()").WithLocation(4, 24), // (5,32): error CS8793: Partial method 'I1.M2()' must have an implementation part because it has accessibility modifiers. // public static partial void M2(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M2").WithArguments("I1.M2()").WithLocation(5, 32), // (6,34): error CS8793: Partial method 'I1.M3()' must have an implementation part because it has accessibility modifiers. // internal static partial void M3(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 34), // (7,33): error CS8793: Partial method 'I1.M4()' must have an implementation part because it has accessibility modifiers. // private static partial void M4(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 33), // (8,25): error CS8795: Partial method 'I1.M5(out int)' must have accessibility modifiers because it has 'out' parameters. // static partial void M5(out int x); Diagnostic(ErrorCode.ERR_PartialMethodWithOutParamMustHaveAccessMods, "M5").WithArguments("I1.M5(out int)").WithLocation(8, 25), // (11,25): error CS0759: No defining declaration found for implementing declaration of partial method 'I1.M8()' // static partial void M8() {} Diagnostic(ErrorCode.ERR_PartialMethodMustHaveLatent, "M8").WithArguments("I1.M8()").WithLocation(11, 25), // (18,17): error CS0111: Type 'I1' already defines a member called 'M6' with the same parameter types // static void M6() {} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M6").WithArguments("M6", "I1").WithLocation(18, 17), // (19,25): error CS0111: Type 'I1' already defines a member called 'M7' with the same parameter types // static partial void M7(); Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M7").WithArguments("M7", "I1").WithLocation(19, 25), // (20,25): error CS0757: A partial method may not have multiple implementing declarations // static partial void M8() {} Diagnostic(ErrorCode.ERR_PartialMethodOnlyOneActual, "M8").WithLocation(20, 25), // (20,25): error CS0111: Type 'I1' already defines a member called 'M8' with the same parameter types // static partial void M8() {} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M8").WithArguments("M8", "I1").WithLocation(20, 25), // (21,25): error CS0756: A partial method may not have multiple defining declarations // static partial void M9(); Diagnostic(ErrorCode.ERR_PartialMethodOnlyOneLatent, "M9").WithLocation(21, 25), // (21,25): error CS0111: Type 'I1' already defines a member called 'M9' with the same parameter types // static partial void M9(); Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M9").WithArguments("M9", "I1").WithLocation(21, 25), // (22,32): error CS8796: Partial method 'I1.M10()' must have accessibility modifiers because it has a 'virtual', 'override', 'sealed', 'new', or 'extern' modifier. // static extern partial void M10(); Diagnostic(ErrorCode.ERR_PartialMethodWithExtendedModMustHaveAccessMods, "M10").WithArguments("I1.M10()").WithLocation(22, 32), // (23,35): error CS8793: Partial method 'I1.M11()' must have an implementation part because it has accessibility modifiers. // protected static partial void M11(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M11").WithArguments("I1.M11()").WithLocation(23, 35), // (24,44): error CS8793: Partial method 'I1.M12()' must have an implementation part because it has accessibility modifiers. // protected internal static partial void M12(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M12").WithArguments("I1.M12()").WithLocation(24, 44), // (25,43): error CS8793: Partial method 'I1.M13()' must have an implementation part because it has accessibility modifiers. // private protected static partial void M13(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M13").WithArguments("I1.M13()").WithLocation(25, 43) ); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularWithExtendedPartialMethods, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (4,24): error CS8794: Partial method 'I1.M1()' must have accessibility modifiers because it has a non-void return type. // static partial int M1(); Diagnostic(ErrorCode.ERR_PartialMethodWithNonVoidReturnMustHaveAccessMods, "M1").WithArguments("I1.M1()").WithLocation(4, 24), // (5,32): error CS8793: Partial method 'I1.M2()' must have an implementation part because it has accessibility modifiers. // public static partial void M2(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M2").WithArguments("I1.M2()").WithLocation(5, 32), // (6,34): error CS8793: Partial method 'I1.M3()' must have an implementation part because it has accessibility modifiers. // internal static partial void M3(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M3").WithArguments("I1.M3()").WithLocation(6, 34), // (7,33): error CS8793: Partial method 'I1.M4()' must have an implementation part because it has accessibility modifiers. // private static partial void M4(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M4").WithArguments("I1.M4()").WithLocation(7, 33), // (8,25): error CS8795: Partial method 'I1.M5(out int)' must have accessibility modifiers because it has 'out' parameters. // static partial void M5(out int x); Diagnostic(ErrorCode.ERR_PartialMethodWithOutParamMustHaveAccessMods, "M5").WithArguments("I1.M5(out int)").WithLocation(8, 25), // (11,25): error CS0759: No defining declaration found for implementing declaration of partial method 'I1.M8()' // static partial void M8() {} Diagnostic(ErrorCode.ERR_PartialMethodMustHaveLatent, "M8").WithArguments("I1.M8()").WithLocation(11, 25), // (18,17): error CS0111: Type 'I1' already defines a member called 'M6' with the same parameter types // static void M6() {} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M6").WithArguments("M6", "I1").WithLocation(18, 17), // (19,25): error CS0111: Type 'I1' already defines a member called 'M7' with the same parameter types // static partial void M7(); Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M7").WithArguments("M7", "I1").WithLocation(19, 25), // (20,25): error CS0757: A partial method may not have multiple implementing declarations // static partial void M8() {} Diagnostic(ErrorCode.ERR_PartialMethodOnlyOneActual, "M8").WithLocation(20, 25), // (20,25): error CS0111: Type 'I1' already defines a member called 'M8' with the same parameter types // static partial void M8() {} Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M8").WithArguments("M8", "I1").WithLocation(20, 25), // (21,25): error CS0756: A partial method may not have multiple defining declarations // static partial void M9(); Diagnostic(ErrorCode.ERR_PartialMethodOnlyOneLatent, "M9").WithLocation(21, 25), // (21,25): error CS0111: Type 'I1' already defines a member called 'M9' with the same parameter types // static partial void M9(); Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M9").WithArguments("M9", "I1").WithLocation(21, 25), // (22,32): error CS8796: Partial method 'I1.M10()' must have accessibility modifiers because it has a 'virtual', 'override', 'sealed', 'new', or 'extern' modifier. // static extern partial void M10(); Diagnostic(ErrorCode.ERR_PartialMethodWithExtendedModMustHaveAccessMods, "M10").WithArguments("I1.M10()").WithLocation(22, 32), // (23,35): error CS8793: Partial method 'I1.M11()' must have an implementation part because it has accessibility modifiers. // protected static partial void M11(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M11").WithArguments("I1.M11()").WithLocation(23, 35), // (24,44): error CS8793: Partial method 'I1.M12()' must have an implementation part because it has accessibility modifiers. // protected internal static partial void M12(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M12").WithArguments("I1.M12()").WithLocation(24, 44), // (25,43): error CS8793: Partial method 'I1.M13()' must have an implementation part because it has accessibility modifiers. // private protected static partial void M13(); Diagnostic(ErrorCode.ERR_PartialMethodWithAccessibilityModsMustHaveImplementation, "M13").WithArguments("I1.M13()").WithLocation(25, 43) ); } [Theory] [CombinatorialData] public void MethodModifiers_26_02([CombinatorialValues("", "public", "private", "internal")] string accessibility) { var source1 = @" public partial interface I1 { " + accessibility + @" static void M1() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (5,17): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static void M1() {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "M1").WithArguments("static members in interfaces", "15.0").WithLocation(5, 17) ); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics(); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics(); } [Theory] [CombinatorialData] public void MethodModifiers_26_03([CombinatorialValues("protected", "internal protected", "private protected")] string accessibility) { var source1 = @" public partial interface I1 { " + accessibility + @" static void M1() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (5,17): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static void M1() {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M1").WithLocation(5, 17) ); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (5,17): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static void M1() {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M1").WithLocation(5, 17) ); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (5,17): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static void M1() {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M1").WithLocation(5, 17) ); } [Fact] public void MethodModifiers_27() { var source1 = @" partial interface I1 : I2 { sealed partial void M1(); abstract partial void M2(); virtual partial void M3(); partial void M4(); partial void M5(); partial void M6(); partial void I2.M7(); } partial interface I1 : I2 { sealed partial void M4() {} abstract partial void M5(); virtual partial void M6() {} partial void I2.M7() {} } interface I2 { void M7(); partial void M8(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularWithExtendedPartialMethods, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,25): error CS8796: Partial method 'I1.M1()' must have accessibility modifiers because it has a 'virtual', 'override', 'sealed', 'new', or 'extern' modifier. // sealed partial void M1(); Diagnostic(ErrorCode.ERR_PartialMethodWithExtendedModMustHaveAccessMods, "M1").WithArguments("I1.M1()").WithLocation(4, 25), // (5,27): error CS0750: A partial member cannot have the 'abstract' modifier // abstract partial void M2(); Diagnostic(ErrorCode.ERR_PartialMemberCannotBeAbstract, "M2").WithLocation(5, 27), // (6,26): error CS8796: Partial method 'I1.M3()' must have accessibility modifiers because it has a 'virtual', 'override', 'sealed', 'new', or 'extern' modifier. // virtual partial void M3(); Diagnostic(ErrorCode.ERR_PartialMethodWithExtendedModMustHaveAccessMods, "M3").WithArguments("I1.M3()").WithLocation(6, 26), // (10,21): error CS0754: A partial member may not explicitly implement an interface member // partial void I2.M7(); Diagnostic(ErrorCode.ERR_PartialMemberNotExplicit, "M7").WithLocation(10, 21), // (15,25): error CS8796: Partial method 'I1.M4()' must have accessibility modifiers because it has a 'virtual', 'override', 'sealed', 'new', or 'extern' modifier. // sealed partial void M4() {} Diagnostic(ErrorCode.ERR_PartialMethodWithExtendedModMustHaveAccessMods, "M4").WithArguments("I1.M4()").WithLocation(15, 25), // (15,25): error CS8798: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers. // sealed partial void M4() {} Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "M4").WithLocation(15, 25), // (16,27): error CS0750: A partial member cannot have the 'abstract' modifier // abstract partial void M5(); Diagnostic(ErrorCode.ERR_PartialMemberCannotBeAbstract, "M5").WithLocation(16, 27), // (16,27): error CS0756: A partial method may not have multiple defining declarations // abstract partial void M5(); Diagnostic(ErrorCode.ERR_PartialMethodOnlyOneLatent, "M5").WithLocation(16, 27), // (16,27): error CS0111: Type 'I1' already defines a member called 'M5' with the same parameter types // abstract partial void M5(); Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "M5").WithArguments("M5", "I1").WithLocation(16, 27), // (17,26): error CS8796: Partial method 'I1.M6()' must have accessibility modifiers because it has a 'virtual', 'override', 'sealed', 'new', or 'extern' modifier. // virtual partial void M6() {} Diagnostic(ErrorCode.ERR_PartialMethodWithExtendedModMustHaveAccessMods, "M6").WithArguments("I1.M6()").WithLocation(17, 26), // (17,26): error CS8798: Both partial member declarations must have identical combinations of 'virtual', 'override', 'sealed', and 'new' modifiers. // virtual partial void M6() {} Diagnostic(ErrorCode.ERR_PartialMemberExtendedModDifference, "M6").WithLocation(17, 26), // (19,21): error CS0754: A partial member may not explicitly implement an interface member // partial void I2.M7() {} Diagnostic(ErrorCode.ERR_PartialMemberNotExplicit, "M7").WithLocation(19, 21), // (25,18): error CS0751: A partial member must be declared within a partial type // partial void M8(); Diagnostic(ErrorCode.ERR_PartialMemberOnlyInPartialClass, "M8").WithLocation(25, 18) ); } [Fact] public void MethodModifiers_28() { var source1 = @" partial interface I1 { partial void M1(); class C : I1 { void I1.M1() {} } } public partial interface I1 { partial void M1() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (8,17): error CS0539: 'I1.C.M1()' in explicit interface declaration is not found among members of the interface that can be implemented // void I1.M1() {} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.C.M1()").WithLocation(8, 17) ); } [Fact] public void MethodModifiers_29() { var source1 = @" public partial interface I1 { partial void M1(); static partial void M2(); void M3() { new System.Action(M1).Invoke(); new System.Action(M2).Invoke(); } partial static void M4(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (9,27): error CS0762: Cannot create delegate from method 'I1.M1()' because it is a partial method without an implementing declaration // new System.Action(M1).Invoke(); Diagnostic(ErrorCode.ERR_PartialMethodToDelegate, "M1").WithArguments("I1.M1()").WithLocation(9, 27), // (10,27): error CS0762: Cannot create delegate from method 'I1.M2()' because it is a partial method without an implementing declaration // new System.Action(M2).Invoke(); Diagnostic(ErrorCode.ERR_PartialMethodToDelegate, "M2").WithArguments("I1.M2()").WithLocation(10, 27), // (13,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', or a method return type. // partial static void M4(); Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(13, 5) ); } [Fact] public void MethodModifiers_30() { var source1 = @" public partial interface I1 { static partial void Main(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // error CS5001: Program does not contain a static 'Main' method suitable for an entry point Diagnostic(ErrorCode.ERR_NoEntryPoint).WithLocation(1, 1) ); } [Fact] public void MethodModifiers_31() { var source1 = @" public partial interface I1 { static partial void M1<T>() where T : struct; static partial void M1<T>() {} static partial void M2(params int[] x); static partial void M2(int[] x) {} static partial void M3(); partial void M3() {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (5,25): error CS0761: Partial method declarations of 'I1.M1<T>()' have inconsistent constraints for type parameter 'T' // static partial void M1<T>() {} Diagnostic(ErrorCode.ERR_PartialMethodInconsistentConstraints, "M1").WithArguments("I1.M1<T>()", "T").WithLocation(5, 25), // (8,25): error CS0758: Both partial member declarations must use a params parameter or neither may use a params parameter // static partial void M2(int[] x) {} Diagnostic(ErrorCode.ERR_PartialMemberParamsDifference, "M2").WithLocation(8, 25), // (11,18): error CS0763: Both partial member declarations must be static or neither may be static // partial void M3() {} Diagnostic(ErrorCode.ERR_PartialMemberStaticDifference, "M3").WithLocation(11, 18) ); } [Fact] public void MethodModifiers_32() { var source1 = @" partial interface I1 { partial void M1(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); compilation1.VerifyDiagnostics(); var source2 = @" partial interface I1 { partial void M1() {} } "; var compilation2 = CreateCompilation(source1 + source2, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (9,18): error CS8701: Target runtime doesn't support default interface implementation. // partial void M1() {} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(9, 18) ); } [Fact] public void MethodModifiers_33() { var source0 = @" public interface I1 { protected static void M1() { System.Console.WriteLine(""M1""); } protected internal static void M2() { System.Console.WriteLine(""M2""); } private protected static void M3() { System.Console.WriteLine(""M3""); } } "; var source1 = @" class Test1 : I1 { static void Main() { I1.M1(); I1.M2(); I1.M3(); } } "; var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M1 M2 M3", symbolValidator: validate, verify: VerifyOnMonoOrCoreClr_FailsIlVerify); validate(compilation1.SourceModule); var source2 = @" class Test1 { static void Main() { I1.M2(); } } "; var compilation2 = CreateCompilation(source0 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M2", verify: VerifyOnMonoOrCoreClr); var compilation3 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); var source3 = @" class Test1 : I1 { static void Main() { I1.M1(); I1.M2(); } } "; var source4 = @" class Test1 { static void Main() { I1.M1(); I1.M2(); I1.M3(); } } "; foreach (var reference in new[] { compilation3.ToMetadataReference(), compilation3.EmitToImageReference() }) { var compilation4 = CreateCompilation(source3, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M1 M2", verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation5 = CreateCompilation(source4, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics( // (6,12): error CS0122: 'I1.M1()' is inaccessible due to its protection level // I1.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(6, 12), // (7,12): error CS0122: 'I1.M2()' is inaccessible due to its protection level // I1.M2(); Diagnostic(ErrorCode.ERR_BadAccess, "M2").WithArguments("I1.M2()").WithLocation(7, 12), // (8,12): error CS0122: 'I1.M3()' is inaccessible due to its protection level // I1.M3(); Diagnostic(ErrorCode.ERR_BadAccess, "M3").WithArguments("I1.M3()").WithLocation(8, 12) ); var compilation6 = CreateCompilation(source1, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation6.VerifyDiagnostics( // (8,12): error CS0122: 'I1.M3()' is inaccessible due to its protection level // I1.M3(); Diagnostic(ErrorCode.ERR_BadAccess, "M3").WithArguments("I1.M3()").WithLocation(8, 12) ); } void validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var tuple in new[] { (name: "M1", access: Accessibility.Protected), (name: "M2", access: Accessibility.ProtectedOrInternal), (name: "M3", access: Accessibility.ProtectedAndInternal) }) { var m1 = i1.GetMember<MethodSymbol>(tuple.name); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.True(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(tuple.access, m1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(m1)); } } } [Fact] public void MethodModifiers_34() { var source1 = @" public interface I1 { protected abstract void M1(); public void M2() => M1(); } "; var source21 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M1(); } public void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source21 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); var expected = new DiagnosticDescription[] { // (10,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(10, 17), // (7,11): error CS1540: Cannot access protected member 'I1.M1()' via a qualifier of type 'I1'; the qualifier must be of type 'Test1' (or derived from it) // x.M1(); Diagnostic(ErrorCode.ERR_BadProtectedAccess, "M1").WithArguments("I1.M1()", "I1", "Test1").WithLocation(7, 11) }; compilation1.VerifyDiagnostics(expected); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.Protected); var source22 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public void M1() { System.Console.WriteLine(""M1""); } } "; compilation1 = CreateCompilation(source22 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, Accessibility.Protected)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.Protected); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Protected); var source3 = @" class Test2 : I1 { } "; foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source21, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expected); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.Protected); compilation3 = CreateCompilation(source22, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, Accessibility.Protected)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.Protected); var compilation5 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.M1()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(2, 15) ); ValidateI1M1NotImplemented(compilation5, "Test2"); } } [Fact] public void MethodModifiers_35() { var source1 = @" public interface I1 { protected internal abstract void M1(); public void M2() => M1(); } "; var source21 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M1(); } public virtual void M1() { System.Console.WriteLine(""M1""); } } "; var source22 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public virtual void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source21 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,25): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(10, 25) ); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.ProtectedOrInternal); compilation1 = CreateCompilation(source21 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, Accessibility.ProtectedOrInternal)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.ProtectedOrInternal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.ProtectedOrInternal); var source3 = @" class Test2 : I1 { } "; foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source21, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (10,25): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(10, 25), // (7,11): error CS1540: Cannot access protected member 'I1.M1()' via a qualifier of type 'I1'; the qualifier must be of type 'Test1' (or derived from it) // x.M1(); Diagnostic(ErrorCode.ERR_BadProtectedAccess, "M1").WithArguments("I1.M1()", "I1", "Test1").WithLocation(7, 11) ); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.ProtectedOrInternal); compilation3 = CreateCompilation(source22, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, Accessibility.ProtectedOrInternal)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.ProtectedOrInternal); var compilation5 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.M1()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(2, 15) ); ValidateI1M1NotImplemented(compilation5, "Test2"); } } [Fact] public void MethodModifiers_36() { var source1 = @" public interface I1 { private protected abstract void M1(); public void M2() => M1(); } "; var source21 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M1(); } public void M1() { System.Console.WriteLine(""M1""); } } "; var source22 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source21 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (10,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(10, 17), // (7,11): error CS1540: Cannot access protected member 'I1.M1()' via a qualifier of type 'I1'; the qualifier must be of type 'Test1' (or derived from it) // x.M1(); Diagnostic(ErrorCode.ERR_BadProtectedAccess, "M1").WithArguments("I1.M1()", "I1", "Test1").WithLocation(7, 11) ); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.ProtectedAndInternal); compilation1 = CreateCompilation(source22 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "M1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersImplicit_10(m, Accessibility.ProtectedAndInternal)).VerifyDiagnostics(); ValidateMethodModifiersImplicit_10(compilation1.SourceModule, Accessibility.ProtectedAndInternal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.ProtectedAndInternal); var source3 = @" class Test2 : I1 { } "; foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source21, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (10,17): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(10, 17), // (7,11): error CS0122: 'I1.M1()' is inaccessible due to its protection level // x.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(7, 11) ); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.ProtectedAndInternal); compilation3 = CreateCompilation(source22, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (10,17): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(10, 17) ); ValidateMethodModifiersImplicit_10(compilation3.SourceModule, Accessibility.ProtectedAndInternal); var compilation5 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.M1()' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.M1()").WithLocation(2, 15) ); ValidateI1M1NotImplemented(compilation5, "Test2"); } } [Fact] public void MethodModifiers_37() { var source1 = @" public interface I1 { protected abstract void M1(); static void M2(I1 x) => x.M1(); } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); I1.M2(x); } void I1.M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicit_10(m, Accessibility.Protected)); ValidateMethodModifiersExplicit_10(compilation1.SourceModule, Accessibility.Protected); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.Protected); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var targetFramework = ExecutionConditionUtil.IsMonoOrCoreClr ? TargetFramework.Net50 : TargetFramework.NetFramework; var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: targetFramework); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: "M1", symbolValidator: (m) => ValidateMethodModifiersExplicit_10(m, Accessibility.Protected)); ValidateMethodModifiersExplicit_10(compilation3.SourceModule, Accessibility.Protected); } } [Fact] public void MethodModifiers_38() { var source1 = @" public interface I1 { protected internal abstract void M1(); static void M2(I1 x) => x.M1(); } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); I1.M2(x); } void I1.M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicit_10(m, Accessibility.ProtectedOrInternal)); ValidateMethodModifiersExplicit_10(compilation1.SourceModule, Accessibility.ProtectedOrInternal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.ProtectedOrInternal); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var targetFramework = ExecutionConditionUtil.IsMonoOrCoreClr ? TargetFramework.Net50 : TargetFramework.NetFramework; var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: targetFramework); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: "M1", symbolValidator: (m) => ValidateMethodModifiersExplicit_10(m, Accessibility.ProtectedOrInternal)); ValidateMethodModifiersExplicit_10(compilation3.SourceModule, Accessibility.ProtectedOrInternal); } } [Fact] public void MethodModifiers_39() { var source1 = @" public interface I1 { private protected abstract void M1(); static void M2(I1 x) => x.M1(); } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); I1.M2(x); } void I1.M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateMethodModifiersExplicit_10(m, Accessibility.ProtectedAndInternal)); ValidateMethodModifiersExplicit_10(compilation1.SourceModule, Accessibility.ProtectedAndInternal); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation2.VerifyDiagnostics(); ValidateMethodModifiers_10(compilation2.GetTypeByMetadataName("I1").GetMember<MethodSymbol>("M1"), Accessibility.ProtectedAndInternal); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation3.VerifyDiagnostics( // (10,13): error CS0122: 'I1.M1()' is inaccessible due to its protection level // void I1.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.M1()").WithLocation(10, 13) ); ValidateMethodModifiersExplicit_10(compilation3.SourceModule, Accessibility.ProtectedAndInternal); } } [Theory] [CombinatorialData] public void MethodModifiers_40(bool isStatic) { string declModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + declModifiers + @" protected abstract void M1(); "; if (!isStatic) { source1 += @" public void M2() => M1(); "; } else { source1 += @" public static void M2<T>() where T : I1 { T.M1(); } "; } source1 += @" } public class Test2 : I1 { " + declModifiers + @" void I1.M1() { } } "; var source2 = @" class Test1 : Test2, I1 { " + declModifiers + @" public void M1() { System.Console.WriteLine(""Test1.M1""); } "; if (!isStatic) { source2 += @" static void Main() { I1 x = new Test1(); x.M2(); } "; } else { source2 += @" static void Main() { Test<Test1>(); } static void Test<T>() where T : I1 { I1.M2<T>(); } "; } source2 += @" } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.Protected, expectedIn9: !isStatic ? ExpectedDiagnostics( // (5,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(5, 17) ) : ExpectedDiagnostics( // (24,29): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // protected abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "9.0", "11.0").WithLocation(24, 29), // (29,9): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // T.M1(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "T").WithArguments("static abstract members in interfaces", "11.0").WithLocation(29, 9), // (36,13): error CS8703: The modifier 'static' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // void I1.M1() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "9.0", "11.0").WithLocation(36, 13) ), expectedIn9AcrossAssemblyBoundaries: !isStatic ? ExpectedDiagnostics( // (5,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(5, 17) ) : ExpectedDiagnostics( // (5,17): error CS8706: 'Test1.M1()' cannot implement interface member 'I1.M1()' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version '11.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "M1").WithArguments("Test1.M1()", "I1.M1()", "Test1", "static abstract members in interfaces", "9.0", "11.0").WithLocation(5, 17) ), expectedAcrossAssemblyBoundaries: Array.Empty<DiagnosticDescription>(), isStatic: isStatic ); } [Fact] public void MethodModifiers_41() { var source1 = @" public interface I1 { protected internal abstract void M1(); public void M2() => M1(); } public class Test2 : I1 { void I1.M1() { } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.M2(); } public void M1() { System.Console.WriteLine(""Test1.M1""); } } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.ProtectedOrInternal, // (10,17): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(10, 17) ); } [Fact] public void MethodModifiers_42() { var source1 = @" public interface I1 { private protected abstract void M1(); public void M2() => M1(); } public class Test2 : I1 { void I1.M1() { } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.M2(); } public virtual void M1() { System.Console.WriteLine(""Test1.M1""); } } "; ValidateMethodModifiers_10_02(source1, source2, Accessibility.ProtectedAndInternal, expectedIn9: ExpectedDiagnostics( // (10,25): error CS8704: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()", "9.0", "10.0").WithLocation(10, 25) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (10,25): error CS9044: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implicitly implement an inaccessible member. // public virtual void M1() Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "M1").WithArguments("Test1", "I1.M1()", "Test1.M1()").WithLocation(10, 25) ) ); } [Fact] public void MethodModifiers_43() { var source1 = @" public interface I1 { protected void M1() { System.Console.WriteLine(""M1""); } void M2() {M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: validate1); validate1(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); validateMethod(m1); } foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: validate1); validate1(compilation3.SourceModule); } void validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var m1 = i1.GetMember<MethodSymbol>("M1"); validateMethod(m1); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); } void validateMethod(MethodSymbol m1) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Protected, m1.DeclaredAccessibility); } } [Fact] public void MethodModifiers_44() { var source1 = @" public interface I1 { protected internal void M1() { System.Console.WriteLine(""M1""); } void M2() {M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: validate1); validate1(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); validateMethod(m1); } foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: validate1); validate1(compilation3.SourceModule); } void validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var m1 = i1.GetMember<MethodSymbol>("M1"); validateMethod(m1); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); } void validateMethod(MethodSymbol m1) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, m1.DeclaredAccessibility); } } [Fact] public void MethodModifiers_45() { var source1 = @" public interface I1 { private protected void M1() { System.Console.WriteLine(""M1""); } void M2() {M1();} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: validate1); validate1(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var m1 = i1.GetMember<MethodSymbol>("M1"); validateMethod(m1); } foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "M1" : null, verify: VerifyOnMonoOrCoreClr, symbolValidator: validate1); validate1(compilation3.SourceModule); } void validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var m1 = i1.GetMember<MethodSymbol>("M1"); validateMethod(m1); Assert.Same(m1, test1.FindImplementationForInterfaceMember(m1)); } void validateMethod(MethodSymbol m1) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, m1.DeclaredAccessibility); } } [Fact] public void ImplicitThisIsAllowed_03() { var source1 = @" public interface I1 { public int F1; void M1() { System.Console.WriteLine(""I1.M1""); } int P1 { get { System.Console.WriteLine(""I1.get_P1""); return 0; } set => System.Console.WriteLine(""I1.set_P1""); } event System.Action E1 { add => System.Console.WriteLine(""I1.add_E1""); remove => System.Console.WriteLine(""I1.remove_E1""); } public interface I2 : I1 { void M2() { M1(); P1 = P1; E1 += null; E1 -= null; F1 = 0; } } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS0525: Interfaces cannot contain fields // public int F1; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16) ); } [Fact] public void ImplicitThisIsAllowed_04() { var source1 = @" public interface I1 { public int F1; void M1() { System.Console.WriteLine(""I1.M1""); } int P1 { get { System.Console.WriteLine(""I1.get_P1""); return 0; } set => System.Console.WriteLine(""I1.set_P1""); } event System.Action E1 { add => System.Console.WriteLine(""I1.add_E1""); remove => System.Console.WriteLine(""I1.remove_E1""); } public interface I2 { void M2() { M1(); P1 = P1; E1 += null; E1 -= null; F1 = 0; } } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS0525: Interfaces cannot contain fields // public int F1; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 16), // (31,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.M1()' // M1(); Diagnostic(ErrorCode.ERR_ObjectRequired, "M1").WithArguments("I1.M1()").WithLocation(31, 13), // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.P1' // P1 = P1; Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("I1.P1").WithLocation(32, 13), // (32,18): error CS0120: An object reference is required for the non-static field, method, or property 'I1.P1' // P1 = P1; Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("I1.P1").WithLocation(32, 18), // (33,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.E1' // E1 += null; Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("I1.E1").WithLocation(33, 13), // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.E1' // E1 -= null; Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("I1.E1").WithLocation(34, 13), // (35,13): error CS0120: An object reference is required for the non-static field, method, or property 'I1.F1' // F1 = 0; Diagnostic(ErrorCode.ERR_ObjectRequired, "F1").WithArguments("I1.F1").WithLocation(35, 13) ); } [Fact] public void ImplicitThisIsAllowed_05() { var source1 = @" public class C1 { public int F1; void M1() { System.Console.WriteLine(""I1.M1""); } int P1 { get { System.Console.WriteLine(""I1.get_P1""); return 0; } set => System.Console.WriteLine(""I1.set_P1""); } event System.Action E1 { add => System.Console.WriteLine(""I1.add_E1""); remove => System.Console.WriteLine(""I1.remove_E1""); } public interface I2 { void M2() { M1(); P1 = P1; E1 += null; E1 -= null; F1 = 0; } } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (31,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.M1()' // M1(); Diagnostic(ErrorCode.ERR_ObjectRequired, "M1").WithArguments("C1.M1()").WithLocation(31, 13), // (32,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.P1' // P1 = P1; Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("C1.P1").WithLocation(32, 13), // (32,18): error CS0120: An object reference is required for the non-static field, method, or property 'C1.P1' // P1 = P1; Diagnostic(ErrorCode.ERR_ObjectRequired, "P1").WithArguments("C1.P1").WithLocation(32, 18), // (33,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.E1' // E1 += null; Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("C1.E1").WithLocation(33, 13), // (34,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.E1' // E1 -= null; Diagnostic(ErrorCode.ERR_ObjectRequired, "E1").WithArguments("C1.E1").WithLocation(34, 13), // (35,13): error CS0120: An object reference is required for the non-static field, method, or property 'C1.F1' // F1 = 0; Diagnostic(ErrorCode.ERR_ObjectRequired, "F1").WithArguments("C1.F1").WithLocation(35, 13) ); } [Fact] public void PropertyModifiers_01() { var source1 = @" public interface I1 { public int P01 {get; set;} protected int P02 {get;} protected internal int P03 {set;} internal int P04 {get;} private int P05 {set;} static int P06 {get;} virtual int P07 {set;} sealed int P08 {get;} override int P09 {set;} abstract int P10 {get;} extern int P11 {get; set;} int P12 { public get; set;} int P13 { get; protected set;} int P14 { protected internal get; set;} int P15 { get; internal set;} int P16 { private get; set;} int P17 { private get;} private protected int P18 {get;} int P19 { get; private protected set;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial // private int P05 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial // virtual int P07 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial // sealed int P08 {get;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), // (12,18): error CS0106: The modifier 'override' is not valid for this item // override int P09 {set;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' // int P12 { public get; set;} Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors // int P16 { private get; set;} Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int P17 { private get;} Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26) ); ValidateSymbolsPropertyModifiers_01(compilation1); } private static void ValidateSymbolsPropertyModifiers_01(CSharpCompilation compilation1) { var i1 = compilation1.GetTypeByMetadataName("I1"); var p01 = i1.GetMember<PropertySymbol>("P01"); Assert.True(p01.IsAbstract); Assert.False(p01.IsVirtual); Assert.False(p01.IsSealed); Assert.False(p01.IsStatic); Assert.False(p01.IsExtern); Assert.False(p01.IsOverride); Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); ValidateP01Accessor(p01.GetMethod); ValidateP01Accessor(p01.SetMethod); void ValidateP01Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p02 = i1.GetMember<PropertySymbol>("P02"); var p02get = p02.GetMethod; Assert.True(p02.IsAbstract); Assert.False(p02.IsVirtual); Assert.False(p02.IsSealed); Assert.False(p02.IsStatic); Assert.False(p02.IsExtern); Assert.False(p02.IsOverride); Assert.Equal(Accessibility.Protected, p02.DeclaredAccessibility); Assert.True(p02get.IsAbstract); Assert.False(p02get.IsVirtual); Assert.True(p02get.IsMetadataVirtual()); Assert.False(p02get.IsSealed); Assert.False(p02get.IsStatic); Assert.False(p02get.IsExtern); Assert.False(p02get.IsAsync); Assert.False(p02get.IsOverride); Assert.Equal(Accessibility.Protected, p02get.DeclaredAccessibility); var p03 = i1.GetMember<PropertySymbol>("P03"); var p03set = p03.SetMethod; Assert.True(p03.IsAbstract); Assert.False(p03.IsVirtual); Assert.False(p03.IsSealed); Assert.False(p03.IsStatic); Assert.False(p03.IsExtern); Assert.False(p03.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, p03.DeclaredAccessibility); Assert.True(p03set.IsAbstract); Assert.False(p03set.IsVirtual); Assert.True(p03set.IsMetadataVirtual()); Assert.False(p03set.IsSealed); Assert.False(p03set.IsStatic); Assert.False(p03set.IsExtern); Assert.False(p03set.IsAsync); Assert.False(p03set.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, p03set.DeclaredAccessibility); var p04 = i1.GetMember<PropertySymbol>("P04"); var p04get = p04.GetMethod; Assert.True(p04.IsAbstract); Assert.False(p04.IsVirtual); Assert.False(p04.IsSealed); Assert.False(p04.IsStatic); Assert.False(p04.IsExtern); Assert.False(p04.IsOverride); Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); Assert.True(p04get.IsAbstract); Assert.False(p04get.IsVirtual); Assert.True(p04get.IsMetadataVirtual()); Assert.False(p04get.IsSealed); Assert.False(p04get.IsStatic); Assert.False(p04get.IsExtern); Assert.False(p04get.IsAsync); Assert.False(p04get.IsOverride); Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); var p05 = i1.GetMember<PropertySymbol>("P05"); var p05set = p05.SetMethod; Assert.False(p05.IsAbstract); Assert.False(p05.IsVirtual); Assert.False(p05.IsSealed); Assert.False(p05.IsStatic); Assert.False(p05.IsExtern); Assert.False(p05.IsOverride); Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); Assert.False(p05set.IsAbstract); Assert.False(p05set.IsVirtual); Assert.False(p05set.IsMetadataVirtual()); Assert.False(p05set.IsSealed); Assert.False(p05set.IsStatic); Assert.False(p05set.IsExtern); Assert.False(p05set.IsAsync); Assert.False(p05set.IsOverride); Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); var p06 = i1.GetMember<PropertySymbol>("P06"); var p06get = p06.GetMethod; Assert.False(p06.IsAbstract); Assert.False(p06.IsVirtual); Assert.False(p06.IsSealed); Assert.True(p06.IsStatic); Assert.False(p06.IsExtern); Assert.False(p06.IsOverride); Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); Assert.False(p06get.IsAbstract); Assert.False(p06get.IsVirtual); Assert.False(p06get.IsMetadataVirtual()); Assert.False(p06get.IsSealed); Assert.True(p06get.IsStatic); Assert.False(p06get.IsExtern); Assert.False(p06get.IsAsync); Assert.False(p06get.IsOverride); Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); var p07 = i1.GetMember<PropertySymbol>("P07"); var p07set = p07.SetMethod; Assert.False(p07.IsAbstract); Assert.True(p07.IsVirtual); Assert.False(p07.IsSealed); Assert.False(p07.IsStatic); Assert.False(p07.IsExtern); Assert.False(p07.IsOverride); Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); Assert.False(p07set.IsAbstract); Assert.True(p07set.IsVirtual); Assert.True(p07set.IsMetadataVirtual()); Assert.False(p07set.IsSealed); Assert.False(p07set.IsStatic); Assert.False(p07set.IsExtern); Assert.False(p07set.IsAsync); Assert.False(p07set.IsOverride); Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); var p08 = i1.GetMember<PropertySymbol>("P08"); var p08get = p08.GetMethod; Assert.False(p08.IsAbstract); Assert.False(p08.IsVirtual); Assert.False(p08.IsSealed); Assert.False(p08.IsStatic); Assert.False(p08.IsExtern); Assert.False(p08.IsOverride); Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); Assert.False(p08get.IsAbstract); Assert.False(p08get.IsVirtual); Assert.False(p08get.IsMetadataVirtual()); Assert.False(p08get.IsSealed); Assert.False(p08get.IsStatic); Assert.False(p08get.IsExtern); Assert.False(p08get.IsAsync); Assert.False(p08get.IsOverride); Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); var p09 = i1.GetMember<PropertySymbol>("P09"); var p09set = p09.SetMethod; Assert.True(p09.IsAbstract); Assert.False(p09.IsVirtual); Assert.False(p09.IsSealed); Assert.False(p09.IsStatic); Assert.False(p09.IsExtern); Assert.False(p09.IsOverride); Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); Assert.True(p09set.IsAbstract); Assert.False(p09set.IsVirtual); Assert.True(p09set.IsMetadataVirtual()); Assert.False(p09set.IsSealed); Assert.False(p09set.IsStatic); Assert.False(p09set.IsExtern); Assert.False(p09set.IsAsync); Assert.False(p09set.IsOverride); Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); var p10 = i1.GetMember<PropertySymbol>("P10"); var p10get = p10.GetMethod; Assert.True(p10.IsAbstract); Assert.False(p10.IsVirtual); Assert.False(p10.IsSealed); Assert.False(p10.IsStatic); Assert.False(p10.IsExtern); Assert.False(p10.IsOverride); Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); Assert.True(p10get.IsAbstract); Assert.False(p10get.IsVirtual); Assert.True(p10get.IsMetadataVirtual()); Assert.False(p10get.IsSealed); Assert.False(p10get.IsStatic); Assert.False(p10get.IsExtern); Assert.False(p10get.IsAsync); Assert.False(p10get.IsOverride); Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); var p11 = i1.GetMember<PropertySymbol>("P11"); Assert.False(p11.IsAbstract); Assert.True(p11.IsVirtual); Assert.False(p11.IsSealed); Assert.False(p11.IsStatic); Assert.True(p11.IsExtern); Assert.False(p11.IsOverride); Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); ValidateP11Accessor(p11.GetMethod); ValidateP11Accessor(p11.SetMethod); void ValidateP11Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p12 = i1.GetMember<PropertySymbol>("P12"); Assert.True(p12.IsAbstract); Assert.False(p12.IsVirtual); Assert.False(p12.IsSealed); Assert.False(p12.IsStatic); Assert.False(p12.IsExtern); Assert.False(p12.IsOverride); Assert.Equal(Accessibility.Public, p12.DeclaredAccessibility); ValidateP12Accessor(p12.GetMethod); ValidateP12Accessor(p12.SetMethod); void ValidateP12Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p13 = i1.GetMember<PropertySymbol>("P13"); Assert.True(p13.IsAbstract); Assert.False(p13.IsVirtual); Assert.False(p13.IsSealed); Assert.False(p13.IsStatic); Assert.False(p13.IsExtern); Assert.False(p13.IsOverride); Assert.Equal(Accessibility.Public, p13.DeclaredAccessibility); ValidateP13Accessor(p13.GetMethod, Accessibility.Public); ValidateP13Accessor(p13.SetMethod, Accessibility.Protected); void ValidateP13Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p14 = i1.GetMember<PropertySymbol>("P14"); Assert.True(p14.IsAbstract); Assert.False(p14.IsVirtual); Assert.False(p14.IsSealed); Assert.False(p14.IsStatic); Assert.False(p14.IsExtern); Assert.False(p14.IsOverride); Assert.Equal(Accessibility.Public, p14.DeclaredAccessibility); ValidateP14Accessor(p14.GetMethod, Accessibility.ProtectedOrInternal); ValidateP14Accessor(p14.SetMethod, Accessibility.Public); void ValidateP14Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p15 = i1.GetMember<PropertySymbol>("P15"); Assert.True(p15.IsAbstract); Assert.False(p15.IsVirtual); Assert.False(p15.IsSealed); Assert.False(p15.IsStatic); Assert.False(p15.IsExtern); Assert.False(p15.IsOverride); Assert.Equal(Accessibility.Public, p15.DeclaredAccessibility); ValidateP15Accessor(p15.GetMethod, Accessibility.Public); ValidateP15Accessor(p15.SetMethod, Accessibility.Internal); void ValidateP15Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p16 = i1.GetMember<PropertySymbol>("P16"); Assert.True(p16.IsAbstract); Assert.False(p16.IsVirtual); Assert.False(p16.IsSealed); Assert.False(p16.IsStatic); Assert.False(p16.IsExtern); Assert.False(p16.IsOverride); Assert.Equal(Accessibility.Public, p16.DeclaredAccessibility); ValidateP16Accessor(p16.GetMethod, Accessibility.Private); ValidateP16Accessor(p16.SetMethod, Accessibility.Public); void ValidateP16Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p17 = i1.GetMember<PropertySymbol>("P17"); var p17get = p17.GetMethod; Assert.True(p17.IsAbstract); Assert.False(p17.IsVirtual); Assert.False(p17.IsSealed); Assert.False(p17.IsStatic); Assert.False(p17.IsExtern); Assert.False(p17.IsOverride); Assert.Equal(Accessibility.Public, p17.DeclaredAccessibility); Assert.True(p17get.IsAbstract); Assert.False(p17get.IsVirtual); Assert.True(p17get.IsMetadataVirtual()); Assert.False(p17get.IsSealed); Assert.False(p17get.IsStatic); Assert.False(p17get.IsExtern); Assert.False(p17get.IsAsync); Assert.False(p17get.IsOverride); Assert.Equal(Accessibility.Private, p17get.DeclaredAccessibility); var p18 = i1.GetMember<PropertySymbol>("P18"); var p18get = p18.GetMethod; Assert.True(p18.IsAbstract); Assert.False(p18.IsVirtual); Assert.False(p18.IsSealed); Assert.False(p18.IsStatic); Assert.False(p18.IsExtern); Assert.False(p18.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, p18.DeclaredAccessibility); Assert.True(p18get.IsAbstract); Assert.False(p18get.IsVirtual); Assert.True(p18get.IsMetadataVirtual()); Assert.False(p18get.IsSealed); Assert.False(p18get.IsStatic); Assert.False(p18get.IsExtern); Assert.False(p18get.IsAsync); Assert.False(p18get.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, p18get.DeclaredAccessibility); var p19 = i1.GetMember<PropertySymbol>("P19"); Assert.True(p19.IsAbstract); Assert.False(p19.IsVirtual); Assert.False(p19.IsSealed); Assert.False(p19.IsStatic); Assert.False(p19.IsExtern); Assert.False(p19.IsOverride); Assert.Equal(Accessibility.Public, p19.DeclaredAccessibility); ValidateP13Accessor(p19.GetMethod, Accessibility.Public); ValidateP13Accessor(p19.SetMethod, Accessibility.ProtectedAndInternal); } [Fact] public void PropertyModifiers_02() { var source1 = @" public interface I1 { public int P01 {get; set;} protected int P02 {get;} protected internal int P03 {set;} internal int P04 {get;} private int P05 {set;} static int P06 {get;} virtual int P07 {set;} sealed int P08 {get;} override int P09 {set;} abstract int P10 {get;} extern int P11 {get; set;} int P12 { public get; set;} int P13 { get; protected set;} int P14 { protected internal get; set;} int P15 { get; internal set;} int P16 { private get; set;} int P17 { private get;} private protected int P18 {get;} int P19 { get; private protected set;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,16): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public int P01 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P01").WithArguments("public", "7.3", "8.0").WithLocation(4, 16), // (5,19): error CS8703: The modifier 'protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // protected int P02 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P02").WithArguments("protected", "7.3", "8.0").WithLocation(5, 19), // (6,28): error CS8703: The modifier 'protected internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // protected internal int P03 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P03").WithArguments("protected internal", "7.3", "8.0").WithLocation(6, 28), // (7,18): error CS8503: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal int P04 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P04").WithArguments("internal", "7.3", "8.0").WithLocation(7, 18), // (8,17): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private int P05 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P05").WithArguments("private", "7.3", "8.0").WithLocation(8, 17), // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial // private int P05 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), // (9,16): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static int P06 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P06").WithArguments("static", "7.3", "8.0").WithLocation(9, 16), // (10,17): error CS8503: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual int P07 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P07").WithArguments("virtual", "7.3", "8.0").WithLocation(10, 17), // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial // virtual int P07 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), // (11,16): error CS8503: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // sealed int P08 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P08").WithArguments("sealed", "7.3", "8.0").WithLocation(11, 16), // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial // sealed int P08 {get;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), // (12,18): error CS0106: The modifier 'override' is not valid for this item // override int P09 {set;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), // (13,18): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // abstract int P10 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P10").WithArguments("abstract", "7.3", "8.0").WithLocation(13, 18), // (14,16): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern int P11 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P11").WithArguments("extern", "7.3", "8.0").WithLocation(14, 16), // (16,22): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P12 { public get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("public", "7.3", "8.0").WithLocation(16, 22), // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' // int P12 { public get; set;} Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), // (17,30): error CS8703: The modifier 'protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P13 { get; protected set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("protected", "7.3", "8.0").WithLocation(17, 30), // (18,34): error CS8703: The modifier 'protected internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P14 { protected internal get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("protected internal", "7.3", "8.0").WithLocation(18, 34), // (19,29): error CS8503: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P15 { get; internal set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("internal", "7.3", "8.0").WithLocation(19, 29), // (20,23): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P16 { private get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("private", "7.3", "8.0").WithLocation(20, 23), // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors // int P16 { private get; set;} Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), // (21,23): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P17 { private get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("private", "7.3", "8.0").WithLocation(21, 23), // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int P17 { private get;} Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), // (23,27): error CS8703: The modifier 'private protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private protected int P18 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P18").WithArguments("private protected", "7.3", "8.0").WithLocation(23, 27), // (24,38): error CS8703: The modifier 'private protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // int P19 { get; private protected set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("private protected", "7.3", "8.0").WithLocation(24, 38), // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26) ); ValidateSymbolsPropertyModifiers_01(compilation1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (5,19): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected int P02 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P02").WithLocation(5, 19), // (6,28): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal int P03 {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P03").WithLocation(6, 28), // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial // private int P05 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), // (9,21): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int P06 {get;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(9, 21), // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial // virtual int P07 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial // sealed int P08 {get;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), // (12,18): error CS0106: The modifier 'override' is not valid for this item // override int P09 {set;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), // (14,21): error CS8701: Target runtime doesn't support default interface implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(14, 21), // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), // (14,26): error CS8701: Target runtime doesn't support default interface implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(14, 26), // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26), // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' // int P12 { public get; set;} Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), // (17,30): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // int P13 { get; protected set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(17, 30), // (18,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // int P14 { protected internal get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "get").WithLocation(18, 34), // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors // int P16 { private get; set;} Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int P17 { private get;} Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), // (23,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected int P18 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P18").WithLocation(23, 27), // (24,38): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // int P19 { get; private protected set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(24, 38) ); ValidateSymbolsPropertyModifiers_01(compilation2); var expected = new[] { // (5,19): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected int P02 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P02").WithLocation(5, 19), // (6,28): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal int P03 {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P03").WithLocation(6, 28), // (8,22): error CS0501: 'I1.P05.set' must declare a body because it is not marked abstract, extern, or partial // private int P05 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P05.set").WithLocation(8, 22), // (10,22): error CS0501: 'I1.P07.set' must declare a body because it is not marked abstract, extern, or partial // virtual int P07 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.P07.set").WithLocation(10, 22), // (11,21): error CS0501: 'I1.P08.get' must declare a body because it is not marked abstract, extern, or partial // sealed int P08 {get;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P08.get").WithLocation(11, 21), // (12,18): error CS0106: The modifier 'override' is not valid for this item // override int P09 {set;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 18), // (14,21): error CS8701: Target runtime doesn't support default interface implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(14, 21), // (14,21): warning CS0626: Method, operator, or accessor 'I1.P11.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P11.get").WithLocation(14, 21), // (14,26): error CS8701: Target runtime doesn't support default interface implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(14, 26), // (14,26): warning CS0626: Method, operator, or accessor 'I1.P11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P11 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I1.P11.set").WithLocation(14, 26), // (16,22): error CS0273: The accessibility modifier of the 'I1.P12.get' accessor must be more restrictive than the property or indexer 'I1.P12' // int P12 { public get; set;} Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I1.P12.get", "I1.P12").WithLocation(16, 22), // (17,30): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // int P13 { get; protected set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(17, 30), // (18,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // int P14 { protected internal get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "get").WithLocation(18, 34), // (20,23): error CS0442: 'I1.P16.get': abstract properties cannot have private accessors // int P16 { private get; set;} Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P16.get").WithLocation(20, 23), // (21,9): error CS0276: 'I1.P17': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int P17 { private get;} Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P17").WithArguments("I1.P17").WithLocation(21, 9), // (23,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected int P18 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P18").WithLocation(23, 27), // (24,38): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // int P19 { get; private protected set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(24, 38) }; compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(expected); ValidateSymbolsPropertyModifiers_01(compilation2); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(expected); ValidateSymbolsPropertyModifiers_01(compilation2); } [Fact] public void PropertyModifiers_03() { ValidatePropertyImplementation_101(@" public interface I1 { public virtual int P1 { get { System.Console.WriteLine(""get P1""); return 0; } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); _ = i1.P1; } } "); ValidatePropertyImplementation_101(@" public interface I1 { public virtual int P1 { get => Test1.GetP1(); } } class Test1 : I1 { public static int GetP1() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); _ = i1.P1; } } "); ValidatePropertyImplementation_101(@" public interface I1 { public virtual int P1 => Test1.GetP1(); } class Test1 : I1 { public static int GetP1() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); _ = i1.P1; } } "); ValidatePropertyImplementation_102(@" public interface I1 { public virtual int P1 { get { System.Console.WriteLine(""get P1""); return 0; } set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1.P1 = i1.P1; } } "); ValidatePropertyImplementation_102(@" public interface I1 { public virtual int P1 { get => Test1.GetP1(); set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 { public static int GetP1() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); i1.P1 = i1.P1; } } "); ValidatePropertyImplementation_103(@" public interface I1 { public virtual int P1 { set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1.P1 = 1; } } "); ValidatePropertyImplementation_103(@" public interface I1 { public virtual int P1 { set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1.P1 = 1; } } "); } [Fact] public void PropertyModifiers_04() { var source1 = @" public interface I1 { public virtual int P1 { get; } = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,24): error CS8053: Instance properties in interfaces cannot have initializers. // public virtual int P1 { get; } = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P1").WithLocation(4, 24), // (4,29): error CS0501: 'I1.P1.get' must declare a body because it is not marked abstract, extern, or partial // public virtual int P1 { get; } = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P1.get").WithLocation(4, 29) ); ValidatePropertyModifiers_04(compilation1, "P1"); } private static void ValidatePropertyModifiers_04(CSharpCompilation compilation1, string propertyName) { var i1 = compilation1.GlobalNamespace.GetTypeMember("I1"); var p1 = i1.GetMember<PropertySymbol>(propertyName); var p1get = p1.GetMethod; Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.False(p1get.IsAbstract); Assert.True(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); } [Fact] public void PropertyModifiers_05() { var source1 = @" public interface I1 { public abstract int P1 {get; set;} } public interface I2 { int P2 {get; set;} } class Test1 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set => System.Console.WriteLine(""set_P1""); } } class Test2 : I2 { public int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } set => System.Console.WriteLine(""set_P2""); } static void Main() { I1 x = new Test1(); x.P1 = x.P1; I2 y = new Test2(); y.P2 = y.P2; } } "; ValidatePropertyModifiers_05(source1); } private void ValidatePropertyModifiers_05(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: @"get_P1 set_P1 get_P2 set_P2", symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { for (int i = 1; i <= 2; i++) { var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleProperty(i1); var test1P1 = GetSingleProperty(test1); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor(p1.GetMethod, test1P1.GetMethod); ValidateAccessor(p1.SetMethod, test1P1.SetMethod); void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(implementation, test1.FindImplementationForInterfaceMember(accessor)); } } } } private static PropertySymbol GetSingleProperty(NamedTypeSymbol container) { return container.GetMembers().OfType<PropertySymbol>().Single(); } private static PropertySymbol GetSingleProperty(CSharpCompilation compilation, string containerName) { return GetSingleProperty(compilation.GetTypeByMetadataName(containerName)); } private static PropertySymbol GetSingleProperty(ModuleSymbol m, string containerName) { return GetSingleProperty(m.GlobalNamespace.GetTypeMember(containerName)); } [Fact] public void PropertyModifiers_06() { var source1 = @" public interface I1 { public abstract int P1 {get; set;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3); compilation1.VerifyDiagnostics( // (4,25): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("abstract", "7.3", "8.0").WithLocation(4, 25), // (4,25): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("public", "7.3", "8.0").WithLocation(4, 25) ); ValidatePropertyModifiers_06(compilation1, "P1"); } private static void ValidatePropertyModifiers_06(CSharpCompilation compilation1, string propertyName) { var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<PropertySymbol>(propertyName); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); ValidateAccessor(p1.GetMethod); ValidateAccessor(p1.SetMethod); void ValidateAccessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } } [Fact] public void PropertyModifiers_07() { var source1 = @" public interface I1 { public static int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } internal static int P2 { get { System.Console.WriteLine(""get_P2""); return P3; } set { System.Console.WriteLine(""set_P2""); P3 = value; } } private static int P3 { get => Test1.GetP3(); set => System.Console.WriteLine(""set_P3""); } internal static int P4 => Test1.GetP4(); internal static int P5 { get { System.Console.WriteLine(""get_P5""); return 0; } } internal static int P6 { get => Test1.GetP6(); } internal static int P7 { set { System.Console.WriteLine(""set_P7""); } } internal static int P8 { set => System.Console.WriteLine(""set_P8""); } } class Test1 : I1 { static void Main() { I1.P1 = I1.P1; I1.P2 = I1.P2; var x = I1.P4; x = I1.P5; x = I1.P6; I1.P7 = x; I1.P8 = x; } public static int GetP3() { System.Console.WriteLine(""get_P3""); return 0; } public static int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } public static int GetP6() { System.Console.WriteLine(""get_P6""); return 0; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var expected = @"get_P1 set_P1 get_P2 get_P3 set_P2 set_P3 get_P4 get_P5 get_P6 set_P7 set_P8"; CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expected, symbolValidator: Validate); Validate(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (6,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // get Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(6, 9), // (11,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // set Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(11, 9), // (19,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // get Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(19, 9), // (24,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // set Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(24, 9), // (33,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // get => Test1.GetP3(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(33, 9), // (34,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // set => System.Console.WriteLine("set_P3"); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(34, 9), // (37,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int P4 => Test1.GetP4(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "Test1.GetP4()").WithArguments("static members in interfaces", "15.0").WithLocation(37, 31), // (41,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // get Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(41, 9), // (50,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // get => Test1.GetP6(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(50, 9), // (55,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // set Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(55, 9), // (63,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // set => System.Console.WriteLine("set_P8"); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(63, 9) ); Validate(compilation2.SourceModule); compilation2 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: expected, symbolValidator: Validate); Validate(compilation2.SourceModule); compilation2 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: expected, symbolValidator: Validate); Validate(compilation2.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var tuple in new[] { (name: "P1", access: Accessibility.Public), (name: "P2", access: Accessibility.Internal), (name: "P3", access: Accessibility.Private), (name: "P4", access: Accessibility.Internal), (name: "P5", access: Accessibility.Internal), (name: "P6", access: Accessibility.Internal), (name: "P7", access: Accessibility.Internal), (name: "P8", access: Accessibility.Internal)}) { var p1 = i1.GetMember<PropertySymbol>(tuple.name); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(tuple.access, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); switch (tuple.name) { case "P7": case "P8": Assert.Null(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; case "P4": case "P5": case "P6": Assert.Null(p1.SetMethod); ValidateAccessor(p1.GetMethod); break; default: ValidateAccessor(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; } void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(tuple.access, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } } [Fact] public void PropertyModifiers_08() { var source1 = @" public interface I1 { abstract static int P1 {get;} virtual static int P2 {set {}} sealed static int P3 => 0; static int P4 {get;} = 0; } class Test1 : I1 { int I1.P1 => 0; int I1.P2 {set {}} int I1.P3 => 0; int I1.P4 {set {}} } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,25): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // abstract static int P1 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("abstract", "9.0", "11.0").WithLocation(4, 25), // (6,24): error CS8703: The modifier 'virtual' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // virtual static int P2 {set {}} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P2").WithArguments("virtual", "9.0", "11.0").WithLocation(6, 24), // (8,23): error CS8703: The modifier 'sealed' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // sealed static int P3 => 0; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("sealed", "9.0", "11.0").WithLocation(8, 23), // (13,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(13, 15), // (15,12): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented // int I1.P1 => 0; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(15, 12), // (16,12): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented // int I1.P2 {set {}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(16, 12), // (17,12): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented // int I1.P3 => 0; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(17, 12), // (18,12): error CS0539: 'Test1.P4' in explicit interface declaration is not found among members of the interface that can be implemented // int I1.P4 {set {}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test1.P4").WithLocation(18, 12), // (21,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(21, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<PropertySymbol>("P1"); var p1get = p1.GetMethod; Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.True(p1get.IsAbstract); Assert.False(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.True(p1get.IsStatic); Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); var p2 = i1.GetMember<PropertySymbol>("P2"); var p2set = p2.SetMethod; Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.True(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); Assert.False(p2set.IsAbstract); Assert.True(p2set.IsVirtual); Assert.True(p2set.IsMetadataVirtual()); Assert.False(p2set.IsSealed); Assert.True(p2set.IsStatic); Assert.False(p2set.IsExtern); Assert.False(p2set.IsAsync); Assert.False(p2set.IsOverride); Assert.Equal(Accessibility.Public, p2set.DeclaredAccessibility); Assert.Same(p2set, test1.FindImplementationForInterfaceMember(p2set)); var p3 = i1.GetMember<PropertySymbol>("P3"); var p3get = p3.GetMethod; Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.False(p3.IsSealed); Assert.True(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.False(p3get.IsAbstract); Assert.False(p3get.IsVirtual); Assert.False(p3get.IsMetadataVirtual()); Assert.False(p3get.IsSealed); Assert.True(p3get.IsStatic); Assert.False(p3get.IsExtern); Assert.False(p3get.IsAsync); Assert.False(p3get.IsOverride); Assert.Equal(Accessibility.Public, p3get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3get)); } [Fact] public void PropertyModifiers_09() { var source1 = @" public interface I1 { private int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } } sealed void M() { var x = P1; } } public interface I2 { private int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } set { System.Console.WriteLine(""set_P2""); } } sealed void M() { P2 = P2; } } public interface I3 { private int P3 { set { System.Console.WriteLine(""set_P3""); } } sealed void M() { P3 = 0; } } public interface I4 { private int P4 { get => GetP4(); } private int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } sealed void M() { var x = P4; } } public interface I5 { private int P5 { get => GetP5(); set => System.Console.WriteLine(""set_P5""); } private int GetP5() { System.Console.WriteLine(""get_P5""); return 0; } sealed void M() { P5 = P5; } } public interface I6 { private int P6 { set => System.Console.WriteLine(""set_P6""); } sealed void M() { P6 = 0; } } public interface I7 { private int P7 => GetP7(); private int GetP7() { System.Console.WriteLine(""get_P7""); return 0; } sealed void M() { var x = P7; } } class Test1 : I1, I2, I3, I4, I5, I6, I7 { static void Main() { I1 x1 = new Test1(); x1.M(); I2 x2 = new Test1(); x2.M(); I3 x3 = new Test1(); x3.M(); I4 x4 = new Test1(); x4.M(); I5 x5 = new Test1(); x5.M(); I6 x6 = new Test1(); x6.M(); I7 x7 = new Test1(); x7.M(); } } "; ValidatePropertyModifiers_09(source1); } private void ValidatePropertyModifiers_09(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 get_P2 set_P2 set_P3 get_P4 get_P5 set_P5 set_P6 get_P7 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); for (int i = 1; i <= 7; i++) { var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleProperty(i1); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); switch (i) { case 3: case 6: Assert.Null(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; case 1: case 4: case 7: Assert.Null(p1.SetMethod); ValidateAccessor(p1.GetMethod); break; default: ValidateAccessor(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; } void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } } [Fact] public void PropertyModifiers_10() { var source1 = @" public interface I1 { abstract private int P1 { get; } virtual private int P2 => 0; sealed private int P3 { get => 0; set {} } private int P4 {get;} = 0; } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,26): error CS0621: 'I1.P1': virtual or abstract members cannot be private // abstract private int P1 { get; } Diagnostic(ErrorCode.ERR_VirtualPrivate, "P1").WithArguments("I1.P1").WithLocation(4, 26), // (6,25): error CS0621: 'I1.P2': virtual or abstract members cannot be private // virtual private int P2 => 0; Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I1.P2").WithLocation(6, 25), // (8,24): error CS0238: 'I1.P3' cannot be sealed because it is not an override // sealed private int P3 Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 24), // (14,17): error CS8053: Instance properties in interfaces cannot have initializers. // private int P4 {get;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P4").WithLocation(14, 17), // (14,21): error CS0501: 'I1.P4.get' must declare a body because it is not marked abstract, extern, or partial // private int P4 {get;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P4.get").WithLocation(14, 21), // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(17, 15) ); ValidatePropertyModifiers_10(compilation1); } private static void ValidatePropertyModifiers_10(CSharpCompilation compilation1) { var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMembers().OfType<PropertySymbol>().ElementAt(0); var p1get = p1.GetMethod; Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.True(p1get.IsAbstract); Assert.False(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Private, p1get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); var p2 = i1.GetMembers().OfType<PropertySymbol>().ElementAt(1); var p2get = p2.GetMethod; Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); Assert.False(p2get.IsAbstract); Assert.True(p2get.IsVirtual); Assert.True(p2get.IsMetadataVirtual()); Assert.False(p2get.IsSealed); Assert.False(p2get.IsStatic); Assert.False(p2get.IsExtern); Assert.False(p2get.IsAsync); Assert.False(p2get.IsOverride); Assert.Equal(Accessibility.Private, p2get.DeclaredAccessibility); Assert.Same(p2get, test1.FindImplementationForInterfaceMember(p2get)); var p3 = i1.GetMembers().OfType<PropertySymbol>().ElementAt(2); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.True(p3.IsSealed); Assert.False(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Private, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.GetMethod); ValidateP3Accessor(p3.SetMethod); void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.True(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } var p4 = i1.GetMembers().OfType<PropertySymbol>().ElementAt(3); var p4get = p4.GetMethod; Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); Assert.False(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.False(p4get.IsAbstract); Assert.False(p4get.IsVirtual); Assert.False(p4get.IsMetadataVirtual()); Assert.False(p4get.IsSealed); Assert.False(p4get.IsStatic); Assert.False(p4get.IsExtern); Assert.False(p4get.IsAsync); Assert.False(p4get.IsOverride); Assert.Equal(Accessibility.Private, p4get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4get)); } [Fact] public void PropertyModifiers_11_01() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} sealed void Test() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_01(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9), // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(17, 9) ), expectedNoImplementation: ExpectedDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(12, 9), // (17,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(17, 9) ) ); } private void ValidatePropertyModifiers_11_01(string source1, string source2, Accessibility accessibility, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedNoImplementation) { ValidatePropertyModifiers_11_01(source1, source2, accessibility, expectedIn9, expectedNoImplementation, expectedAcrossAssemblyBoundaries: Array.Empty<DiagnosticDescription>()); } private void ValidatePropertyModifiers_11_01(string source1, string source2, Accessibility accessibility, DiagnosticDescription[] expectedIn9, DiagnosticDescription[] expectedNoImplementation, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expectedIn9); ValidatePropertyModifiers_11(compilation1.SourceModule, accessibility); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyModifiers_11(m, accessibility)).VerifyDiagnostics(); ValidatePropertyModifiers_11(compilation1.SourceModule, accessibility); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var p1 = GetSingleProperty(i1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; ValidatePropertyModifiers_11(p1, accessibility); ValidatePropertyAccessorModifiers_11(p1get, accessibility); ValidatePropertyAccessorModifiers_11(p1set, accessibility); } var source3 = @" class Test2 : I1 { } "; foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); ValidatePropertyModifiers_11(compilation3.SourceModule, accessibility); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyModifiers_11(m, accessibility)).VerifyDiagnostics(); } ValidatePropertyModifiers_11(compilation3.SourceModule, accessibility); var compilation5 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics(expectedNoImplementation); ValidatePropertyNotImplemented_11(compilation5, "Test2"); } } private static void ValidatePropertyModifiers_11(ModuleSymbol m, Accessibility accessibility) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var p1 = GetSingleProperty(i1); var test1P1 = GetSingleProperty(test1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; ValidatePropertyModifiers_11(p1, accessibility); ValidatePropertyAccessorModifiers_11(p1get, accessibility); ValidatePropertyAccessorModifiers_11(p1set, accessibility); Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test1P1.GetMethod, test1.FindImplementationForInterfaceMember(p1get)); Assert.Same(test1P1.SetMethod, test1.FindImplementationForInterfaceMember(p1set)); } private static void ValidatePropertyModifiers_11(PropertySymbol p1, Accessibility accessibility) { Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(accessibility, p1.DeclaredAccessibility); } private static void ValidatePropertyAccessorModifiers_11(MethodSymbol m1, Accessibility accessibility) { Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(accessibility, m1.DeclaredAccessibility); } private static void ValidatePropertyNotImplemented_11(CSharpCompilation compilation, string className) { var test2 = compilation.GetTypeByMetadataName(className); var i1 = compilation.GetTypeByMetadataName("I1"); var p1 = GetSingleProperty(i1); Assert.Null(test2.FindImplementationForInterfaceMember(p1)); Assert.Null(test2.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p1.SetMethod)); } [Fact] public void PropertyModifiers_11_02() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } private void ValidatePropertyModifiers_11_02(string source1, string source2, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expectedIn9); ValidatePropertyImplementation_11(compilation1.SourceModule); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyImplementation_11(m)).VerifyDiagnostics(); ValidatePropertyImplementation_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); ValidatePropertyImplementation_11(compilation3.SourceModule); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyImplementation_11(m)).VerifyDiagnostics(); } ValidatePropertyImplementation_11(compilation3.SourceModule); } } private static void ValidatePropertyImplementation_11(ModuleSymbol m) { ValidatePropertyImplementation_11(m, implementedByBase: false); } private static void ValidatePropertyImplementationByBase_11(ModuleSymbol m) { ValidatePropertyImplementation_11(m, implementedByBase: true); } private static void ValidatePropertyImplementation_11(ModuleSymbol m, bool implementedByBase) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var p1 = GetSingleProperty(i1); var test1P1 = GetSingleProperty(implementedByBase ? test1.BaseTypeNoUseSiteDiagnostics : test1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test1P1.GetMethod, test1.FindImplementationForInterfaceMember(p1get)); Assert.Same(test1P1.SetMethod, test1.FindImplementationForInterfaceMember(p1set)); var i2 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I2").SingleOrDefault(); Assert.True(test1P1.GetMethod.IsMetadataVirtual()); Assert.True(test1P1.SetMethod.IsMetadataVirtual()); } [Fact] public void PropertyModifiers_11_03() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // int I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(9, 12) ); } private void ValidatePropertyModifiers_11_03(string source1, string source2, TargetFramework targetFramework, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, targetFramework: targetFramework, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: !(targetFramework == TargetFramework.Standard || ExecutionConditionUtil.IsMonoOrCoreClr) ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidatePropertyImplementation_11); ValidatePropertyImplementation_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: targetFramework, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, targetFramework: targetFramework, parseOptions: TestOptions.Regular); compilation3.VerifyDiagnostics(expected); if (expected.Length == 0) { CompileAndVerify(compilation3, expectedOutput: !(targetFramework == TargetFramework.Standard || ExecutionConditionUtil.IsMonoOrCoreClr) ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidatePropertyImplementation_11); } ValidatePropertyImplementation_11(compilation3.SourceModule); } } [Fact] public void PropertyModifiers_11_04() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_11_05() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_11_06() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract int P1 {get; set;} } class Test3 : Test1 { public override int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,29): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(9, 29), // (9,34): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(9, 34) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,29): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(9, 29), // (9,34): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(9, 34) ) ); } [Fact] public void PropertyModifiers_11_07() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int P1 {get; set;} } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_11_08() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long P1 { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_08(source1, source2); } private void ValidatePropertyModifiers_11_08(string source1, string source2) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: @"Test2.get_P1 Test2.set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidatePropertyImplementationByBase_11); ValidatePropertyImplementationByBase_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation3, expectedOutput: @"Test2.get_P1 Test2.set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidatePropertyImplementationByBase_11); ValidatePropertyImplementationByBase_11(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation4, expectedOutput: @"Test2.get_P1 Test2.set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidatePropertyImplementationByBase_11); ValidatePropertyImplementationByBase_11(compilation4.SourceModule); } [Fact] public void PropertyModifiers_11_09() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long P1 { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.P1'. 'Test1.P1' cannot implement 'I1.P1' because it does not have the matching return type of 'int'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.P1", "Test1.P1", "int").WithLocation(2, 15) ); } private void ValidatePropertyModifiers_11_09(string source1, string source2, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics(expected); ValidatePropertyNotImplemented_11(compilation1, "Test1"); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation3.VerifyDiagnostics(expected); ValidatePropertyNotImplemented_11(compilation3, "Test1"); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation4.VerifyDiagnostics(expected); ValidatePropertyNotImplemented_11(compilation4, "Test1"); } [Fact] public void PropertyModifiers_11_10() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} sealed void Test() { P1 = P1; } } "; var source2 = @" public class Test2 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (6,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.P1.get", "Test2.P1.get", "9.0", "10.0").WithLocation(6, 9), // (11,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.P1.set", "Test2.P1.set", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (6,9): error CS9044: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test2", "I1.P1.get", "Test2.P1.get").WithLocation(6, 9), // (11,9): error CS9044: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test2", "I1.P1.set", "Test2.P1.set").WithLocation(11, 9) ) ); } private void ValidatePropertyModifiers_11_10(string source1, string source2, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(expectedIn9); ValidatePropertyImplementationByBase_11(compilation1.SourceModule); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyImplementationByBase_11(m)).VerifyDiagnostics(); ValidatePropertyImplementationByBase_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); ValidatePropertyImplementationByBase_11(compilation3.SourceModule); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyImplementationByBase_11(m)).VerifyDiagnostics(); } ValidatePropertyImplementationByBase_11(compilation3.SourceModule); } } [Fact] public void PropertyModifiers_11_11() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} sealed void Test() { P1 = P1; } } public class Test2 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_11(source1, source2, // (15,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.P1.get", "Test2.P1.get", "9.0", "10.0").WithLocation(15, 9), // (20,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.P1.set", "Test2.P1.set", "9.0", "10.0").WithLocation(20, 9) ); } private void ValidatePropertyModifiers_11_11(string source1, string source2, params DiagnosticDescription[] expectedIn9) { ValidatePropertyModifiers_11_11(source1, source2, expectedIn9, expectedAcrossAssemblyBoundaries: Array.Empty<DiagnosticDescription>()); } private void ValidatePropertyModifiers_11_11(string source1, string source2, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp, assemblyName: "PropertyModifiers_11_11"); compilation2.VerifyDiagnostics(expectedIn9); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp, assemblyName: "PropertyModifiers_11_11"); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidatePropertyImplementationByBase_11(m)).VerifyDiagnostics(); } ValidatePropertyImplementationByBase_11(compilation3.SourceModule); } [Fact] public void PropertyModifiers_12() { var source1 = @" public interface I1 { internal abstract int P1 {get; set;} } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(7, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<PropertySymbol>("P1"); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test1.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Null(test1.FindImplementationForInterfaceMember(p1.SetMethod)); } [Fact] public void PropertyModifiers_13() { var source1 = @" public interface I1 { public sealed int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } } } public interface I2 { public sealed int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } set { System.Console.WriteLine(""set_P2""); } } } public interface I3 { public sealed int P3 { set { System.Console.WriteLine(""set_P3""); } } } public interface I4 { public sealed int P4 { get => GetP4(); } private int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } public interface I5 { public sealed int P5 { get => GetP5(); set => System.Console.WriteLine(""set_P5""); } private int GetP5() { System.Console.WriteLine(""get_P5""); return 0; } } public interface I6 { public sealed int P6 { set => System.Console.WriteLine(""set_P6""); } } public interface I7 { public sealed int P7 => GetP7(); private int GetP7() { System.Console.WriteLine(""get_P7""); return 0; } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); var x = i1.P1; I2 i2 = new Test2(); i2.P2 = i2.P2; I3 i3 = new Test3(); i3.P3 = x; I4 i4 = new Test4(); x = i4.P4; I5 i5 = new Test5(); i5.P5 = i5.P5; I6 i6 = new Test6(); i6.P6 = x; I7 i7 = new Test7(); x = i7.P7; } public int P1 => throw null; } class Test2 : I2 { public int P2 { get => throw null; set => throw null; } } class Test3 : I3 { public int P3 { set => throw null; } } class Test4 : I4 { public int P4 { get => throw null; } } class Test5 : I5 { public int P5 { get => throw null; set => throw null; } } class Test6 : I6 { public int P6 { set => throw null; } } class Test7 : I7 { public int P7 => throw null; } "; ValidatePropertyModifiers_13(source1); } private void ValidatePropertyModifiers_13(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate(ModuleSymbol m) { for (int i = 1; i <= 7; i++) { var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleProperty(i1); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); switch (i) { case 3: case 6: Assert.Null(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; case 1: case 4: case 7: Assert.Null(p1.SetMethod); ValidateAccessor(p1.GetMethod); break; default: ValidateAccessor(p1.GetMethod); ValidateAccessor(p1.SetMethod); break; } void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 get_P2 set_P2 set_P3 get_P4 get_P5 set_P5 set_P6 get_P7 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); } [Fact] public void PropertyModifiers_14() { var source1 = @" public interface I1 { public sealed int P1 {get;} = 0; } public interface I2 { abstract sealed int P2 {get;} } public interface I3 { virtual sealed int P3 { set {} } } class Test1 : I1, I2, I3 { int I1.P1 { get => throw null; } int I2.P2 { get => throw null; } int I3.P3 { set => throw null; } } class Test2 : I1, I2, I3 {} "; ValidatePropertyModifiers_14(source1, // (4,23): error CS8053: Instance properties in interfaces cannot have initializers. // public sealed int P1 {get;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P1").WithLocation(4, 23), // (4,27): error CS0501: 'I1.P1.get' must declare a body because it is not marked abstract, extern, or partial // public sealed int P1 {get;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.P1.get").WithLocation(4, 27), // (8,25): error CS0238: 'I2.P2' cannot be sealed because it is not an override // abstract sealed int P2 {get;} Diagnostic(ErrorCode.ERR_SealedNonOverride, "P2").WithArguments("I2.P2").WithLocation(8, 25), // (12,24): error CS0238: 'I3.P3' cannot be sealed because it is not an override // virtual sealed int P3 Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I3.P3").WithLocation(12, 24), // (20,12): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented // int I1.P1 { get => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(20, 12), // (21,12): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented // int I2.P2 { get => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(21, 12), // (22,12): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented // int I3.P3 { set => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(22, 12) ); } private void ValidatePropertyModifiers_14(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var p1 = GetSingleProperty(compilation1, "I1"); var p1get = p1.GetMethod; Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test2.FindImplementationForInterfaceMember(p1)); Assert.False(p1get.IsAbstract); Assert.False(p1get.IsVirtual); Assert.False(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); Assert.False(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); Assert.Null(test2.FindImplementationForInterfaceMember(p1get)); var p2 = GetSingleProperty(compilation1, "I2"); var test1P2 = test1.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); var p2get = p2.GetMethod; Assert.True(p2.IsAbstract); Assert.False(p2.IsVirtual); Assert.True(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p2)); Assert.Null(test2.FindImplementationForInterfaceMember(p2)); Assert.True(p2get.IsAbstract); Assert.False(p2get.IsVirtual); Assert.True(p2get.IsMetadataVirtual()); Assert.True(p2get.IsSealed); Assert.False(p2get.IsStatic); Assert.False(p2get.IsExtern); Assert.False(p2get.IsAsync); Assert.False(p2get.IsOverride); Assert.Equal(Accessibility.Public, p2get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p2get)); Assert.Null(test2.FindImplementationForInterfaceMember(p2get)); var p3 = GetSingleProperty(compilation1, "I3"); var test1P3 = test1.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I3.")).Single(); var p3set = p3.SetMethod; Assert.False(p3.IsAbstract); Assert.True(p3.IsVirtual); Assert.True(p3.IsSealed); Assert.False(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); Assert.False(p3set.IsAbstract); Assert.True(p3set.IsVirtual); Assert.True(p3set.IsMetadataVirtual()); Assert.True(p3set.IsSealed); Assert.False(p3set.IsStatic); Assert.False(p3set.IsExtern); Assert.False(p3set.IsAsync); Assert.False(p3set.IsOverride); Assert.Equal(Accessibility.Public, p3set.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3set)); Assert.Null(test2.FindImplementationForInterfaceMember(p3set)); } [Fact] public void PropertyModifiers_15() { var source1 = @" public interface I0 { abstract virtual int P0 { get; set; } } public interface I1 { abstract virtual int P1 { get { throw null; } } } public interface I2 { virtual abstract int P2 { get { throw null; } set { throw null; } } } public interface I3 { abstract virtual int P3 { set { throw null; } } } public interface I4 { abstract virtual int P4 { get => throw null; } } public interface I5 { abstract virtual int P5 { get => throw null; set => throw null; } } public interface I6 { abstract virtual int P6 { set => throw null; } } public interface I7 { abstract virtual int P7 => throw null; } public interface I8 { abstract virtual int P8 {get;} = 0; } class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 { int I0.P0 { get { throw null; } set { throw null; } } int I1.P1 { get { throw null; } } int I2.P2 { get { throw null; } set { throw null; } } int I3.P3 { set { throw null; } } int I4.P4 { get { throw null; } } int I5.P5 { get { throw null; } set { throw null; } } int I6.P6 { set { throw null; } } int I7.P7 { get { throw null; } } int I8.P8 { get { throw null; } } } class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 {} "; ValidatePropertyModifiers_15(source1, // (4,26): error CS0503: The abstract property 'I0.P0' cannot be marked virtual // abstract virtual int P0 { get; set; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P0").WithArguments("property", "I0.P0").WithLocation(4, 26), // (8,26): error CS0503: The abstract property 'I1.P1' cannot be marked virtual // abstract virtual int P1 { get { throw null; } } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P1").WithArguments("property", "I1.P1").WithLocation(8, 26), // (8,31): error CS0500: 'I1.P1.get' cannot declare a body because it is marked abstract // abstract virtual int P1 { get { throw null; } } Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.P1.get").WithLocation(8, 31), // (12,26): error CS0503: The abstract property 'I2.P2' cannot be marked virtual // virtual abstract int P2 Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P2").WithArguments("property", "I2.P2").WithLocation(12, 26), // (14,9): error CS0500: 'I2.P2.get' cannot declare a body because it is marked abstract // get { throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I2.P2.get").WithLocation(14, 9), // (15,9): error CS0500: 'I2.P2.set' cannot declare a body because it is marked abstract // set { throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I2.P2.set").WithLocation(15, 9), // (20,26): error CS0503: The abstract property 'I3.P3' cannot be marked virtual // abstract virtual int P3 { set { throw null; } } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P3").WithArguments("property", "I3.P3").WithLocation(20, 26), // (20,31): error CS0500: 'I3.P3.set' cannot declare a body because it is marked abstract // abstract virtual int P3 { set { throw null; } } Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I3.P3.set").WithLocation(20, 31), // (24,26): error CS0503: The abstract property 'I4.P4' cannot be marked virtual // abstract virtual int P4 { get => throw null; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P4").WithArguments("property", "I4.P4").WithLocation(24, 26), // (24,31): error CS0500: 'I4.P4.get' cannot declare a body because it is marked abstract // abstract virtual int P4 { get => throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.P4.get").WithLocation(24, 31), // (28,26): error CS0503: The abstract property 'I5.P5' cannot be marked virtual // abstract virtual int P5 Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P5").WithArguments("property", "I5.P5").WithLocation(28, 26), // (30,9): error CS0500: 'I5.P5.get' cannot declare a body because it is marked abstract // get => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I5.P5.get").WithLocation(30, 9), // (31,9): error CS0500: 'I5.P5.set' cannot declare a body because it is marked abstract // set => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I5.P5.set").WithLocation(31, 9), // (36,26): error CS0503: The abstract property 'I6.P6' cannot be marked virtual // abstract virtual int P6 { set => throw null; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P6").WithArguments("property", "I6.P6").WithLocation(36, 26), // (36,31): error CS0500: 'I6.P6.set' cannot declare a body because it is marked abstract // abstract virtual int P6 { set => throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I6.P6.set").WithLocation(36, 31), // (40,26): error CS0503: The abstract property 'I7.P7' cannot be marked virtual // abstract virtual int P7 => throw null; Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P7").WithArguments("property", "I7.P7").WithLocation(40, 26), // (40,32): error CS0500: 'I7.P7.get' cannot declare a body because it is marked abstract // abstract virtual int P7 => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "throw null").WithArguments("I7.P7.get").WithLocation(40, 32), // (44,26): error CS0503: The abstract property 'I8.P8' cannot be marked virtual // abstract virtual int P8 {get;} = 0; Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P8").WithArguments("property", "I8.P8").WithLocation(44, 26), // (44,26): error CS8053: Instance properties in interfaces cannot have initializers. // abstract virtual int P8 {get;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P8").WithLocation(44, 26), // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.P0' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.P0").WithLocation(90, 15), // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(90, 19), // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.P2' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.P2").WithLocation(90, 23), // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.P3' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.P3").WithLocation(90, 27), // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.P4' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.P4").WithLocation(90, 31), // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.P5' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.P5").WithLocation(90, 35), // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.P6' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.P6").WithLocation(90, 39), // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.P7' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.P7").WithLocation(90, 43), // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.P8' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.P8").WithLocation(90, 47) ); } private void ValidatePropertyModifiers_15(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); for (int i = 0; i <= 8; i++) { var i1 = compilation1.GetTypeByMetadataName("I" + i); var p2 = GetSingleProperty(i1); var test1P2 = test1.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith(i1.Name)).Single(); Assert.True(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(test1P2, test1.FindImplementationForInterfaceMember(p2)); Assert.Null(test2.FindImplementationForInterfaceMember(p2)); switch (i) { case 3: case 6: Assert.Null(p2.GetMethod); ValidateAccessor(p2.SetMethod, test1P2.SetMethod); break; case 1: case 4: case 7: case 8: Assert.Null(p2.SetMethod); ValidateAccessor(p2.GetMethod, test1P2.GetMethod); break; default: ValidateAccessor(p2.GetMethod, test1P2.GetMethod); ValidateAccessor(p2.SetMethod, test1P2.SetMethod); break; } void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementedBy) { Assert.True(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(implementedBy, test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } } [Fact] public void PropertyModifiers_16() { var source1 = @" public interface I1 { extern int P1 {get;} } public interface I2 { virtual extern int P2 {set;} } public interface I3 { static extern int P3 {get; set;} } public interface I4 { private extern int P4 {get;} } public interface I5 { extern sealed int P5 {set;} } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { int I1.P1 => 0; int I2.P2 { set {} } } "; ValidatePropertyModifiers_16(source1, new DiagnosticDescription[] { // (4,16): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern int P1 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("extern", "7.3", "8.0").WithLocation(4, 16), // (8,24): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern int P2 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P2").WithArguments("extern", "7.3", "8.0").WithLocation(8, 24), // (8,24): error CS8503: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern int P2 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P2").WithArguments("virtual", "7.3", "8.0").WithLocation(8, 24), // (12,23): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static extern int P3 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("static", "7.3", "8.0").WithLocation(12, 23), // (12,23): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static extern int P3 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("extern", "7.3", "8.0").WithLocation(12, 23), // (16,24): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern int P4 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P4").WithArguments("private", "7.3", "8.0").WithLocation(16, 24), // (16,24): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern int P4 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P4").WithArguments("extern", "7.3", "8.0").WithLocation(16, 24), // (20,23): error CS8503: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed int P5 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P5").WithArguments("sealed", "7.3", "8.0").WithLocation(20, 23), // (20,23): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed int P5 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P5").WithArguments("extern", "7.3", "8.0").WithLocation(20, 23), // (8,28): warning CS0626: Method, operator, or accessor 'I2.P2.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern int P2 {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I2.P2.set").WithLocation(8, 28), // (12,27): warning CS0626: Method, operator, or accessor 'I3.P3.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int P3 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.P3.get").WithLocation(12, 27), // (12,32): warning CS0626: Method, operator, or accessor 'I3.P3.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int P3 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.P3.set").WithLocation(12, 32), // (16,28): warning CS0626: Method, operator, or accessor 'I4.P4.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern int P4 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I4.P4.get").WithLocation(16, 28), // (20,27): warning CS0626: Method, operator, or accessor 'I5.P5.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed int P5 {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I5.P5.set").WithLocation(20, 27), // (4,20): warning CS0626: Method, operator, or accessor 'I1.P1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P1.get").WithLocation(4, 20) }, // (4,20): error CS8501: Target runtime doesn't support default interface implementation. // extern int P1 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(4, 20), // (8,28): error CS8501: Target runtime doesn't support default interface implementation. // virtual extern int P2 {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(8, 28), // (16,28): error CS8501: Target runtime doesn't support default interface implementation. // private extern int P4 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(16, 28), // (20,27): error CS8501: Target runtime doesn't support default interface implementation. // extern sealed int P5 {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(20, 27), // (8,28): warning CS0626: Method, operator, or accessor 'I2.P2.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern int P2 {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I2.P2.set").WithLocation(8, 28), // (12,27): warning CS0626: Method, operator, or accessor 'I3.P3.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int P3 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.P3.get").WithLocation(12, 27), // (12,32): warning CS0626: Method, operator, or accessor 'I3.P3.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int P3 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.P3.set").WithLocation(12, 32), // (16,28): warning CS0626: Method, operator, or accessor 'I4.P4.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern int P4 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I4.P4.get").WithLocation(16, 28), // (20,27): warning CS0626: Method, operator, or accessor 'I5.P5.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed int P5 {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I5.P5.set").WithLocation(20, 27), // (4,20): warning CS0626: Method, operator, or accessor 'I1.P1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int P1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.P1.get").WithLocation(4, 20) ); } private void ValidatePropertyModifiers_16(string source1, DiagnosticDescription[] expected1, params DiagnosticDescription[] expected2) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var test2 = m.GlobalNamespace.GetTypeMember("Test2"); bool isSource = !(m is PEModuleSymbol); var p1 = GetSingleProperty(m, "I1"); var test2P1 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I1.")).Single(); var p1get = p1.GetMethod; Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.Equal(isSource, p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); Assert.False(p1get.IsAbstract); Assert.True(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); Assert.Equal(isSource, p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); Assert.Same(test2P1.GetMethod, test2.FindImplementationForInterfaceMember(p1get)); var p2 = GetSingleProperty(m, "I2"); var test2P2 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); var p2set = p2.SetMethod; Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.Equal(isSource, p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); Assert.False(p2set.IsAbstract); Assert.True(p2set.IsVirtual); Assert.True(p2set.IsMetadataVirtual()); Assert.False(p2set.IsSealed); Assert.False(p2set.IsStatic); Assert.Equal(isSource, p2set.IsExtern); Assert.False(p2set.IsAsync); Assert.False(p2set.IsOverride); Assert.Equal(Accessibility.Public, p2set.DeclaredAccessibility); Assert.Same(p2set, test1.FindImplementationForInterfaceMember(p2set)); Assert.Same(test2P2.SetMethod, test2.FindImplementationForInterfaceMember(p2set)); var i3 = m.ContainingAssembly.GetTypeByMetadataName("I3"); if ((object)i3 != null) { var p3 = GetSingleProperty(i3); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.False(p3.IsSealed); Assert.True(p3.IsStatic); Assert.Equal(isSource, p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.GetMethod); ValidateP3Accessor(p3.SetMethod); void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.Equal(isSource, accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } var p4 = GetSingleProperty(m, "I4"); var p4get = p4.GetMethod; Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); Assert.Equal(isSource, p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.Null(test2.FindImplementationForInterfaceMember(p4)); Assert.False(p4get.IsAbstract); Assert.False(p4get.IsVirtual); Assert.False(p4get.IsMetadataVirtual()); Assert.False(p4get.IsSealed); Assert.False(p4get.IsStatic); Assert.Equal(isSource, p4get.IsExtern); Assert.False(p4get.IsAsync); Assert.False(p4get.IsOverride); Assert.Equal(Accessibility.Private, p4get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4get)); Assert.Null(test2.FindImplementationForInterfaceMember(p4get)); var p5 = GetSingleProperty(m, "I5"); var p5set = p5.SetMethod; Assert.False(p5.IsAbstract); Assert.False(p5.IsVirtual); Assert.False(p5.IsSealed); Assert.False(p5.IsStatic); Assert.Equal(isSource, p5.IsExtern); Assert.False(p5.IsOverride); Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); Assert.False(p5set.IsAbstract); Assert.False(p5set.IsVirtual); Assert.False(p5set.IsMetadataVirtual()); Assert.False(p5set.IsSealed); Assert.False(p5set.IsStatic); Assert.Equal(isSource, p5set.IsExtern); Assert.False(p5set.IsAsync); Assert.False(p5set.IsOverride); Assert.Equal(Accessibility.Public, p5set.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5set)); Assert.Null(test2.FindImplementationForInterfaceMember(p5set)); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(expected1); Validate(compilation2.SourceModule); var compilation3 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expected2); Validate(compilation3.SourceModule); } [Fact] public void PropertyModifiers_17() { var source1 = @" public interface I1 { abstract extern int P1 {get;} } public interface I2 { extern int P2 => 0; } public interface I3 { static extern int P3 {get => 0; set => throw null;} } public interface I4 { private extern int P4 { get {throw null;} set {throw null;}} } public interface I5 { extern sealed int P5 {get;} = 0; } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { int I1.P1 => 0; int I2.P2 => 0; int I3.P3 { get => 0; set => throw null;} int I4.P4 { get => 0; set => throw null;} int I5.P5 => 0; } "; ValidatePropertyModifiers_17(source1, // (4,25): error CS0180: 'I1.P1' cannot be both extern and abstract // abstract extern int P1 {get;} Diagnostic(ErrorCode.ERR_AbstractAndExtern, "P1").WithArguments("I1.P1").WithLocation(4, 25), // (8,22): error CS0179: 'I2.P2.get' cannot be extern and declare a body // extern int P2 => 0; Diagnostic(ErrorCode.ERR_ExternHasBody, "0").WithArguments("I2.P2.get").WithLocation(8, 22), // (12,27): error CS0179: 'I3.P3.get' cannot be extern and declare a body // static extern int P3 {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I3.P3.get").WithLocation(12, 27), // (12,37): error CS0179: 'I3.P3.set' cannot be extern and declare a body // static extern int P3 {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I3.P3.set").WithLocation(12, 37), // (16,29): error CS0179: 'I4.P4.get' cannot be extern and declare a body // private extern int P4 { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I4.P4.get").WithLocation(16, 29), // (16,47): error CS0179: 'I4.P4.set' cannot be extern and declare a body // private extern int P4 { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I4.P4.set").WithLocation(16, 47), // (20,23): error CS8053: Instance properties in interfaces cannot have initializers. // extern sealed int P5 {get;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P5").WithLocation(20, 23), // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), // (31,12): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented // int I3.P3 { get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 12), // (32,12): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented // int I4.P4 { get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 12), // (33,12): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented // int I5.P5 => 0; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 12), // (20,27): warning CS0626: Method, operator, or accessor 'I5.P5.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed int P5 {get;} = 0; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I5.P5.get").WithLocation(20, 27) ); } private void ValidatePropertyModifiers_17(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var p1 = GetSingleProperty(compilation1, "I1"); var test2P1 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I1.")).Single(); var p1get = p1.GetMethod; Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.True(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); Assert.True(p1get.IsAbstract); Assert.False(p1get.IsVirtual); Assert.True(p1get.IsMetadataVirtual()); Assert.False(p1get.IsSealed); Assert.False(p1get.IsStatic); Assert.True(p1get.IsExtern); Assert.False(p1get.IsAsync); Assert.False(p1get.IsOverride); Assert.Equal(Accessibility.Public, p1get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1get)); Assert.Same(test2P1.GetMethod, test2.FindImplementationForInterfaceMember(p1get)); var p2 = GetSingleProperty(compilation1, "I2"); var test2P2 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); var p2get = p2.GetMethod; Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.True(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); Assert.False(p2get.IsAbstract); Assert.True(p2get.IsVirtual); Assert.True(p2get.IsMetadataVirtual()); Assert.False(p2get.IsSealed); Assert.False(p2get.IsStatic); Assert.True(p2get.IsExtern); Assert.False(p2get.IsAsync); Assert.False(p2get.IsOverride); Assert.Equal(Accessibility.Public, p2get.DeclaredAccessibility); Assert.Same(p2get, test1.FindImplementationForInterfaceMember(p2get)); Assert.Same(test2P2.GetMethod, test2.FindImplementationForInterfaceMember(p2get)); var p3 = GetSingleProperty(compilation1, "I3"); var test2P3 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I3.")).Single(); Assert.False(p3.IsAbstract); Assert.Equal(p3.IsIndexer, p3.IsVirtual); Assert.False(p3.IsSealed); Assert.Equal(!p3.IsIndexer, p3.IsStatic); Assert.True(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Same(p3.IsIndexer ? p3 : null, test1.FindImplementationForInterfaceMember(p3)); Assert.Same(p3.IsIndexer ? test2P3 : null, test2.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.GetMethod, p3.IsIndexer ? test2P3.GetMethod : null); ValidateP3Accessor(p3.SetMethod, p3.IsIndexer ? test2P3.SetMethod : null); void ValidateP3Accessor(MethodSymbol accessor, MethodSymbol test2Implementation) { Assert.False(accessor.IsAbstract); Assert.Equal(p3.IsIndexer, accessor.IsVirtual); Assert.Equal(p3.IsIndexer, accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.Equal(!p3.IsIndexer, accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(p3.IsIndexer ? accessor : null, test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(test2Implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p4 = GetSingleProperty(compilation1, "I4"); Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); Assert.True(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.Null(test2.FindImplementationForInterfaceMember(p4)); ValidateP4Accessor(p4.GetMethod); ValidateP4Accessor(p4.SetMethod); void ValidateP4Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p5 = GetSingleProperty(compilation1, "I5"); var p5get = p5.GetMethod; Assert.False(p5.IsAbstract); Assert.False(p5.IsVirtual); Assert.False(p5.IsSealed); Assert.False(p5.IsStatic); Assert.True(p5.IsExtern); Assert.False(p5.IsOverride); Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); Assert.False(p5get.IsAbstract); Assert.False(p5get.IsVirtual); Assert.False(p5get.IsMetadataVirtual()); Assert.False(p5get.IsSealed); Assert.False(p5get.IsStatic); Assert.True(p5get.IsExtern); Assert.False(p5get.IsAsync); Assert.False(p5get.IsOverride); Assert.Equal(Accessibility.Public, p5get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5get)); Assert.Null(test2.FindImplementationForInterfaceMember(p5get)); } [Fact] public void PropertyModifiers_18() { var source1 = @" public interface I1 { abstract int P1 {get => 0; set => throw null;} } public interface I2 { abstract private int P2 => 0; } public interface I3 { static extern int P3 {get; set;} } public interface I4 { abstract static int P4 { get {throw null;} set {throw null;}} } public interface I5 { override sealed int P5 {get;} = 0; } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { int I1.P1 { get => 0; set => throw null;} int I2.P2 => 0; int I3.P3 { get => 0; set => throw null;} int I4.P4 { get => 0; set => throw null;} int I5.P5 => 0; } "; ValidatePropertyModifiers_18(source1, // (8,32): error CS0500: 'I2.P2.get' cannot declare a body because it is marked abstract // abstract private int P2 => 0; Diagnostic(ErrorCode.ERR_AbstractHasBody, "0").WithArguments("I2.P2.get").WithLocation(8, 32), // (4,22): error CS0500: 'I1.P1.get' cannot declare a body because it is marked abstract // abstract int P1 {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.P1.get").WithLocation(4, 22), // (4,32): error CS0500: 'I1.P1.set' cannot declare a body because it is marked abstract // abstract int P1 {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.P1.set").WithLocation(4, 32), // (20,25): error CS0106: The modifier 'override' is not valid for this item // override sealed int P5 {get;} = 0; Diagnostic(ErrorCode.ERR_BadMemberFlag, "P5").WithArguments("override").WithLocation(20, 25), // (20,29): error CS0501: 'I5.P5.get' must declare a body because it is not marked abstract, extern, or partial // override sealed int P5 {get;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I5.P5.get").WithLocation(20, 29), // (16,25): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // abstract static int P4 { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P4").WithArguments("abstract", "9.0", "11.0").WithLocation(16, 25), // (16,30): error CS0500: 'I4.P4.get' cannot declare a body because it is marked abstract // abstract static int P4 { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.P4.get").WithLocation(16, 30), // (16,48): error CS0500: 'I4.P4.set' cannot declare a body because it is marked abstract // abstract static int P4 { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I4.P4.set").WithLocation(16, 48), // (8,26): error CS0621: 'I2.P2': virtual or abstract members cannot be private // abstract private int P2 => 0; Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I2.P2").WithLocation(8, 26), // (20,25): error CS8053: Instance properties in interfaces cannot have initializers. // override sealed int P5 {get;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "P5").WithLocation(20, 25), // (12,32): warning CS0626: Method, operator, or accessor 'I3.P3.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int P3 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.P3.set").WithLocation(12, 32), // (12,27): warning CS0626: Method, operator, or accessor 'I3.P3.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int P3 {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.P3.get").WithLocation(12, 27), // (30,12): error CS0122: 'I2.P2' is inaccessible due to its protection level // int I2.P2 => 0; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I2.P2").WithLocation(30, 12), // (31,12): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented // int I3.P3 { get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 12), // (32,12): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented // int I4.P4 { get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 12), // (33,12): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented // int I5.P5 => 0; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 12), // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.P2' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.P2").WithLocation(23, 19), // (23,27): error CS0535: 'Test1' does not implement interface member 'I4.P4' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test1", "I4.P4").WithLocation(23, 27), // (27,27): error CS0535: 'Test2' does not implement interface member 'I4.P4' // class Test2 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.P4").WithLocation(27, 27) ); } private void ValidatePropertyModifiers_18(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var p1 = GetSingleProperty(compilation1, "I1"); var test2P1 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I1.")).Single(); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); ValidateP1Accessor(p1.GetMethod, test2P1.GetMethod); ValidateP1Accessor(p1.SetMethod, test2P1.SetMethod); void ValidateP1Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p2 = GetSingleProperty(compilation1, "I2"); var test2P2 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); var p2get = p2.GetMethod; Assert.True(p2.IsAbstract); Assert.False(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p2)); Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); Assert.True(p2get.IsAbstract); Assert.False(p2get.IsVirtual); Assert.True(p2get.IsMetadataVirtual()); Assert.False(p2get.IsSealed); Assert.False(p2get.IsStatic); Assert.False(p2get.IsExtern); Assert.False(p2get.IsAsync); Assert.False(p2get.IsOverride); Assert.Equal(Accessibility.Private, p2get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p2get)); Assert.Same(test2P2.GetMethod, test2.FindImplementationForInterfaceMember(p2get)); var p3 = GetSingleProperty(compilation1, "I3"); var test2P3 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I3.")).Single(); Assert.False(p3.IsAbstract); Assert.Equal(p3.IsIndexer, p3.IsVirtual); Assert.False(p3.IsSealed); Assert.Equal(!p3.IsIndexer, p3.IsStatic); Assert.True(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Same(p3.IsIndexer ? p3 : null, test1.FindImplementationForInterfaceMember(p3)); Assert.Same(p3.IsIndexer ? test2P3 : null, test2.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.GetMethod, p3.IsIndexer ? test2P3.GetMethod : null); ValidateP3Accessor(p3.SetMethod, p3.IsIndexer ? test2P3.SetMethod : null); void ValidateP3Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.False(accessor.IsAbstract); Assert.Equal(p3.IsIndexer, accessor.IsVirtual); Assert.Equal(p3.IsIndexer, accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.Equal(!p3.IsIndexer, accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(p3.IsIndexer ? accessor : null, test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p4 = GetSingleProperty(compilation1, "I4"); var test2P4 = test2.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I4.")).Single(); Assert.True(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.Equal(!p4.IsIndexer, p4.IsStatic); Assert.False(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Public, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.Same(p4.IsIndexer ? test2P4 : null, test2.FindImplementationForInterfaceMember(p4)); ValidateP4Accessor(p4.GetMethod, p4.IsIndexer ? test2P4.GetMethod : null); ValidateP4Accessor(p4.SetMethod, p4.IsIndexer ? test2P4.SetMethod : null); void ValidateP4Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.Equal(!p4.IsIndexer, accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p5 = GetSingleProperty(compilation1, "I5"); var p5get = p5.GetMethod; Assert.False(p5.IsAbstract); Assert.False(p5.IsVirtual); Assert.False(p5.IsSealed); Assert.False(p5.IsStatic); Assert.False(p5.IsExtern); Assert.False(p5.IsOverride); Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); Assert.False(p5get.IsAbstract); Assert.False(p5get.IsVirtual); Assert.False(p5get.IsMetadataVirtual()); Assert.False(p5get.IsSealed); Assert.False(p5get.IsStatic); Assert.False(p5get.IsExtern); Assert.False(p5get.IsAsync); Assert.False(p5get.IsOverride); Assert.Equal(Accessibility.Public, p5get.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5get)); Assert.Null(test2.FindImplementationForInterfaceMember(p5get)); } [Fact] public void PropertyModifiers_20() { var source1 = @" public interface I1 { internal int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } void M2() {P1 = P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_20(source1, source2, Accessibility.Internal); } private void ValidatePropertyModifiers_20(string source1, string source2, Accessibility accessibility) { var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var p1 = GetSingleProperty(i1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; ValidateProperty(p1); ValidateMethod(p1get); ValidateMethod(p1set); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); Assert.Same(p1set, test1.FindImplementationForInterfaceMember(p1set)); } void ValidateProperty(PropertySymbol p1) { Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(accessibility, p1.DeclaredAccessibility); } void ValidateMethod(MethodSymbol m1) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(accessibility, m1.DeclaredAccessibility); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var p1 = GetSingleProperty(i1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; ValidateProperty(p1); ValidateMethod(p1get); ValidateMethod(p1set); } var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation4.SourceModule); } [Fact] public void PropertyModifiers_21() { var source1 = @" public interface I1 { private static int P1 { get => throw null; set => throw null; } internal static int P2 { get => throw null; set => throw null; } public static int P3 { get => throw null; set => throw null; } static int P4 { get => throw null; set => throw null; } } class Test1 { static void Main() { int x; x = I1.P1; I1.P1 = x; x = I1.P2; I1.P2 = x; x = I1.P3; I1.P3 = x; x = I1.P4; I1.P4 = x; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (18,16): error CS0122: 'I1.P1' is inaccessible due to its protection level // x = I1.P1; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(18, 16), // (19,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 = x; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(19, 12) ); var source2 = @" class Test2 { static void Main() { int x; x = I1.P1; I1.P1 = x; x = I1.P2; I1.P2 = x; x = I1.P3; I1.P3 = x; x = I1.P4; I1.P4 = x; } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics( // (7,16): error CS0122: 'I1.P1' is inaccessible due to its protection level // x = I1.P1; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(7, 16), // (8,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 = x; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(8, 12), // (9,16): error CS0122: 'I1.P2' is inaccessible due to its protection level // x = I1.P2; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(9, 16), // (10,12): error CS0122: 'I1.P2' is inaccessible due to its protection level // I1.P2 = x; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(10, 12) ); } [Fact] public void PropertyModifiers_22() { var source1 = @" public interface I1 { public int P1 { internal get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } internal set { System.Console.WriteLine(""set_P2""); } } } public interface I3 { int P3 { internal get => Test1.GetP3(); set => System.Console.WriteLine(""set_P3""); } } public interface I4 { int P4 { get => Test1.GetP4(); internal set => System.Console.WriteLine(""set_P4""); } } class Test1 : I1, I2, I3, I4 { static void Main() { I1 i1 = new Test1(); I2 i2 = new Test1(); I3 i3 = new Test1(); I4 i4 = new Test1(); i1.P1 = i1.P1; i2.P2 = i2.P2; i3.P3 = i3.P3; i4.P4 = i4.P4; } public static int GetP3() { System.Console.WriteLine(""get_P3""); return 0; } public static int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } "; ValidatePropertyModifiers_22(source1, Accessibility.Internal); } private void ValidatePropertyModifiers_22(string source1, Accessibility accessibility) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2 get_P3 set_P3 get_P4 set_P4 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); for (int i = 1; i <= 4; i++) { var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleProperty(i1); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); switch (i) { case 1: case 3: ValidateAccessor(p1.GetMethod, accessibility); ValidateAccessor(p1.SetMethod, Accessibility.Public); break; case 2: case 4: ValidateAccessor(p1.GetMethod, Accessibility.Public); ValidateAccessor(p1.SetMethod, accessibility); break; default: Assert.False(true); break; } void ValidateAccessor(MethodSymbol accessor, Accessibility access) { Assert.False(accessor.IsAbstract); Assert.Equal(accessor.DeclaredAccessibility != Accessibility.Private, accessor.IsVirtual); Assert.Equal(accessor.DeclaredAccessibility != Accessibility.Private, accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(access, accessor.DeclaredAccessibility); Assert.Same(accessor.DeclaredAccessibility == Accessibility.Private ? null : accessor, test1.FindImplementationForInterfaceMember(accessor)); } } } } [Fact] public void PropertyModifiers_23_00() { var source1 = @" public interface I1 {} public interface I3 { int P3 { private get { System.Console.WriteLine(""get_P3""); return 0; } set {System.Console.WriteLine(""set_P3"");} } void M2() { P3 = P3; } } public interface I4 { int P4 { get {System.Console.WriteLine(""get_P4""); return 0;} private set {System.Console.WriteLine(""set_P4"");} } void M2() { P4 = P4; } } public interface I5 { int P5 { private get => GetP5(); set => System.Console.WriteLine(""set_P5""); } private int GetP5() { System.Console.WriteLine(""get_P5""); return 0; } void M2() { P5 = P5; } } public interface I6 { int P6 { get => GetP6(); private set => System.Console.WriteLine(""set_P6""); } private int GetP6() { System.Console.WriteLine(""get_P6""); return 0; } void M2() { P6 = P6; } } "; var source2 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public int P3 { get { throw null; } set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public int P4 { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } set { throw null; } } } class Test5 : I5 { public int P5 { get { throw null; } set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public int P6 { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } set { throw null; } } } "; ValidatePropertyModifiers_23(source1, source2); var source3 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public int P3 { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public int P4 { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test5 : I5 { public int P5 { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public int P6 { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } "; ValidatePropertyModifiers_23(source1, source3); var source4 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public virtual int P3 { get { throw null; } set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public virtual int P4 { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } set { throw null; } } } class Test5 : I5 { public virtual int P5 { get { throw null; } set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public virtual int P6 { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } set { throw null; } } } "; ValidatePropertyModifiers_23(source1, source4); var source5 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public virtual int P3 { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public virtual int P4 { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test5 : I5 { public virtual int P5 { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public virtual int P6 { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } "; ValidatePropertyModifiers_23(source1, source5); var source6 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { int I3.P3 { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { int I4.P4 { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test5 : I5 { int I5.P5 { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { int I6.P6 { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } "; ValidatePropertyModifiers_23(source1, source6); var source7 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test33(); I4 i4 = new Test44(); I5 i5 = new Test55(); I6 i6 = new Test66(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } interface Test3 : I3 { int I3.P3 { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test33 : Test3 {} interface Test4 : I4 { int I4.P4 { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test44 : Test4 {} interface Test5 : I5 { int I5.P5 { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test55 : Test5 {} interface Test6 : I6 { int I6.P6 { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } class Test66 : Test6 {} "; ValidatePropertyModifiers_23(source1, source7); } private void ValidatePropertyModifiers_23(string source1, string source2) { foreach (var metadataImportOptions in new[] { MetadataImportOptions.All, MetadataImportOptions.Public }) { var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe.WithMetadataImportOptions(metadataImportOptions), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var im = test1.InterfacesNoUseSiteDiagnostics().Single().ContainingModule; ValidateProperty23(GetSingleProperty(im, "I3"), false, Accessibility.Private, Accessibility.Public, m.GlobalNamespace.GetTypeMember("Test3")); ValidateProperty23(GetSingleProperty(im, "I4"), false, Accessibility.Public, Accessibility.Private, m.GlobalNamespace.GetTypeMember("Test4")); ValidateProperty23(GetSingleProperty(im, "I5"), false, Accessibility.Private, Accessibility.Public, m.GlobalNamespace.GetTypeMember("Test5")); ValidateProperty23(GetSingleProperty(im, "I6"), false, Accessibility.Public, Accessibility.Private, m.GlobalNamespace.GetTypeMember("Test6")); } var expectedOutput = @" get_P3 Test3.set_P3 Test4.get_P4 set_P4 get_P5 Test5.set_P5 Test6.get_P6 set_P6 "; CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(metadataImportOptions), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateProperty23(GetSingleProperty(compilation2, "I3"), false, Accessibility.Private, Accessibility.Public); ValidateProperty23(GetSingleProperty(compilation2, "I4"), false, Accessibility.Public, Accessibility.Private); ValidateProperty23(GetSingleProperty(compilation2, "I5"), false, Accessibility.Private, Accessibility.Public); ValidateProperty23(GetSingleProperty(compilation2, "I6"), false, Accessibility.Public, Accessibility.Private); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe.WithMetadataImportOptions(metadataImportOptions), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(); Validate1(compilation3.SourceModule); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); } } } private static void ValidateProperty23(PropertySymbol p1, bool isAbstract, Accessibility getAccess, Accessibility setAccess, NamedTypeSymbol test1 = null) { Assert.Equal(isAbstract, p1.IsAbstract); Assert.NotEqual(isAbstract, p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); PropertySymbol implementingProperty = null; if ((object)test1 != null) { implementingProperty = GetSingleProperty(test1); Assert.Same(implementingProperty, test1.FindImplementationForInterfaceMember(p1)); if (implementingProperty.GetMethod?.ExplicitInterfaceImplementations.Length > 0 || implementingProperty.SetMethod?.ExplicitInterfaceImplementations.Length > 0) { Assert.Same(p1, implementingProperty.ExplicitInterfaceImplementations.Single()); } else { Assert.Empty(implementingProperty.ExplicitInterfaceImplementations); } } ValidateMethod23(p1, p1.GetMethod, isAbstract, getAccess, test1, implementingProperty?.GetMethod); ValidateMethod23(p1, p1.SetMethod, isAbstract, setAccess, test1, implementingProperty?.SetMethod); } private static void ValidateMethod23(PropertySymbol p1, MethodSymbol m1, bool isAbstract, Accessibility access, NamedTypeSymbol test1, MethodSymbol implementingMethod) { if (m1 is null) { Assert.Equal(Accessibility.Private, access); Assert.Equal(MetadataImportOptions.Public, ((PEModuleSymbol)p1.ContainingModule).ImportOptions); return; } Assert.Equal(isAbstract, m1.IsAbstract); Assert.NotEqual(isAbstract || access == Accessibility.Private, m1.IsVirtual); Assert.Equal(isAbstract || access != Accessibility.Private, m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(access, m1.DeclaredAccessibility); if ((object)test1 != null) { Assert.Same(access != Accessibility.Private ? implementingMethod : null, test1.FindImplementationForInterfaceMember(m1)); } } [Fact] public void PropertyModifiers_23_01() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} void M2() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.Internal, Accessibility.Public, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(12, 9) ) ); } private void ValidatePropertyModifiers_23(string source1, string source2, Accessibility getAccess, Accessibility setAccess, params DiagnosticDescription[] expectedIn9) { ValidatePropertyModifiers_23(source1, source2, getAccess, setAccess, expectedIn9, expectedAcrossAssemblyBoundaries: Array.Empty<DiagnosticDescription>()); } private void ValidatePropertyModifiers_23(string source1, string source2, Accessibility getAccess, Accessibility setAccess, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expectedIn9); Validate1(compilation1.SourceModule); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => Validate1(m)).VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var im = test1.InterfacesNoUseSiteDiagnostics().Single().ContainingModule; ValidateProperty23(GetSingleProperty(im, "I1"), true, getAccess, setAccess, test1); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); ValidateProperty23(GetSingleProperty(compilation2, "I1"), true, getAccess, setAccess); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); Validate1(compilation3.SourceModule); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => Validate1(m)).VerifyDiagnostics(); } Validate1(compilation3.SourceModule); } } [Fact] public void PropertyModifiers_23_02() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9) ) ); } [Fact] public void PropertyModifiers_23_03() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,12): error CS0122: 'I1.P1.get' is inaccessible due to its protection level // int I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1.get").WithLocation(9, 12) ); } [Fact] public void PropertyModifiers_23_04() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9) ) ); } [Fact] public void PropertyModifiers_23_05() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9) ) ); } [Fact] public void PropertyModifiers_23_06() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract int P1 {get; set;} } class Test3 : Test1 { public override int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,29): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(9, 29) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,29): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(9, 29) ) ); } [Fact] public void PropertyModifiers_23_07() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int P1 {get; set;} } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(11, 9) ) ); } [Fact] public void PropertyModifiers_23_08() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long P1 { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_08(source1, source2); } [Fact] public void PropertyModifiers_23_09() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long P1 { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.P1'. 'Test1.P1' cannot implement 'I1.P1' because it does not have the matching return type of 'int'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.P1", "Test1.P1", "int").WithLocation(2, 15) ); } [Fact] public void PropertyModifiers_23_10() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} sealed void Test() { P1 = P1; } } "; var source2 = @" public class Test2 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (6,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.P1.get", "Test2.P1.get", "9.0", "10.0").WithLocation(6, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (6,9): error CS9044: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test2", "I1.P1.get", "Test2.P1.get").WithLocation(6, 9) ) ); } [Fact] public void PropertyModifiers_23_11() { var source1 = @" public interface I1 { abstract int P1 {internal get; set;} sealed void Test() { P1 = P1; } } public class Test2 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_11(source1, source2, // (15,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.get'. 'Test2.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.P1.get", "Test2.P1.get", "9.0", "10.0").WithLocation(15, 9) ); } [Fact] public void PropertyModifiers_23_51() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} void M2() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.Public, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(17, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (17,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(17, 9) ) ); } [Fact] public void PropertyModifiers_23_52() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_23_53() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,12): error CS0122: 'I1.P1.set' is inaccessible due to its protection level // int I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1.set").WithLocation(9, 12) ); } [Fact] public void PropertyModifiers_23_54() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_23_55() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_23_56() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract int P1 {get; set;} } class Test3 : Test1 { public override int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,34): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(9, 34) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,34): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // public abstract int P1 {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(9, 34) ) ); } [Fact] public void PropertyModifiers_23_57() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int P1 {get; set;} } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(16, 9) ) ); } [Fact] public void PropertyModifiers_23_58() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } public class Test2 : I1 { int I1.P1 { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long P1 { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_08(source1, source2); } [Fact] public void PropertyModifiers_23_59() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long P1 { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.P1'. 'Test1.P1' cannot implement 'I1.P1' because it does not have the matching return type of 'int'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.P1", "Test1.P1", "int").WithLocation(2, 15) ); } [Fact] public void PropertyModifiers_23_60() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} sealed void Test() { P1 = P1; } } "; var source2 = @" public class Test2 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.P1.set", "Test2.P1.set", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test2", "I1.P1.set", "Test2.P1.set").WithLocation(11, 9) ) ); } [Fact] public void PropertyModifiers_23_61() { var source1 = @" public interface I1 { abstract int P1 {get; internal set;} sealed void Test() { P1 = P1; } } public class Test2 : I1 { public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_11(source1, source2, // (20,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.set'. 'Test2.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.P1.set", "Test2.P1.set", "9.0", "10.0").WithLocation(20, 9) ); } [Fact] public void PropertyModifiers_24() { var source1 = @" public interface I1 { int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } internal set { System.Console.WriteLine(""set_P1""); } } void M2() {P1 = P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_24(source1, source2); } private void ValidatePropertyModifiers_24(string source1, string source2) { var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var p1 = GetSingleProperty(i1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; ValidateProperty(p1); ValidateMethod(p1get, Accessibility.Public); ValidateMethod(p1set, Accessibility.Internal); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(p1get, test1.FindImplementationForInterfaceMember(p1get)); Assert.Same(p1set, test1.FindImplementationForInterfaceMember(p1set)); } void ValidateProperty(PropertySymbol p1) { Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); } void ValidateMethod(MethodSymbol m1, Accessibility access) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(access, m1.DeclaredAccessibility); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var p1 = GetSingleProperty(i1); var p1get = p1.GetMethod; var p1set = p1.SetMethod; ValidateProperty(p1); ValidateMethod(p1get, Accessibility.Public); ValidateMethod(p1set, Accessibility.Internal); } var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation4.SourceModule); } [Fact] public void PropertyModifiers_25() { var source1 = @" public interface I1 { static int P1 { private get => throw null; set => throw null; } static int P2 { internal get => throw null; set => throw null; } public static int P3 { get => throw null; private set => throw null; } static int P4 { get => throw null; internal set => throw null; } } class Test1 { static void Main() { int x; x = I1.P1; I1.P1 = x; x = I1.P2; I1.P2 = x; x = I1.P3; I1.P3 = x; x = I1.P4; I1.P4 = x; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (18,13): error CS0271: The property or indexer 'I1.P1' cannot be used in this context because the get accessor is inaccessible // x = I1.P1; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P1").WithArguments("I1.P1").WithLocation(18, 13), // (23,9): error CS0272: The property or indexer 'I1.P3' cannot be used in this context because the set accessor is inaccessible // I1.P3 = x; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P3").WithArguments("I1.P3").WithLocation(23, 9) ); var source2 = @" class Test2 { static void Main() { int x; x = I1.P1; I1.P1 = x; x = I1.P2; I1.P2 = x; x = I1.P3; I1.P3 = x; x = I1.P4; I1.P4 = x; } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics( // (7,13): error CS0271: The property or indexer 'I1.P1' cannot be used in this context because the get accessor is inaccessible // x = I1.P1; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P1").WithArguments("I1.P1").WithLocation(7, 13), // (9,13): error CS0271: The property or indexer 'I1.P2' cannot be used in this context because the get accessor is inaccessible // x = I1.P2; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P2").WithArguments("I1.P2").WithLocation(9, 13), // (12,9): error CS0272: The property or indexer 'I1.P3' cannot be used in this context because the set accessor is inaccessible // I1.P3 = x; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P3").WithArguments("I1.P3").WithLocation(12, 9), // (14,9): error CS0272: The property or indexer 'I1.P4' cannot be used in this context because the set accessor is inaccessible // I1.P4 = x; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P4").WithArguments("I1.P4").WithLocation(14, 9) ); } [Fact] public void PropertyModifiers_26() { var source1 = @" public interface I1 { abstract int P1 { private get; set; } abstract int P2 { get; private set; } abstract int P3 { internal get; } static int P4 {internal get;} = 0; static int P5 { internal get {throw null;} } static int P6 { internal set {throw null;} } static int P7 { internal get => throw null; } static int P8 { internal set => throw null; } static int P9 { internal get {throw null;} private set {throw null;}} static int P10 { internal get => throw null; private set => throw null;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,31): error CS0442: 'I1.P1.get': abstract properties cannot have private accessors // abstract int P1 { private get; set; } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.P1.get").WithLocation(4, 31), // (5,36): error CS0442: 'I1.P2.set': abstract properties cannot have private accessors // abstract int P2 { get; private set; } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "set").WithArguments("I1.P2.set").WithLocation(5, 36), // (6,18): error CS0276: 'I1.P3': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // abstract int P3 { internal get; } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P3").WithArguments("I1.P3").WithLocation(6, 18), // (7,16): error CS0276: 'I1.P4': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // static int P4 {internal get;} = 0; Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P4").WithArguments("I1.P4").WithLocation(7, 16), // (8,16): error CS0276: 'I1.P5': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // static int P5 { internal get {throw null;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P5").WithArguments("I1.P5").WithLocation(8, 16), // (9,16): error CS0276: 'I1.P6': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // static int P6 { internal set {throw null;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P6").WithArguments("I1.P6").WithLocation(9, 16), // (10,16): error CS0276: 'I1.P7': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // static int P7 { internal get => throw null; } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P7").WithArguments("I1.P7").WithLocation(10, 16), // (11,16): error CS0276: 'I1.P8': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // static int P8 { internal set => throw null; } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "P8").WithArguments("I1.P8").WithLocation(11, 16), // (12,16): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.P9' // static int P9 { internal get {throw null;} private set {throw null;}} Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P9").WithArguments("I1.P9").WithLocation(12, 16), // (13,16): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.P10' // static int P10 { internal get => throw null; private set => throw null;} Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "P10").WithArguments("I1.P10").WithLocation(13, 16) ); } [Fact] public void PropertyModifiers_27() { var source1 = @" public interface I1 { int P3 { private get {throw null;} set {} } int P4 { get {throw null;} private set {} } } class Test1 : I1 { int I1.P3 { get {throw null;} set {} } int I1.P4 { get {throw null;} set {} } } interface ITest1 : I1 { int I1.P3 { get {throw null;} set {} } int I1.P4 { get {throw null;} set {} } } public interface I2 { int P5 { private get {throw null;} set {} } int P6 { get {throw null;} private set {} } class Test3 : I2 { int I2.P5 { get {throw null;} set {} } int I2.P6 { get {throw null;} set {} } } interface ITest3 : I2 { int I2.P5 { get {throw null;} set {} } int I2.P6 { get {throw null;} set {} } } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); // https://github.com/dotnet/roslyn/issues/34455: The wording "accessor not found in interface member" is somewhat misleading // in this scenario. The accessor is there, but cannot be implemented. Perhaps // the message should be adjusted. Should also check diagnostics for an attempt // to implement other sealed members. compilation1.VerifyDiagnostics( // (21,9): error CS0550: 'Test1.I1.P3.get' adds an accessor not found in interface member 'I1.P3' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("Test1.I1.P3.get", "I1.P3").WithLocation(21, 9), // (28,9): error CS0550: 'Test1.I1.P4.set' adds an accessor not found in interface member 'I1.P4' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("Test1.I1.P4.set", "I1.P4").WithLocation(28, 9), // (36,9): error CS0550: 'ITest1.I1.P3.get' adds an accessor not found in interface member 'I1.P3' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("ITest1.I1.P3.get", "I1.P3").WithLocation(36, 9), // (43,9): error CS0550: 'ITest1.I1.P4.set' adds an accessor not found in interface member 'I1.P4' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("ITest1.I1.P4.set", "I1.P4").WithLocation(43, 9), // (65,13): error CS0550: 'I2.Test3.I2.P5.get' adds an accessor not found in interface member 'I2.P5' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I2.Test3.I2.P5.get", "I2.P5").WithLocation(65, 13), // (72,13): error CS0550: 'I2.Test3.I2.P6.set' adds an accessor not found in interface member 'I2.P6' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I2.Test3.I2.P6.set", "I2.P6").WithLocation(72, 13), // (80,13): error CS0550: 'I2.ITest3.I2.P5.get' adds an accessor not found in interface member 'I2.P5' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I2.ITest3.I2.P5.get", "I2.P5").WithLocation(80, 13), // (87,13): error CS0550: 'I2.ITest3.I2.P6.set' adds an accessor not found in interface member 'I2.P6' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I2.ITest3.I2.P6.set", "I2.P6").WithLocation(87, 13) ); } [Fact] public void PropertyModifiers_28() { var source0 = @" public interface I1 { protected static int P1 { get { System.Console.WriteLine(""get_P1""); return 1; } set { System.Console.WriteLine(""set_P1""); } } protected internal static int P2 { get { System.Console.WriteLine(""get_P2""); return 2; } set { System.Console.WriteLine(""set_P2""); } } private protected static int P3 { get { System.Console.WriteLine(""get_P3""); return 3; } set { System.Console.WriteLine(""set_P3""); } } static int P4 { protected get { System.Console.WriteLine(""get_P4""); return 4; } set { System.Console.WriteLine(""set_P4""); } } static int P5 { get { System.Console.WriteLine(""get_P5""); return 5; } protected internal set { System.Console.WriteLine(""set_P5""); } } static int P6 { private protected get { System.Console.WriteLine(""get_P6""); return 6; } set { System.Console.WriteLine(""set_P6""); } } } "; var source1 = @" class Test1 : I1 { static void Main() { _ = I1.P1; I1.P1 = 11; _ = I1.P2; I1.P2 = 11; _ = I1.P3; I1.P3 = 11; _ = I1.P4; I1.P4 = 11; _ = I1.P5; I1.P5 = 11; _ = I1.P6; I1.P6 = 11; } } "; var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2 get_P3 set_P3 get_P4 set_P4 get_P5 set_P5 get_P6 set_P6", symbolValidator: validate, verify: VerifyOnMonoOrCoreClr_FailsIlVerify); validate(compilation1.SourceModule); var source2 = @" class Test1 { static void Main() { _ = I1.P2; I1.P2 = 11; I1.P4 = 11; _ = I1.P5; I1.P5 = 11; I1.P6 = 11; } } "; var compilation2 = CreateCompilation(source0 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P2 set_P2 set_P4 get_P5 set_P5 set_P6 ", verify: VerifyOnMonoOrCoreClr); var compilation3 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); var source3 = @" class Test1 : I1 { static void Main() { _ = I1.P1; I1.P1 = 11; _ = I1.P2; I1.P2 = 11; _ = I1.P4; I1.P4 = 11; _ = I1.P5; I1.P5 = 11; I1.P6 = 11; } } "; var source4 = @" class Test1 { static void Main() { I1.P4 = 11; _ = I1.P5; I1.P6 = 11; } } "; var source5 = @" class Test1 { static void Main() { _ = I1.P1; I1.P1 = 11; _ = I1.P2; I1.P2 = 11; _ = I1.P3; I1.P3 = 11; _ = I1.P4; I1.P5 = 11; _ = I1.P6; } } "; foreach (var reference in new[] { compilation3.ToMetadataReference(), compilation3.EmitToImageReference() }) { var compilation4 = CreateCompilation(source3, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2 get_P4 set_P4 get_P5 set_P5 set_P6 ", verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation5 = CreateCompilation(source4, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation5, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"set_P4 get_P5 set_P6 ", verify: VerifyOnMonoOrCoreClr); var compilation6 = CreateCompilation(source5, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation6.VerifyDiagnostics( // (6,16): error CS0122: 'I1.P1' is inaccessible due to its protection level // _ = I1.P1; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(6, 16), // (7,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 = 11; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(7, 12), // (8,16): error CS0122: 'I1.P2' is inaccessible due to its protection level // _ = I1.P2; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(8, 16), // (9,12): error CS0122: 'I1.P2' is inaccessible due to its protection level // I1.P2 = 11; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(9, 12), // (10,16): error CS0122: 'I1.P3' is inaccessible due to its protection level // _ = I1.P3; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(10, 16), // (11,12): error CS0122: 'I1.P3' is inaccessible due to its protection level // I1.P3 = 11; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(11, 12), // (12,13): error CS0271: The property or indexer 'I1.P4' cannot be used in this context because the get accessor is inaccessible // _ = I1.P4; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P4").WithArguments("I1.P4").WithLocation(12, 13), // (13,9): error CS0272: The property or indexer 'I1.P5' cannot be used in this context because the set accessor is inaccessible // I1.P5 = 11; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "I1.P5").WithArguments("I1.P5").WithLocation(13, 9), // (14,13): error CS0271: The property or indexer 'I1.P6' cannot be used in this context because the get accessor is inaccessible // _ = I1.P6; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P6").WithArguments("I1.P6").WithLocation(14, 13) ); var compilation7 = CreateCompilation(source1, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation7.VerifyDiagnostics( // (10,16): error CS0122: 'I1.P3' is inaccessible due to its protection level // _ = I1.P3; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(10, 16), // (11,12): error CS0122: 'I1.P3' is inaccessible due to its protection level // I1.P3 = 11; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(11, 12), // (16,13): error CS0271: The property or indexer 'I1.P6' cannot be used in this context because the get accessor is inaccessible // _ = I1.P6; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "I1.P6").WithArguments("I1.P6").WithLocation(16, 13) ); } static void validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var tuple in new[] { (name: "P1", access: Accessibility.Protected, getAccess: Accessibility.Protected, setAccess: Accessibility.Protected), (name: "P2", access: Accessibility.ProtectedOrInternal, getAccess: Accessibility.ProtectedOrInternal, setAccess: Accessibility.ProtectedOrInternal), (name: "P3", access: Accessibility.ProtectedAndInternal, getAccess: Accessibility.ProtectedAndInternal, setAccess: Accessibility.ProtectedAndInternal), (name: "P4", access: Accessibility.Public, getAccess: Accessibility.Protected, setAccess: Accessibility.Public), (name: "P5", access: Accessibility.Public, getAccess: Accessibility.Public, setAccess: Accessibility.ProtectedOrInternal), (name: "P6", access: Accessibility.Public, getAccess: Accessibility.ProtectedAndInternal, setAccess: Accessibility.Public)}) { var p1 = i1.GetMember<PropertySymbol>(tuple.name); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(tuple.access, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); validateAccessor(p1.GetMethod, tuple.getAccess); validateAccessor(p1.SetMethod, tuple.setAccess); } void validateAccessor(MethodSymbol accessor, Accessibility accessibility) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } [Fact] public void PropertyModifiers_29() { var source1 = @" public interface I1 { protected abstract int P1 {get; set;} sealed void Test() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_01(source1, source2, Accessibility.Protected, new DiagnosticDescription[] { // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9), // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(17, 9) }, // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ); } [Fact] public void PropertyModifiers_30() { var source1 = @" public interface I1 { protected internal abstract int P1 {get; set;} sealed void Test() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_01(source1, source2, Accessibility.ProtectedOrInternal, new DiagnosticDescription[] { // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9), // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(17, 9) }, // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ); } [Fact] public void PropertyModifiers_31() { var source1 = @" public interface I1 { private protected abstract int P1 {get; set;} sealed void Test() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_01(source1, source2, Accessibility.ProtectedAndInternal, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9), // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(17, 9) ), expectedNoImplementation: ExpectedDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get").WithLocation(12, 9), // (17,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(17, 9) ) ); } [Fact] public void PropertyModifiers_32() { var source1 = @" public interface I1 { abstract int P1 {protected get; set;} void M2() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.Protected, Accessibility.Public, // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9) ); } [Fact] public void PropertyModifiers_33() { var source1 = @" public interface I1 { abstract int P1 {protected internal get; set;} void M2() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.ProtectedOrInternal, Accessibility.Public, // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.get'. 'Test1.P1.get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.P1.get", "Test1.P1.get", "9.0", "10.0").WithLocation(12, 9) ); } [Fact] public void PropertyModifiers_34() { var source1 = @" public interface I1 { abstract int P1 {get; private protected set;} void M2() { P1 = P1; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.Public, Accessibility.ProtectedAndInternal, expectedIn9: ExpectedDiagnostics( // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set", "9.0", "10.0").WithLocation(17, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (17,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.set'. 'Test1.P1.set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.P1.set", "Test1.P1.set").WithLocation(17, 9) ) ); } [Fact] public void PropertyModifiers_35() { var source1 = @" public interface I1 { protected abstract int P1 {get; set;} public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.NetCoreApp); } [Fact] public void PropertyModifiers_36() { var source1 = @" public interface I1 { protected internal abstract int P1 {get; set;} public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.NetCoreApp); } [Fact] public void PropertyModifiers_37() { var source1 = @" public interface I1 { private protected abstract int P1 {get; set;} public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.NetCoreApp, // (9,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // int I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(9, 12) ); } [Fact] public void PropertyModifiers_38() { var source1 = @" public interface I1 { abstract int P1 {protected get; set;} public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.NetCoreApp); } [Fact] public void PropertyModifiers_39() { var source1 = @" public interface I1 { abstract int P1 {get; protected internal set;} public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.NetCoreApp); } [Fact] public void PropertyModifiers_40() { var source1 = @" public interface I1 { abstract int P1 { private protected get; set;} public static void CallP1(I1 x) {x.P1 = x.P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } int I1.P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.NetCoreApp, // (9,12): error CS0122: 'I1.P1.get' is inaccessible due to its protection level // int I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1.get").WithLocation(9, 12) ); } [Fact] public void PropertyModifiers_41() { var source1 = @" public interface I1 { protected int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } void M2() {P1 = P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_20(source1, source2, Accessibility.Protected); } [Fact] public void PropertyModifiers_42() { var source1 = @" public interface I1 { protected internal int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } void M2() {P1 = P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_20(source1, source2, Accessibility.ProtectedOrInternal); } [Fact] public void PropertyModifiers_43() { var source1 = @" public interface I1 { private protected int P1 { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } void M2() {P1 = P1;} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_20(source1, source2, Accessibility.ProtectedAndInternal); } [Fact] public void PropertyModifiers_44() { var source1 = @" public interface I1 { public int P1 { protected get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } static void Test(I1 i1) { i1.P1 = i1.P1; } } public interface I2 { int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } protected set { System.Console.WriteLine(""set_P2""); } } static void Test(I2 i2) { i2.P2 = i2.P2; } } public interface I3 { int P3 { protected get => Test1.GetP3(); set => System.Console.WriteLine(""set_P3""); } static void Test(I3 i3) { i3.P3 = i3.P3; } } public interface I4 { int P4 { get => Test1.GetP4(); protected set => System.Console.WriteLine(""set_P4""); } static void Test(I4 i4) { i4.P4 = i4.P4; } } class Test1 : I1, I2, I3, I4 { static void Main() { I1.Test(new Test1()); I2.Test(new Test1()); I3.Test(new Test1()); I4.Test(new Test1()); } public static int GetP3() { System.Console.WriteLine(""get_P3""); return 0; } public static int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } "; ValidatePropertyModifiers_22(source1, Accessibility.Protected); } [Fact] public void PropertyModifiers_45() { var source1 = @" public interface I1 { public int P1 { protected internal get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } protected internal set { System.Console.WriteLine(""set_P2""); } } } public interface I3 { int P3 { protected internal get => Test1.GetP3(); set => System.Console.WriteLine(""set_P3""); } } public interface I4 { int P4 { get => Test1.GetP4(); protected internal set => System.Console.WriteLine(""set_P4""); } } class Test1 : I1, I2, I3, I4 { static void Main() { I1 i1 = new Test1(); I2 i2 = new Test1(); I3 i3 = new Test1(); I4 i4 = new Test1(); i1.P1 = i1.P1; i2.P2 = i2.P2; i3.P3 = i3.P3; i4.P4 = i4.P4; } public static int GetP3() { System.Console.WriteLine(""get_P3""); return 0; } public static int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } "; ValidatePropertyModifiers_22(source1, Accessibility.ProtectedOrInternal); } [Fact] public void PropertyModifiers_46() { var source1 = @" public interface I1 { public int P1 { private protected get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } static void Test(I1 i1) { i1.P1 = i1.P1; } } public interface I2 { int P2 { get { System.Console.WriteLine(""get_P2""); return 0; } private protected set { System.Console.WriteLine(""set_P2""); } } static void Test(I2 i2) { i2.P2 = i2.P2; } } public interface I3 { int P3 { private protected get => Test1.GetP3(); set => System.Console.WriteLine(""set_P3""); } static void Test(I3 i3) { i3.P3 = i3.P3; } } public interface I4 { int P4 { get => Test1.GetP4(); private protected set => System.Console.WriteLine(""set_P4""); } static void Test(I4 i4) { i4.P4 = i4.P4; } } class Test1 : I1, I2, I3, I4 { static void Main() { I1.Test(new Test1()); I2.Test(new Test1()); I3.Test(new Test1()); I4.Test(new Test1()); } public static int GetP3() { System.Console.WriteLine(""get_P3""); return 0; } public static int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } "; ValidatePropertyModifiers_22(source1, Accessibility.ProtectedAndInternal); } [Fact] public void IndexerModifiers_01() { var source1 = @" public interface I01{ public int this[int x] {get; set;} } public interface I02{ protected int this[int x] {get;} } public interface I03{ protected internal int this[int x] {set;} } public interface I04{ internal int this[int x] {get;} } public interface I05{ private int this[int x] {set;} } public interface I06{ static int this[int x] {get;} } public interface I07{ virtual int this[int x] {set;} } public interface I08{ sealed int this[int x] {get;} } public interface I09{ override int this[int x] {set;} } public interface I10{ abstract int this[int x] {get;} } public interface I11{ extern int this[int x] {get; set;} } public interface I12{ int this[int x] { public get; set;} } public interface I13{ int this[int x] { get; protected set;} } public interface I14{ int this[int x] { protected internal get; set;} } public interface I15{ int this[int x] { get; internal set;} } public interface I16{ int this[int x] { private get; set;} } public interface I17{ int this[int x] { private get;} } public interface I18{ private protected int this[int x] { get; } } public interface I19{ int this[int x] { get; private protected set;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial // public interface I05{ private int this[int x] {set;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), // (7,34): error CS0106: The modifier 'static' is not valid for this item // public interface I06{ static int this[int x] {get;} } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial // public interface I07{ virtual int this[int x] {set;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial // public interface I08{ sealed int this[int x] {get;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), // (10,36): error CS0106: The modifier 'override' is not valid for this item // public interface I09{ override int this[int x] {set;} } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' // public interface I12{ int this[int x] { public get; set;} } Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors // public interface I16{ int this[int x] { private get; set;} } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // public interface I17{ int this[int x] { private get;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52) ); ValidateSymbolsIndexerModifiers_01(compilation1); } private static void ValidateSymbolsIndexerModifiers_01(CSharpCompilation compilation1) { var p01 = compilation1.GetMember<PropertySymbol>("I01.this[]"); Assert.True(p01.IsAbstract); Assert.False(p01.IsVirtual); Assert.False(p01.IsSealed); Assert.False(p01.IsStatic); Assert.False(p01.IsExtern); Assert.False(p01.IsOverride); Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); ValidateP01Accessor(p01.GetMethod); ValidateP01Accessor(p01.SetMethod); void ValidateP01Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p02 = compilation1.GetMember<PropertySymbol>("I02.this[]"); var p02get = p02.GetMethod; Assert.True(p02.IsAbstract); Assert.False(p02.IsVirtual); Assert.False(p02.IsSealed); Assert.False(p02.IsStatic); Assert.False(p02.IsExtern); Assert.False(p02.IsOverride); Assert.Equal(Accessibility.Protected, p02.DeclaredAccessibility); Assert.True(p02get.IsAbstract); Assert.False(p02get.IsVirtual); Assert.True(p02get.IsMetadataVirtual()); Assert.False(p02get.IsSealed); Assert.False(p02get.IsStatic); Assert.False(p02get.IsExtern); Assert.False(p02get.IsAsync); Assert.False(p02get.IsOverride); Assert.Equal(Accessibility.Protected, p02get.DeclaredAccessibility); var p03 = compilation1.GetMember<PropertySymbol>("I03.this[]"); var p03set = p03.SetMethod; Assert.True(p03.IsAbstract); Assert.False(p03.IsVirtual); Assert.False(p03.IsSealed); Assert.False(p03.IsStatic); Assert.False(p03.IsExtern); Assert.False(p03.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, p03.DeclaredAccessibility); Assert.True(p03set.IsAbstract); Assert.False(p03set.IsVirtual); Assert.True(p03set.IsMetadataVirtual()); Assert.False(p03set.IsSealed); Assert.False(p03set.IsStatic); Assert.False(p03set.IsExtern); Assert.False(p03set.IsAsync); Assert.False(p03set.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, p03set.DeclaredAccessibility); var p04 = compilation1.GetMember<PropertySymbol>("I04.this[]"); var p04get = p04.GetMethod; Assert.True(p04.IsAbstract); Assert.False(p04.IsVirtual); Assert.False(p04.IsSealed); Assert.False(p04.IsStatic); Assert.False(p04.IsExtern); Assert.False(p04.IsOverride); Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); Assert.True(p04get.IsAbstract); Assert.False(p04get.IsVirtual); Assert.True(p04get.IsMetadataVirtual()); Assert.False(p04get.IsSealed); Assert.False(p04get.IsStatic); Assert.False(p04get.IsExtern); Assert.False(p04get.IsAsync); Assert.False(p04get.IsOverride); Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); var p05 = compilation1.GetMember<PropertySymbol>("I05.this[]"); var p05set = p05.SetMethod; Assert.False(p05.IsAbstract); Assert.False(p05.IsVirtual); Assert.False(p05.IsSealed); Assert.False(p05.IsStatic); Assert.False(p05.IsExtern); Assert.False(p05.IsOverride); Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); Assert.False(p05set.IsAbstract); Assert.False(p05set.IsVirtual); Assert.False(p05set.IsMetadataVirtual()); Assert.False(p05set.IsSealed); Assert.False(p05set.IsStatic); Assert.False(p05set.IsExtern); Assert.False(p05set.IsAsync); Assert.False(p05set.IsOverride); Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); var p06 = compilation1.GetMember<PropertySymbol>("I06.this[]"); var p06get = p06.GetMethod; Assert.True(p06.IsAbstract); Assert.False(p06.IsVirtual); Assert.False(p06.IsSealed); Assert.False(p06.IsStatic); Assert.False(p06.IsExtern); Assert.False(p06.IsOverride); Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); Assert.True(p06get.IsAbstract); Assert.False(p06get.IsVirtual); Assert.True(p06get.IsMetadataVirtual()); Assert.False(p06get.IsSealed); Assert.False(p06get.IsStatic); Assert.False(p06get.IsExtern); Assert.False(p06get.IsAsync); Assert.False(p06get.IsOverride); Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); var p07 = compilation1.GetMember<PropertySymbol>("I07.this[]"); var p07set = p07.SetMethod; Assert.False(p07.IsAbstract); Assert.True(p07.IsVirtual); Assert.False(p07.IsSealed); Assert.False(p07.IsStatic); Assert.False(p07.IsExtern); Assert.False(p07.IsOverride); Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); Assert.False(p07set.IsAbstract); Assert.True(p07set.IsVirtual); Assert.True(p07set.IsMetadataVirtual()); Assert.False(p07set.IsSealed); Assert.False(p07set.IsStatic); Assert.False(p07set.IsExtern); Assert.False(p07set.IsAsync); Assert.False(p07set.IsOverride); Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); var p08 = compilation1.GetMember<PropertySymbol>("I08.this[]"); var p08get = p08.GetMethod; Assert.False(p08.IsAbstract); Assert.False(p08.IsVirtual); Assert.False(p08.IsSealed); Assert.False(p08.IsStatic); Assert.False(p08.IsExtern); Assert.False(p08.IsOverride); Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); Assert.False(p08get.IsAbstract); Assert.False(p08get.IsVirtual); Assert.False(p08get.IsMetadataVirtual()); Assert.False(p08get.IsSealed); Assert.False(p08get.IsStatic); Assert.False(p08get.IsExtern); Assert.False(p08get.IsAsync); Assert.False(p08get.IsOverride); Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); var p09 = compilation1.GetMember<PropertySymbol>("I09.this[]"); var p09set = p09.SetMethod; Assert.True(p09.IsAbstract); Assert.False(p09.IsVirtual); Assert.False(p09.IsSealed); Assert.False(p09.IsStatic); Assert.False(p09.IsExtern); Assert.False(p09.IsOverride); Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); Assert.True(p09set.IsAbstract); Assert.False(p09set.IsVirtual); Assert.True(p09set.IsMetadataVirtual()); Assert.False(p09set.IsSealed); Assert.False(p09set.IsStatic); Assert.False(p09set.IsExtern); Assert.False(p09set.IsAsync); Assert.False(p09set.IsOverride); Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); var p10 = compilation1.GetMember<PropertySymbol>("I10.this[]"); var p10get = p10.GetMethod; Assert.True(p10.IsAbstract); Assert.False(p10.IsVirtual); Assert.False(p10.IsSealed); Assert.False(p10.IsStatic); Assert.False(p10.IsExtern); Assert.False(p10.IsOverride); Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); Assert.True(p10get.IsAbstract); Assert.False(p10get.IsVirtual); Assert.True(p10get.IsMetadataVirtual()); Assert.False(p10get.IsSealed); Assert.False(p10get.IsStatic); Assert.False(p10get.IsExtern); Assert.False(p10get.IsAsync); Assert.False(p10get.IsOverride); Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); var p11 = compilation1.GetMember<PropertySymbol>("I11.this[]"); Assert.False(p11.IsAbstract); Assert.True(p11.IsVirtual); Assert.False(p11.IsSealed); Assert.False(p11.IsStatic); Assert.True(p11.IsExtern); Assert.False(p11.IsOverride); Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); ValidateP11Accessor(p11.GetMethod); ValidateP11Accessor(p11.SetMethod); void ValidateP11Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p12 = compilation1.GetMember<PropertySymbol>("I12.this[]"); Assert.True(p12.IsAbstract); Assert.False(p12.IsVirtual); Assert.False(p12.IsSealed); Assert.False(p12.IsStatic); Assert.False(p12.IsExtern); Assert.False(p12.IsOverride); Assert.Equal(Accessibility.Public, p12.DeclaredAccessibility); ValidateP12Accessor(p12.GetMethod); ValidateP12Accessor(p12.SetMethod); void ValidateP12Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p13 = compilation1.GetMember<PropertySymbol>("I13.this[]"); Assert.True(p13.IsAbstract); Assert.False(p13.IsVirtual); Assert.False(p13.IsSealed); Assert.False(p13.IsStatic); Assert.False(p13.IsExtern); Assert.False(p13.IsOverride); Assert.Equal(Accessibility.Public, p13.DeclaredAccessibility); ValidateP13Accessor(p13.GetMethod, Accessibility.Public); ValidateP13Accessor(p13.SetMethod, Accessibility.Protected); void ValidateP13Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p14 = compilation1.GetMember<PropertySymbol>("I14.this[]"); Assert.True(p14.IsAbstract); Assert.False(p14.IsVirtual); Assert.False(p14.IsSealed); Assert.False(p14.IsStatic); Assert.False(p14.IsExtern); Assert.False(p14.IsOverride); Assert.Equal(Accessibility.Public, p14.DeclaredAccessibility); ValidateP14Accessor(p14.GetMethod, Accessibility.ProtectedOrInternal); ValidateP14Accessor(p14.SetMethod, Accessibility.Public); void ValidateP14Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p15 = compilation1.GetMember<PropertySymbol>("I15.this[]"); Assert.True(p15.IsAbstract); Assert.False(p15.IsVirtual); Assert.False(p15.IsSealed); Assert.False(p15.IsStatic); Assert.False(p15.IsExtern); Assert.False(p15.IsOverride); Assert.Equal(Accessibility.Public, p15.DeclaredAccessibility); ValidateP15Accessor(p15.GetMethod, Accessibility.Public); ValidateP15Accessor(p15.SetMethod, Accessibility.Internal); void ValidateP15Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p16 = compilation1.GetMember<PropertySymbol>("I16.this[]"); Assert.True(p16.IsAbstract); Assert.False(p16.IsVirtual); Assert.False(p16.IsSealed); Assert.False(p16.IsStatic); Assert.False(p16.IsExtern); Assert.False(p16.IsOverride); Assert.Equal(Accessibility.Public, p16.DeclaredAccessibility); ValidateP16Accessor(p16.GetMethod, Accessibility.Private); ValidateP16Accessor(p16.SetMethod, Accessibility.Public); void ValidateP16Accessor(MethodSymbol accessor, Accessibility accessibility) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(accessibility, accessor.DeclaredAccessibility); } var p17 = compilation1.GetMember<PropertySymbol>("I17.this[]"); var p17get = p17.GetMethod; Assert.True(p17.IsAbstract); Assert.False(p17.IsVirtual); Assert.False(p17.IsSealed); Assert.False(p17.IsStatic); Assert.False(p17.IsExtern); Assert.False(p17.IsOverride); Assert.Equal(Accessibility.Public, p17.DeclaredAccessibility); Assert.True(p17get.IsAbstract); Assert.False(p17get.IsVirtual); Assert.True(p17get.IsMetadataVirtual()); Assert.False(p17get.IsSealed); Assert.False(p17get.IsStatic); Assert.False(p17get.IsExtern); Assert.False(p17get.IsAsync); Assert.False(p17get.IsOverride); Assert.Equal(Accessibility.Private, p17get.DeclaredAccessibility); var p18 = compilation1.GetMember<PropertySymbol>("I18.this[]"); var p18get = p18.GetMethod; Assert.True(p18.IsAbstract); Assert.False(p18.IsVirtual); Assert.False(p18.IsSealed); Assert.False(p18.IsStatic); Assert.False(p18.IsExtern); Assert.False(p18.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, p18.DeclaredAccessibility); Assert.True(p18get.IsAbstract); Assert.False(p18get.IsVirtual); Assert.True(p18get.IsMetadataVirtual()); Assert.False(p18get.IsSealed); Assert.False(p18get.IsStatic); Assert.False(p18get.IsExtern); Assert.False(p18get.IsAsync); Assert.False(p18get.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, p18get.DeclaredAccessibility); var p19 = compilation1.GetMember<PropertySymbol>("I19.this[]"); Assert.True(p19.IsAbstract); Assert.False(p19.IsVirtual); Assert.False(p19.IsSealed); Assert.False(p19.IsStatic); Assert.False(p19.IsExtern); Assert.False(p19.IsOverride); Assert.Equal(Accessibility.Public, p19.DeclaredAccessibility); ValidateP13Accessor(p19.GetMethod, Accessibility.Public); ValidateP13Accessor(p19.SetMethod, Accessibility.ProtectedAndInternal); } [Fact] public void IndexerModifiers_02() { var source1 = @" public interface I01{ public int this[int x] {get; set;} } public interface I02{ protected int this[int x] {get;} } public interface I03{ protected internal int this[int x] {set;} } public interface I04{ internal int this[int x] {get;} } public interface I05{ private int this[int x] {set;} } public interface I06{ static int this[int x] {get;} } public interface I07{ virtual int this[int x] {set;} } public interface I08{ sealed int this[int x] {get;} } public interface I09{ override int this[int x] {set;} } public interface I10{ abstract int this[int x] {get;} } public interface I11{ extern int this[int x] {get; set;} } public interface I12{ int this[int x] { public get; set;} } public interface I13{ int this[int x] { get; protected set;} } public interface I14{ int this[int x] { protected internal get; set;} } public interface I15{ int this[int x] { get; internal set;} } public interface I16{ int this[int x] { private get; set;} } public interface I17{ int this[int x] { private get;} } public interface I18{ private protected int this[int x] { get; } } public interface I19{ int this[int x] { get; private protected set;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (2,34): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I01{ public int this[int x] {get; set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("public", "7.3", "8.0").WithLocation(2, 34), // (3,37): error CS8703: The modifier 'protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I02{ protected int this[int x] {get;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("protected", "7.3", "8.0").WithLocation(3, 37), // (4,46): error CS8703: The modifier 'protected internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I03{ protected internal int this[int x] {set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("protected internal", "7.3", "8.0").WithLocation(4, 46), // (5,36): error CS8503: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I04{ internal int this[int x] {get;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("internal", "7.3", "8.0").WithLocation(5, 36), // (6,35): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I05{ private int this[int x] {set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("private", "7.3", "8.0").WithLocation(6, 35), // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial // public interface I05{ private int this[int x] {set;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), // (7,34): error CS0106: The modifier 'static' is not valid for this item // public interface I06{ static int this[int x] {get;} } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), // (8,35): error CS8503: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I07{ virtual int this[int x] {set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("virtual", "7.3", "8.0").WithLocation(8, 35), // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial // public interface I07{ virtual int this[int x] {set;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), // (9,34): error CS8503: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I08{ sealed int this[int x] {get;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("sealed", "7.3", "8.0").WithLocation(9, 34), // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial // public interface I08{ sealed int this[int x] {get;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), // (10,36): error CS0106: The modifier 'override' is not valid for this item // public interface I09{ override int this[int x] {set;} } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), // (11,36): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I10{ abstract int this[int x] {get;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("abstract", "7.3", "8.0").WithLocation(11, 36), // (12,34): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("extern", "7.3", "8.0").WithLocation(12, 34), // (14,48): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I12{ int this[int x] { public get; set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("public", "7.3", "8.0").WithLocation(14, 48), // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' // public interface I12{ int this[int x] { public get; set;} } Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), // (15,56): error CS8703: The modifier 'protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I13{ int this[int x] { get; protected set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("protected", "7.3", "8.0").WithLocation(15, 56), // (16,60): error CS8703: The modifier 'protected internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I14{ int this[int x] { protected internal get; set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("protected internal", "7.3", "8.0").WithLocation(16, 60), // (17,55): error CS8503: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I15{ int this[int x] { get; internal set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("internal", "7.3", "8.0").WithLocation(17, 55), // (18,49): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I16{ int this[int x] { private get; set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("private", "7.3", "8.0").WithLocation(18, 49), // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors // public interface I16{ int this[int x] { private get; set;} } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), // (19,49): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I17{ int this[int x] { private get;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "get").WithArguments("private", "7.3", "8.0").WithLocation(19, 49), // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // public interface I17{ int this[int x] { private get;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), // (21,45): error CS8703: The modifier 'private protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I18{ private protected int this[int x] { get; } } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("private protected", "7.3", "8.0").WithLocation(21, 45), // (22,64): error CS8703: The modifier 'private protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public interface I19{ int this[int x] { get; private protected set;} } Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("private protected", "7.3", "8.0").WithLocation(22, 64), // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52) ); ValidateSymbolsIndexerModifiers_01(compilation1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (3,37): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // public interface I02{ protected int this[int x] {get;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "this").WithLocation(3, 37), // (4,46): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // public interface I03{ protected internal int this[int x] {set;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "this").WithLocation(4, 46), // (6,48): error CS0501: 'I05.this[int].set' must declare a body because it is not marked abstract, extern, or partial // public interface I05{ private int this[int x] {set;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I05.this[int].set").WithLocation(6, 48), // (7,34): error CS0106: The modifier 'static' is not valid for this item // public interface I06{ static int this[int x] {get;} } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(7, 34), // (8,48): error CS0501: 'I07.this[int].set' must declare a body because it is not marked abstract, extern, or partial // public interface I07{ virtual int this[int x] {set;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I07.this[int].set").WithLocation(8, 48), // (9,47): error CS0501: 'I08.this[int].get' must declare a body because it is not marked abstract, extern, or partial // public interface I08{ sealed int this[int x] {get;} } Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I08.this[int].get").WithLocation(9, 47), // (10,36): error CS0106: The modifier 'override' is not valid for this item // public interface I09{ override int this[int x] {set;} } Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(10, 36), // (12,47): error CS8701: Target runtime doesn't support default interface implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(12, 47), // (12,47): warning CS0626: Method, operator, or accessor 'I11.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I11.this[int].get").WithLocation(12, 47), // (12,52): error CS8701: Target runtime doesn't support default interface implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(12, 52), // (12,52): warning CS0626: Method, operator, or accessor 'I11.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // public interface I11{ extern int this[int x] {get; set;} } Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I11.this[int].set").WithLocation(12, 52), // (14,48): error CS0273: The accessibility modifier of the 'I12.this[int].get' accessor must be more restrictive than the property or indexer 'I12.this[int]' // public interface I12{ int this[int x] { public get; set;} } Diagnostic(ErrorCode.ERR_InvalidPropertyAccessMod, "get").WithArguments("I12.this[int].get", "I12.this[int]").WithLocation(14, 48), // (15,56): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // public interface I13{ int this[int x] { get; protected set;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(15, 56), // (16,60): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // public interface I14{ int this[int x] { protected internal get; set;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "get").WithLocation(16, 60), // (18,49): error CS0442: 'I16.this[int].get': abstract properties cannot have private accessors // public interface I16{ int this[int x] { private get; set;} } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I16.this[int].get").WithLocation(18, 49), // (19,27): error CS0276: 'I17.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // public interface I17{ int this[int x] { private get;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I17.this[int]").WithLocation(19, 27), // (21,45): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // public interface I18{ private protected int this[int x] { get; } } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "this").WithLocation(21, 45), // (22,64): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // public interface I19{ int this[int x] { get; private protected set;} } Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(22, 64) ); ValidateSymbolsIndexerModifiers_01(compilation2); } [Fact] public void IndexerModifiers_03() { ValidateIndexerImplementation_101(@" public interface I1 { public virtual int this[int i] { get { System.Console.WriteLine(""get P1""); return 0; } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); _ = i1[0]; } } "); ValidateIndexerImplementation_101(@" public interface I1 { public virtual int this[int i] { get => Test1.GetP1(); } } class Test1 : I1 { public static int GetP1() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); _ = i1[0]; } } "); ValidateIndexerImplementation_101(@" public interface I1 { public virtual int this[int i] => Test1.GetP1(); } class Test1 : I1 { public static int GetP1() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); _ = i1[0]; } } "); ValidateIndexerImplementation_102(@" public interface I1 { public virtual int this[int i] { get { System.Console.WriteLine(""get P1""); return 0; } set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1[0] = i1[0]; } } "); ValidateIndexerImplementation_102(@" public interface I1 { public virtual int this[int i] { get => Test1.GetP1(); set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 { public static int GetP1() { System.Console.WriteLine(""get P1""); return 0; } static void Main() { I1 i1 = new Test1(); i1[0] = i1[0]; } } "); ValidateIndexerImplementation_103(@" public interface I1 { public virtual int this[int i] { set { System.Console.WriteLine(""set P1""); } } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1[0] = 1; } } "); ValidateIndexerImplementation_103(@" public interface I1 { public virtual int this[int i] { set => System.Console.WriteLine(""set P1""); } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1[0] = 1; } } "); } [Fact] public void IndexerModifiers_04() { var source1 = @" public interface I1 { public virtual int this[int x] { get; } = 0; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (4,45): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // public virtual int this[int x] { get; } = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 45), // (4,38): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial // public virtual int this[int x] { get; } = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 38) ); ValidatePropertyModifiers_04(compilation1, "this[]"); } [Fact] public void IndexerModifiers_05() { var source1 = @" public interface I1 { public abstract int this[int x] {get; set;} } public interface I2 { int this[int x] {get; set;} } class Test1 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set => System.Console.WriteLine(""set_P1""); } } class Test2 : I2 { public int this[int x] { get { System.Console.WriteLine(""get_P2""); return 0; } set => System.Console.WriteLine(""set_P2""); } static void Main() { I1 x = new Test1(); x[0] = x[0]; I2 y = new Test2(); y[0] = y[0]; } } "; ValidatePropertyModifiers_05(source1); } [Fact] public void IndexerModifiers_06() { var source1 = @" public interface I1 { public abstract int this[int x] {get; set;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3); compilation1.VerifyDiagnostics( // (4,25): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("abstract", "7.3", "8.0").WithLocation(4, 25), // (4,25): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("public", "7.3", "8.0").WithLocation(4, 25) ); ValidatePropertyModifiers_06(compilation1, "this[]"); } [Fact] public void IndexerModifiers_09() { var source1 = @" public interface I1 { private int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } } sealed void M() { var x = this[0]; } } public interface I2 { private int this[int x] { get { System.Console.WriteLine(""get_P2""); return 0; } set { System.Console.WriteLine(""set_P2""); } } sealed void M() { this[0] = this[0]; } } public interface I3 { private int this[int x] { set { System.Console.WriteLine(""set_P3""); } } sealed void M() { this[0] = 0; } } public interface I4 { private int this[int x] { get => GetP4(); } private int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } sealed void M() { var x = this[0]; } } public interface I5 { private int this[int x] { get => GetP5(); set => System.Console.WriteLine(""set_P5""); } private int GetP5() { System.Console.WriteLine(""get_P5""); return 0; } sealed void M() { this[0] = this[0]; } } public interface I6 { private int this[int x] { set => System.Console.WriteLine(""set_P6""); } sealed void M() { this[0] = 0; } } public interface I7 { private int this[int x] => GetP7(); private int GetP7() { System.Console.WriteLine(""get_P7""); return 0; } sealed void M() { var x = this[0]; } } class Test1 : I1, I2, I3, I4, I5, I6, I7 { static void Main() { I1 x1 = new Test1(); x1.M(); I2 x2 = new Test1(); x2.M(); I3 x3 = new Test1(); x3.M(); I4 x4 = new Test1(); x4.M(); I5 x5 = new Test1(); x5.M(); I6 x6 = new Test1(); x6.M(); I7 x7 = new Test1(); x7.M(); } } "; ValidatePropertyModifiers_09(source1); } [Fact] public void IndexerModifiers_10() { var source1 = @" public interface I1 { abstract private int this[byte x] { get; } virtual private int this[int x] => 0; sealed private int this[short x] { get => 0; set {} } private int this[long x] {get;} = 0; } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,37): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // private int this[long x] {get;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(14, 37), // (4,26): error CS0621: 'I1.this[byte]': virtual or abstract members cannot be private // abstract private int this[byte x] { get; } Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I1.this[byte]").WithLocation(4, 26), // (6,25): error CS0621: 'I1.this[int]': virtual or abstract members cannot be private // virtual private int this[int x] => 0; Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I1.this[int]").WithLocation(6, 25), // (8,24): error CS0238: 'I1.this[short]' cannot be sealed because it is not an override // sealed private int this[short x] Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I1.this[short]").WithLocation(8, 24), // (14,31): error CS0501: 'I1.this[long].get' must declare a body because it is not marked abstract, extern, or partial // private int this[long x] {get;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[long].get").WithLocation(14, 31), // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.this[byte]' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[byte]") ); ValidatePropertyModifiers_10(compilation1); } [Fact] public void IndexerModifiers_11_01() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} sealed void Test() { this[0] = this[0]; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_01(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(12, 9), // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(17, 9) ), expectedNoImplementation: ExpectedDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.this[int]' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.this[int]") ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(12, 9), // (17,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(17, 9) ) ); } [Fact] public void IndexerModifiers_11_02() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_11_03() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } int I1.this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,12): error CS0122: 'I1.this[int]' is inaccessible due to its protection level // int I1.this[int x] Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int]").WithLocation(9, 12) ); } [Fact] public void IndexerModifiers_11_04() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_11_05() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_11_06() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract int this[int x] {get; set;} } class Test3 : Test1 { public override int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,38): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(9, 38), // (9,43): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(9, 43) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,38): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(9, 38), // (9,43): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(9, 43) ) ); } [Fact] public void IndexerModifiers_11_07() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int this[int x] {get; set;} } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_11_08() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long this[int x] { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_08(source1, source2); } [Fact] public void IndexerModifiers_11_09() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long this[int x] { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.this[int]'. 'Test1.this[int]' cannot implement 'I1.this[int]' because it does not have the matching return type of 'int'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.this[int]", "Test1.this[int]", "int").WithLocation(2, 15) ); } [Fact] public void IndexerModifiers_11_10() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} sealed void Test() { this[0] = this[0]; } } "; var source2 = @" public class Test2 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (6,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get", "9.0", "10.0").WithLocation(6, 9), // (11,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (6,9): error CS9044: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get").WithLocation(6, 9), // (11,9): error CS9044: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set").WithLocation(11, 9) ) ); } [Fact] public void IndexerModifiers_11_11() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} sealed void Test() { this[0] = this[0]; } } public class Test2 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_11(source1, source2, // (15,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get", "9.0", "10.0").WithLocation(15, 9), // (20,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set", "9.0", "10.0").WithLocation(20, 9) ); } [Fact] public void IndexerModifiers_12() { var source1 = @" public interface I1 { internal abstract int this[int x] {get; set;} } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]") ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<PropertySymbol>("this[]"); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test1.FindImplementationForInterfaceMember(p1.GetMethod)); Assert.Null(test1.FindImplementationForInterfaceMember(p1.SetMethod)); } [Fact] public void IndexerModifiers_13() { var source1 = @" public interface I1 { public sealed int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } } } public interface I2 { public sealed int this[int x] { get { System.Console.WriteLine(""get_P2""); return 0; } set { System.Console.WriteLine(""set_P2""); } } } public interface I3 { public sealed int this[int x] { set { System.Console.WriteLine(""set_P3""); } } } public interface I4 { public sealed int this[int x] { get => GetP4(); } private int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } public interface I5 { public sealed int this[int x] { get => GetP5(); set => System.Console.WriteLine(""set_P5""); } private int GetP5() { System.Console.WriteLine(""get_P5""); return 0; } } public interface I6 { public sealed int this[int x] { set => System.Console.WriteLine(""set_P6""); } } public interface I7 { public sealed int this[int x] => GetP7(); private int GetP7() { System.Console.WriteLine(""get_P7""); return 0; } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); var x = i1[0]; I2 i2 = new Test2(); i2[0] = i2[0]; I3 i3 = new Test3(); i3[0] = x; I4 i4 = new Test4(); x = i4[0]; I5 i5 = new Test5(); i5[0] = i5[0]; I6 i6 = new Test6(); i6[0] = x; I7 i7 = new Test7(); x = i7[0]; } public int this[int x] => throw null; } class Test2 : I2 { public int this[int x] { get => throw null; set => throw null; } } class Test3 : I3 { public int this[int x] { set => throw null; } } class Test4 : I4 { public int this[int x] { get => throw null; } } class Test5 : I5 { public int this[int x] { get => throw null; set => throw null; } } class Test6 : I6 { public int this[int x] { set => throw null; } } class Test7 : I7 { public int this[int x] => throw null; } "; ValidatePropertyModifiers_13(source1); } [Fact] public void AccessModifiers_14() { var source1 = @" public interface I1 { public sealed int this[int x] {get;} = 0; } public interface I2 { abstract sealed int this[int x] {get;} } public interface I3 { virtual sealed int this[int x] { set {} } } class Test1 : I1, I2, I3 { int I1.this[int x] { get => throw null; } int I2.this[int x] { get => throw null; } int I3.this[int x] { set => throw null; } } class Test2 : I1, I2, I3 {} "; ValidatePropertyModifiers_14(source1, // (4,42): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // public sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(4, 42), // (4,36): error CS0501: 'I1.this[int].get' must declare a body because it is not marked abstract, extern, or partial // public sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 36), // (8,25): error CS0238: 'I2.this[int]' cannot be sealed because it is not an override // abstract sealed int this[int x] {get;} Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I2.this[int]").WithLocation(8, 25), // (12,24): error CS0238: 'I3.this[int]' cannot be sealed because it is not an override // virtual sealed int this[int x] Diagnostic(ErrorCode.ERR_SealedNonOverride, "this").WithArguments("I3.this[int]").WithLocation(12, 24), // (20,12): error CS0539: 'Test1.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented // int I1.this[int x] { get => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test1.this[int]").WithLocation(20, 12), // (21,12): error CS0539: 'Test1.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented // int I2.this[int x] { get => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test1.this[int]").WithLocation(21, 12), // (22,12): error CS0539: 'Test1.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented // int I3.this[int x] { set => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test1.this[int]").WithLocation(22, 12) ); } [Fact] [WorkItem(38398, "https://github.com/dotnet/roslyn/issues/38398")] public void InconsistentAccessibility_01() { var source1 = @" interface I1 { protected interface I2 { } } class C1 { protected interface I2 { } } interface I3 : I1 { protected I1.I2 M1(); protected interface I5 { I1.I2 M5(); } } class CI3 : I3 { I1.I2 I3.M1() => null; class CI5 : I3.I5 { I1.I2 I3.I5.M5() => null; } } class C3 : I1 { protected virtual void M1(I1.I2 x) { } protected interface I7 { I1.I2 M7(); } } class CC3 : C3 { protected override void M1(I1.I2 x) { } class CI7 : C3.I7 { I1.I2 C3.I7.M7() => null; } } class C33 : C1 { protected virtual void M1(C1.I2 x) { } protected class C55 { public virtual C1.I2 M55() => null; } } class CC33 : C33 { protected override void M1(C1.I2 x) { } class CC55 : C33.C55 { public override C1.I2 M55() => null; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr).VerifyDiagnostics(); } [Fact] [WorkItem(38398, "https://github.com/dotnet/roslyn/issues/38398")] public void InconsistentAccessibility_02() { var source1 = @" interface I1 { protected interface I2 { } } class C1 { protected interface I2 { } } interface I3 : I1 { interface I4 { protected I1.I2 M4(); } } class CI4 : I3.I4 { I1.I2 I3.I4.M4() => null; } class C3 : I1 { public interface I6 { protected I1.I2 M6(); } } class CI6 : C3.I6 { I1.I2 C3.I6.M6() => null; } class C33 : C1 { public class C44 { protected virtual C1.I2 M44() => null; } } class CC44 : C33.C44 { protected override C1.I2 M44() => null; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (20,29): error CS0050: Inconsistent accessibility: return type 'I1.I2' is less accessible than method 'I3.I4.M4()' // protected I1.I2 M4(); Diagnostic(ErrorCode.ERR_BadVisReturnType, "M4").WithArguments("I3.I4.M4()", "I1.I2").WithLocation(20, 29), // (24,17): error CS0535: 'CI4' does not implement interface member 'I3.I4.M4()' // class CI4 : I3.I4 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3.I4").WithArguments("CI4", "I3.I4.M4()").WithLocation(24, 17), // (26,12): error CS0122: 'I1.I2' is inaccessible due to its protection level // I1.I2 I3.I4.M4() => null; Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1.I2").WithLocation(26, 12), // (26,21): error CS9334: 'CI4.M4()' return type must be 'I1.I2' to match implemented member 'I3.I4.M4()' // I1.I2 I3.I4.M4() => null; Diagnostic(ErrorCode.ERR_ExplicitInterfaceMemberReturnTypeMismatch, "M4").WithArguments("CI4.M4()", "I1.I2", "I3.I4.M4()").WithLocation(26, 21), // (33,29): error CS0050: Inconsistent accessibility: return type 'I1.I2' is less accessible than method 'C3.I6.M6()' // protected I1.I2 M6(); Diagnostic(ErrorCode.ERR_BadVisReturnType, "M6").WithArguments("C3.I6.M6()", "I1.I2").WithLocation(33, 29), // (37,17): error CS0535: 'CI6' does not implement interface member 'C3.I6.M6()' // class CI6 : C3.I6 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "C3.I6").WithArguments("CI6", "C3.I6.M6()").WithLocation(37, 17), // (39,12): error CS0122: 'I1.I2' is inaccessible due to its protection level // I1.I2 C3.I6.M6() => null; Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1.I2").WithLocation(39, 12), // (39,21): error CS9334: 'CI6.M6()' return type must be 'I1.I2' to match implemented member 'C3.I6.M6()' // I1.I2 C3.I6.M6() => null; Diagnostic(ErrorCode.ERR_ExplicitInterfaceMemberReturnTypeMismatch, "M6").WithArguments("CI6.M6()", "I1.I2", "C3.I6.M6()").WithLocation(39, 21), // (46,37): error CS0050: Inconsistent accessibility: return type 'C1.I2' is less accessible than method 'C33.C44.M44()' // protected virtual C1.I2 M44() => null; Diagnostic(ErrorCode.ERR_BadVisReturnType, "M44").WithArguments("C33.C44.M44()", "C1.I2").WithLocation(46, 37), // (52,31): error CS0122: 'C1.I2' is inaccessible due to its protection level // protected override C1.I2 M44() => null; Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("C1.I2").WithLocation(52, 31) ); } [Fact] [WorkItem(38398, "https://github.com/dotnet/roslyn/issues/38398")] public void InconsistentAccessibility_03() { var source1 = @" interface I1<T> { protected interface I2 { } } class C1<T> { protected interface I2 { } } interface I3 : I1<int> { protected I1<string>.I2 M1(); protected interface I5 { I1<string>.I2 M5(); } } class CI3 : I3 { I1<string>.I2 I3.M1() => null; class CI5 : I3.I5 { I1<string>.I2 I3.I5.M5() => null; } } class C3 : I1<int> { protected virtual void M1(I1<string>.I2 x) { } protected interface I7 { I1<string>.I2 M7(); } } class CC3 : C3 { protected override void M1(I1<string>.I2 x) { } class CI7 : C3.I7 { I1<string>.I2 C3.I7.M7() => null; } } class C33 : C1<int> { protected virtual void M1(C1<string>.I2 x) { } protected class C55 { public virtual C1<string>.I2 M55() => null; } } class CC33 : C33 { protected override void M1(C1<string>.I2 x) { } class CC55 : C33.C55 { public override C1<string>.I2 M55() => null; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr).VerifyDiagnostics(); } [Fact] [WorkItem(38398, "https://github.com/dotnet/roslyn/issues/38398")] public void InconsistentAccessibility_04() { var source1 = @" interface I1<T> { protected interface I2 { } } class C1<T> { protected interface I2 { } } interface I3 : I1<int> { interface I4 { protected I1<string>.I2 M4(); } } class CI4 : I3.I4 { I1<string>.I2 I3.I4.M4() => null; } class C3 : I1<int> { public interface I6 { protected I1<string>.I2 M6(); } } class CI6 : C3.I6 { I1<string>.I2 C3.I6.M6() => null; } class C33 : C1<int> { public class C44 { protected virtual C1<string>.I2 M44() => null; } } class CC44 : C33.C44 { protected override C1<string>.I2 M44() => null; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (20,37): error CS0050: Inconsistent accessibility: return type 'I1<string>.I2' is less accessible than method 'I3.I4.M4()' // protected I1<string>.I2 M4(); Diagnostic(ErrorCode.ERR_BadVisReturnType, "M4").WithArguments("I3.I4.M4()", "I1<string>.I2").WithLocation(20, 37), // (24,17): error CS0535: 'CI4' does not implement interface member 'I3.I4.M4()' // class CI4 : I3.I4 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3.I4").WithArguments("CI4", "I3.I4.M4()").WithLocation(24, 17), // (26,20): error CS0122: 'I1<string>.I2' is inaccessible due to its protection level // I1<string>.I2 I3.I4.M4() => null; Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1<string>.I2").WithLocation(26, 20), // (26,29): error CS9334: 'CI4.M4()' type must be 'I1<string>.I2' to match implemented member 'I3.I4.M4()' // I1<string>.I2 I3.I4.M4() => null; Diagnostic(ErrorCode.ERR_ExplicitInterfaceMemberReturnTypeMismatch, "M4").WithArguments("CI4.M4()", "I1<string>.I2", "I3.I4.M4()").WithLocation(26, 29), // (33,37): error CS0050: Inconsistent accessibility: return type 'I1<string>.I2' is less accessible than method 'C3.I6.M6()' // protected I1<string>.I2 M6(); Diagnostic(ErrorCode.ERR_BadVisReturnType, "M6").WithArguments("C3.I6.M6()", "I1<string>.I2").WithLocation(33, 37), // (37,17): error CS0535: 'CI6' does not implement interface member 'C3.I6.M6()' // class CI6 : C3.I6 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "C3.I6").WithArguments("CI6", "C3.I6.M6()").WithLocation(37, 17), // (39,20): error CS0122: 'I1<string>.I2' is inaccessible due to its protection level // I1<string>.I2 C3.I6.M6() => null; Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1<string>.I2").WithLocation(39, 20), // (39,29): error CS9334: 'CI6.M6()' type must be 'I1<string>.I2' to match implemented member 'C3.I6.M6()' // I1<string>.I2 C3.I6.M6() => null; Diagnostic(ErrorCode.ERR_ExplicitInterfaceMemberReturnTypeMismatch, "M6").WithArguments("CI6.M6()", "I1<string>.I2", "C3.I6.M6()").WithLocation(39, 29), // (46,45): error CS0050: Inconsistent accessibility: return type 'C1<string>.I2' is less accessible than method 'C33.C44.M44()' // protected virtual C1<string>.I2 M44() => null; Diagnostic(ErrorCode.ERR_BadVisReturnType, "M44").WithArguments("C33.C44.M44()", "C1<string>.I2").WithLocation(46, 45), // (52,39): error CS0122: 'C1<string>.I2' is inaccessible due to its protection level // protected override C1<string>.I2 M44() => null; Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("C1<string>.I2").WithLocation(52, 39) ); } [Fact] public void IndexerModifiers_15() { var source1 = @" public interface I0 { abstract virtual int this[int x] { get; set; } } public interface I1 { abstract virtual int this[int x] { get { throw null; } } } public interface I2 { virtual abstract int this[int x] { get { throw null; } set { throw null; } } } public interface I3 { abstract virtual int this[int x] { set { throw null; } } } public interface I4 { abstract virtual int this[int x] { get => throw null; } } public interface I5 { abstract virtual int this[int x] { get => throw null; set => throw null; } } public interface I6 { abstract virtual int this[int x] { set => throw null; } } public interface I7 { abstract virtual int this[int x] => throw null; } public interface I8 { abstract virtual int this[int x] {get;} = 0; } class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 { int I0.this[int x] { get { throw null; } set { throw null; } } int I1.this[int x] { get { throw null; } } int I2.this[int x] { get { throw null; } set { throw null; } } int I3.this[int x] { set { throw null; } } int I4.this[int x] { get { throw null; } } int I5.this[int x] { get { throw null; } set { throw null; } } int I6.this[int x] { set { throw null; } } int I7.this[int x] { get { throw null; } } int I8.this[int x] { get { throw null; } } } class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 {} "; ValidatePropertyModifiers_15(source1, // (44,45): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // abstract virtual int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(44, 45), // (4,26): error CS0503: The abstract property 'I0.this[int]' cannot be marked virtual // abstract virtual int this[int x] { get; set; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I0.this[int]").WithLocation(4, 26), // (8,26): error CS0503: The abstract property 'I1.this[int]' cannot be marked virtual // abstract virtual int this[int x] { get { throw null; } } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I1.this[int]").WithLocation(8, 26), // (8,40): error CS0500: 'I1.this[int].get' cannot declare a body because it is marked abstract // abstract virtual int this[int x] { get { throw null; } } Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.this[int].get").WithLocation(8, 40), // (12,26): error CS0503: The abstract property 'I2.this[int]' cannot be marked virtual // virtual abstract int this[int x] Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I2.this[int]").WithLocation(12, 26), // (14,9): error CS0500: 'I2.this[int].get' cannot declare a body because it is marked abstract // get { throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I2.this[int].get").WithLocation(14, 9), // (15,9): error CS0500: 'I2.this[int].set' cannot declare a body because it is marked abstract // set { throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I2.this[int].set").WithLocation(15, 9), // (20,26): error CS0503: The abstract property 'I3.this[int]' cannot be marked virtual // abstract virtual int this[int x] { set { throw null; } } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I3.this[int]").WithLocation(20, 26), // (20,40): error CS0500: 'I3.this[int].set' cannot declare a body because it is marked abstract // abstract virtual int this[int x] { set { throw null; } } Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I3.this[int].set").WithLocation(20, 40), // (24,26): error CS0503: The abstract property 'I4.this[int]' cannot be marked virtual // abstract virtual int this[int x] { get => throw null; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I4.this[int]").WithLocation(24, 26), // (24,40): error CS0500: 'I4.this[int].get' cannot declare a body because it is marked abstract // abstract virtual int this[int x] { get => throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.this[int].get").WithLocation(24, 40), // (28,26): error CS0503: The abstract property 'I5.this[int]' cannot be marked virtual // abstract virtual int this[int x] Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I5.this[int]").WithLocation(28, 26), // (30,9): error CS0500: 'I5.this[int].get' cannot declare a body because it is marked abstract // get => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I5.this[int].get").WithLocation(30, 9), // (31,9): error CS0500: 'I5.this[int].set' cannot declare a body because it is marked abstract // set => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I5.this[int].set").WithLocation(31, 9), // (36,26): error CS0503: The abstract property 'I6.this[int]' cannot be marked virtual // abstract virtual int this[int x] { set => throw null; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I6.this[int]").WithLocation(36, 26), // (36,40): error CS0500: 'I6.this[int].set' cannot declare a body because it is marked abstract // abstract virtual int this[int x] { set => throw null; } Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I6.this[int].set").WithLocation(36, 40), // (40,26): error CS0503: The abstract property 'I7.this[int]' cannot be marked virtual // abstract virtual int this[int x] => throw null; Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I7.this[int]").WithLocation(40, 26), // (40,41): error CS0500: 'I7.this[int].get' cannot declare a body because it is marked abstract // abstract virtual int this[int x] => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "throw null").WithArguments("I7.this[int].get").WithLocation(40, 41), // (44,26): error CS0503: The abstract property 'I8.this[int]' cannot be marked virtual // abstract virtual int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "this").WithArguments("property", "I8.this[int]").WithLocation(44, 26), // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.this[int]").WithLocation(90, 15), // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.this[int]").WithLocation(90, 19), // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.this[int]").WithLocation(90, 23), // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.this[int]").WithLocation(90, 27), // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.this[int]").WithLocation(90, 31), // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.this[int]").WithLocation(90, 35), // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.this[int]").WithLocation(90, 39), // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.this[int]").WithLocation(90, 43), // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.this[int]' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.this[int]").WithLocation(90, 47) ); } [Fact] public void IndexerModifiers_16() { var source1 = @" public interface I1 { extern int this[int x] {get;} } public interface I2 { virtual extern int this[int x] {set;} } public interface I4 { private extern int this[int x] {get;} } public interface I5 { extern sealed int this[int x] {set;} } class Test1 : I1, I2, I4, I5 { } class Test2 : I1, I2, I4, I5 { int I1.this[int x] => 0; int I2.this[int x] { set {} } } "; ValidatePropertyModifiers_16(source1, new DiagnosticDescription[] { // (4,16): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern int this[int x] {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("extern", "7.3", "8.0").WithLocation(4, 16), // (8,24): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern int this[int x] {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("extern", "7.3", "8.0").WithLocation(8, 24), // (8,24): error CS8503: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern int this[int x] {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("virtual", "7.3", "8.0").WithLocation(8, 24), // (12,24): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern int this[int x] {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("private", "7.3", "8.0").WithLocation(12, 24), // (12,24): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern int this[int x] {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("extern", "7.3", "8.0").WithLocation(12, 24), // (16,23): error CS8503: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed int this[int x] {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("sealed", "7.3", "8.0").WithLocation(16, 23), // (16,23): error CS8503: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed int this[int x] {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "this").WithArguments("extern", "7.3", "8.0").WithLocation(16, 23), // (8,37): warning CS0626: Method, operator, or accessor 'I2.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern int this[int x] {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I2.this[int].set").WithLocation(8, 37), // (12,37): warning CS0626: Method, operator, or accessor 'I4.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern int this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I4.this[int].get").WithLocation(12, 37), // (16,36): warning CS0626: Method, operator, or accessor 'I5.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed int this[int x] {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I5.this[int].set").WithLocation(16, 36), // (4,29): warning CS0626: Method, operator, or accessor 'I1.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.this[int].get").WithLocation(4, 29) }, // (4,29): error CS8501: Target runtime doesn't support default interface implementation. // extern int this[int x] {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(4, 29), // (8,37): error CS8501: Target runtime doesn't support default interface implementation. // virtual extern int this[int x] {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(8, 37), // (12,37): error CS8501: Target runtime doesn't support default interface implementation. // private extern int this[int x] {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(12, 37), // (16,36): error CS8501: Target runtime doesn't support default interface implementation. // extern sealed int this[int x] {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(16, 36), // (8,37): warning CS0626: Method, operator, or accessor 'I2.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern int this[int x] {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I2.this[int].set").WithLocation(8, 37), // (12,37): warning CS0626: Method, operator, or accessor 'I4.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern int this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I4.this[int].get").WithLocation(12, 37), // (16,36): warning CS0626: Method, operator, or accessor 'I5.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed int this[int x] {set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I5.this[int].set").WithLocation(16, 36), // (4,29): warning CS0626: Method, operator, or accessor 'I1.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.this[int].get").WithLocation(4, 29) ); } [Fact] public void IndexerModifiers_17() { var source1 = @" public interface I1 { abstract extern int this[int x] {get;} } public interface I2 { extern int this[int x] => 0; } public interface I3 { static extern int this[int x] {get => 0; set => throw null;} } public interface I4 { private extern int this[int x] { get {throw null;} set {throw null;}} } public interface I5 { extern sealed int this[int x] {get;} = 0; } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { int I1.this[int x] => 0; int I2.this[int x] => 0; int I3.this[int x] { get => 0; set => throw null;} int I4.this[int x] { get => 0; set => throw null;} int I5.this[int x] => 0; } "; ValidatePropertyModifiers_17(source1, // (20,42): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // extern sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(20, 42), // (4,25): error CS0180: 'I1.this[int]' cannot be both extern and abstract // abstract extern int this[int x] {get;} Diagnostic(ErrorCode.ERR_AbstractAndExtern, "this").WithArguments("I1.this[int]").WithLocation(4, 25), // (8,31): error CS0179: 'I2.this[int].get' cannot be extern and declare a body // extern int this[int x] => 0; Diagnostic(ErrorCode.ERR_ExternHasBody, "0").WithArguments("I2.this[int].get").WithLocation(8, 31), // (12,23): error CS0106: The modifier 'static' is not valid for this item // static extern int this[int x] {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(12, 23), // (12,36): error CS0179: 'I3.this[int].get' cannot be extern and declare a body // static extern int this[int x] {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I3.this[int].get").WithLocation(12, 36), // (12,46): error CS0179: 'I3.this[int].set' cannot be extern and declare a body // static extern int this[int x] {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I3.this[int].set").WithLocation(12, 46), // (16,38): error CS0179: 'I4.this[int].get' cannot be extern and declare a body // private extern int this[int x] { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_ExternHasBody, "get").WithArguments("I4.this[int].get").WithLocation(16, 38), // (16,56): error CS0179: 'I4.this[int].set' cannot be extern and declare a body // private extern int this[int x] { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I4.this[int].set").WithLocation(16, 56), // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]"), // (32,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented // int I4.this[int x] { get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(32, 12), // (33,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented // int I5.this[int x] => 0; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(33, 12), // (20,36): warning CS0626: Method, operator, or accessor 'I5.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I5.this[int].get").WithLocation(20, 36) ); } [Fact] public void IndexerModifiers_18() { var source1 = @" public interface I1 { abstract int this[int x] {get => 0; set => throw null;} } public interface I2 { abstract private int this[int x] => 0; } public interface I3 { static extern int this[int x] {get; set;} } public interface I4 { abstract static int this[int x] { get {throw null;} set {throw null;}} } public interface I5 { override sealed int this[int x] {get;} = 0; } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { int I1.this[int x] { get => 0; set => throw null;} int I2.this[int x] => 0; int I3.this[int x] { get => 0; set => throw null;} int I4.this[int x] { get => 0; set => throw null;} int I5.this[int x] => 0; } "; ValidatePropertyModifiers_18(source1, // (20,44): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // override sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(20, 44), // (4,31): error CS0500: 'I1.this[int].get' cannot declare a body because it is marked abstract // abstract int this[int x] {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.this[int].get").WithLocation(4, 31), // (4,41): error CS0500: 'I1.this[int].set' cannot declare a body because it is marked abstract // abstract int this[int x] {get => 0; set => throw null;} Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.this[int].set").WithLocation(4, 41), // (8,26): error CS0621: 'I2.this[int]': virtual or abstract members cannot be private // abstract private int this[int x] => 0; Diagnostic(ErrorCode.ERR_VirtualPrivate, "this").WithArguments("I2.this[int]").WithLocation(8, 26), // (8,41): error CS0500: 'I2.this[int].get' cannot declare a body because it is marked abstract // abstract private int this[int x] => 0; Diagnostic(ErrorCode.ERR_AbstractHasBody, "0").WithArguments("I2.this[int].get").WithLocation(8, 41), // (12,23): error CS0106: The modifier 'static' is not valid for this item // static extern int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(12, 23), // (16,25): error CS0106: The modifier 'static' is not valid for this item // abstract static int this[int x] { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(16, 25), // (16,39): error CS0500: 'I4.this[int].get' cannot declare a body because it is marked abstract // abstract static int this[int x] { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I4.this[int].get").WithLocation(16, 39), // (16,57): error CS0500: 'I4.this[int].set' cannot declare a body because it is marked abstract // abstract static int this[int x] { get {throw null;} set {throw null;}} Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I4.this[int].set").WithLocation(16, 57), // (20,25): error CS0106: The modifier 'override' is not valid for this item // override sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(20, 25), // (20,38): error CS0501: 'I5.this[int].get' must declare a body because it is not marked abstract, extern, or partial // override sealed int this[int x] {get;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I5.this[int].get").WithLocation(20, 38), // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.this[int]"), // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.this[int]' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.this[int]"), // (23,27): error CS0535: 'Test1' does not implement interface member 'I4.this[int]' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test1", "I4.this[int]").WithLocation(23, 27), // (30,12): error CS0122: 'I2.this[int]' is inaccessible due to its protection level // int I2.this[int x] => 0; Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I2.this[int]").WithLocation(30, 12), // (33,12): error CS0539: 'Test2.this[int]' in explicit interface declaration is not found among members of the interface that can be implemented // int I5.this[int x] => 0; Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Test2.this[int]").WithLocation(33, 12), // (12,36): warning CS0626: Method, operator, or accessor 'I3.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int this[int x] {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I3.this[int].get").WithLocation(12, 36), // (12,41): warning CS0626: Method, operator, or accessor 'I3.this[int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int this[int x] {get; set;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("I3.this[int].set").WithLocation(12, 41) ); } [Fact] public void IndexerModifiers_20() { var source1 = @" public interface I1 { internal int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } void M2() {this[0] = this[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_20(source1, source2, Accessibility.Internal); } [Fact] public void IndexerModifiers_21() { var source1 = @" public interface I1 { private int this[int x] { get => throw null; set => throw null; } } public interface I2 { internal int this[int x] { get => throw null; set => throw null; } } public interface I3 { public int this[int x] { get => throw null; set => throw null; } } public interface I4 { int this[int x] { get => throw null; set => throw null; } } class Test1 { static void Test(I1 i1, I2 i2, I3 i3, I4 i4) { int x; x = i1[0]; i1[0] = x; x = i2[0]; i2[0] = x; x = i3[0]; i3[0] = x; x = i4[0]; i4[0] = x; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (24,13): error CS0122: 'I1.this[int]' is inaccessible due to its protection level // x = i1[0]; Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(24, 13), // (25,9): error CS0122: 'I1.this[int]' is inaccessible due to its protection level // i1[0] = x; Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(25, 9) ); var source2 = @" class Test2 { static void Test(I1 i1, I2 i2, I3 i3, I4 i4) { int x; x = i1[0]; i1[0] = x; x = i2[0]; i2[0] = x; x = i3[0]; i3[0] = x; x = i4[0]; i4[0] = x; } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (7,13): error CS0122: 'I1.this[int]' is inaccessible due to its protection level // x = i1[0]; Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(7, 13), // (8,9): error CS0122: 'I1.this[int]' is inaccessible due to its protection level // i1[0] = x; Diagnostic(ErrorCode.ERR_BadAccess, "i1[0]").WithArguments("I1.this[int]").WithLocation(8, 9), // (9,13): error CS0122: 'I2.this[int]' is inaccessible due to its protection level // x = i2[0]; Diagnostic(ErrorCode.ERR_BadAccess, "i2[0]").WithArguments("I2.this[int]").WithLocation(9, 13), // (10,9): error CS0122: 'I2.this[int]' is inaccessible due to its protection level // i2[0] = x; Diagnostic(ErrorCode.ERR_BadAccess, "i2[0]").WithArguments("I2.this[int]").WithLocation(10, 9) ); } [Fact] public void IndexerModifiers_22() { var source1 = @" public interface I1 { public int this[int x] { internal get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int this[int x] { get { System.Console.WriteLine(""get_P2""); return 0; } internal set { System.Console.WriteLine(""set_P2""); } } } public interface I3 { int this[int x] { internal get => Test1.GetP3(); set => System.Console.WriteLine(""set_P3""); } } public interface I4 { int this[int x] { get => Test1.GetP4(); internal set => System.Console.WriteLine(""set_P4""); } } class Test1 : I1, I2, I3, I4 { static void Main() { I1 i1 = new Test1(); I2 i2 = new Test1(); I3 i3 = new Test1(); I4 i4 = new Test1(); i1[0] = i1[0]; i2[0] = i2[0]; i3[0] = i3[0]; i4[0] = i4[0]; } public static int GetP3() { System.Console.WriteLine(""get_P3""); return 0; } public static int GetP4() { System.Console.WriteLine(""get_P4""); return 0; } } "; ValidatePropertyModifiers_22(source1, Accessibility.Internal); } [Fact] public void IndexerModifiers_23_00() { var source1 = @" public interface I1 { } public interface I3 { int this[int x] { private get { System.Console.WriteLine(""get_P3""); return 0; } set {System.Console.WriteLine(""set_P3"");} } void M2() { this[0] = this[1]; } } public interface I4 { int this[int x] { get {System.Console.WriteLine(""get_P4""); return 0;} private set {System.Console.WriteLine(""set_P4"");} } void M2() { this[0] = this[1]; } } public interface I5 { int this[int x] { private get => GetP5(); set => System.Console.WriteLine(""set_P5""); } private int GetP5() { System.Console.WriteLine(""get_P5""); return 0; } void M2() { this[0] = this[1]; } } public interface I6 { int this[int x] { get => GetP6(); private set => System.Console.WriteLine(""set_P6""); } private int GetP6() { System.Console.WriteLine(""get_P6""); return 0; } void M2() { this[0] = this[1]; } } "; var source2 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public int this[int x] { get { throw null; } set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public int this[int x] { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } set { throw null; } } } class Test5 : I5 { public int this[int x] { get { throw null; } set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public int this[int x] { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } set { throw null; } } } "; ValidatePropertyModifiers_23(source1, source2); var source3 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public int this[int x] { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public int this[int x] { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test5 : I5 { public int this[int x] { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public int this[int x] { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } "; ValidatePropertyModifiers_23(source1, source3); var source4 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public virtual int this[int x] { get { throw null; } set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public virtual int this[int x] { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } set { throw null; } } } class Test5 : I5 { public virtual int this[int x] { get { throw null; } set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public virtual int this[int x] { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } set { throw null; } } } "; ValidatePropertyModifiers_23(source1, source4); var source5 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { public virtual int this[int x] { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { public virtual int this[int x] { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test5 : I5 { public virtual int this[int x] { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { public virtual int this[int x] { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } "; ValidatePropertyModifiers_23(source1, source5); var source6 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test3(); I4 i4 = new Test4(); I5 i5 = new Test5(); I6 i6 = new Test6(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } class Test3 : I3 { int I3.this[int x] { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test4 : I4 { int I4.this[int x] { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test5 : I5 { int I5.this[int x] { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test6 : I6 { int I6.this[int x] { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } "; ValidatePropertyModifiers_23(source1, source6); var source7 = @" class Test1 : I1 { static void Main() { I3 i3 = new Test33(); I4 i4 = new Test44(); I5 i5 = new Test55(); I6 i6 = new Test66(); i3.M2(); i4.M2(); i5.M2(); i6.M2(); } } interface Test3 : I3 { int I3.this[int x] { set { System.Console.WriteLine(""Test3.set_P3""); } } } class Test33 : Test3 {} interface Test4 : I4 { int I4.this[int x] { get { System.Console.WriteLine(""Test4.get_P4""); return 0; } } } class Test44 : Test4 {} interface Test5 : I5 { int I5.this[int x] { set { System.Console.WriteLine(""Test5.set_P5""); } } } class Test55 : Test5 {} interface Test6 : I6 { int I6.this[int x] { get { System.Console.WriteLine(""Test6.get_P6""); return 0; } } } class Test66 : Test6 {} "; ValidatePropertyModifiers_23(source1, source7); } [Fact] public void IndexerModifiers_23_01() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} void M2() { this[0] = this[1]; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.Internal, Accessibility.Public, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(12, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(12, 9) ) ); } [Fact] public void IndexerModifiers_23_02() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9) ) ); } [Fact] public void IndexerModifiers_23_03() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } int I1.this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,12): error CS0122: 'I1.this[int].get' is inaccessible due to its protection level // int I1.this[int x] Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int].get").WithLocation(9, 12) ); } [Fact] public void IndexerModifiers_23_04() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9) ) ); } [Fact] public void IndexerModifiers_23_05() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9) ) ); } [Fact] public void IndexerModifiers_23_06() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract int this[int x] {get; set;} } class Test3 : Test1 { public override int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,38): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(9, 38) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,38): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(9, 38) ) ); } [Fact] public void IndexerModifiers_23_07() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int this[int x] {get; set;} } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].get'. 'Test1.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test1", "I1.this[int].get", "Test1.this[int].get").WithLocation(11, 9) ) ); } [Fact] public void IndexerModifiers_23_08() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long this[int x] { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_08(source1, source2); } [Fact] public void IndexerModifiers_23_09() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long this[int x] { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.this[int]'. 'Test1.this[int]' cannot implement 'I1.this[int]' because it does not have the matching return type of 'int'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.this[int]", "Test1.this[int]", "int").WithLocation(2, 15) ); } [Fact] public void IndexerModifiers_23_10() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} sealed void Test() { this[0] = this[0]; } } "; var source2 = @" public class Test2 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (6,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get", "9.0", "10.0").WithLocation(6, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (6,9): error CS9044: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement an inaccessible member. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "get").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get").WithLocation(6, 9) ) ); } [Fact] public void IndexerModifiers_23_11() { var source1 = @" public interface I1 { abstract int this[int x] {internal get; set;} sealed void Test() { this[0] = this[0]; } } public class Test2 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_11(source1, source2, // (15,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].get'. 'Test2.this[int].get' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // get Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "get").WithArguments("Test2", "I1.this[int].get", "Test2.this[int].get", "9.0", "10.0").WithLocation(15, 9) ); } [Fact] public void IndexerModifiers_23_51() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} void M2() { this[0] = this[0]; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_23(source1, source2, Accessibility.Public, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (17,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(17, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (17,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(17, 9) ) ); } [Fact] public void IndexerModifiers_23_52() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_23_53() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } int I1.this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,12): error CS0122: 'I1.this[int].set' is inaccessible due to its protection level // int I1.this[int x] Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I1.this[int].set").WithLocation(9, 12) ); } [Fact] public void IndexerModifiers_23_54() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_23_55() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_23_56() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract int this[int x] {get; set;} } class Test3 : Test1 { public override int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,43): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(9, 43) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,43): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // public abstract int this[int x] {get; set;} Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(9, 43) ) ); } [Fact] public void IndexerModifiers_23_57() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } public interface I2 { int this[int x] {get; set;} } "; ValidatePropertyModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set", "9.0", "10.0").WithLocation(16, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.this[int].set'. 'Test1.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test1", "I1.this[int].set", "Test1.this[int].set").WithLocation(16, 9) ) ); } [Fact] public void IndexerModifiers_23_58() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } public class Test2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""Test2.get_P1""); return 0; } set { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long this[int x] { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_08(source1, source2); } [Fact] public void IndexerModifiers_23_59() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} } public class TestHelper { public static void CallP1(I1 x) {x[0] = x[0];} } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual long this[int x] { get { System.Console.WriteLine(""Test1.get_P1""); return 0; } set { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidatePropertyModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.this[int]'. 'Test1.this[int]' cannot implement 'I1.this[int]' because it does not have the matching return type of 'int'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.this[int]", "Test1.this[int]", "int").WithLocation(2, 15) ); } [Fact] public void IndexerModifiers_23_60() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} sealed void Test() { this[0] = this[0]; } } "; var source2 = @" public class Test2 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set", "9.0", "10.0").WithLocation(11, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement an inaccessible member. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "set").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set").WithLocation(11, 9) ) ); } [Fact] public void IndexerModifiers_23_61() { var source1 = @" public interface I1 { abstract int this[int x] {get; internal set;} sealed void Test() { this[0] = this[0]; } } public class Test2 : I1 { public int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } set { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidatePropertyModifiers_11_11(source1, source2, // (20,9): error CS8704: 'Test2' does not implement interface member 'I1.this[int].set'. 'Test2.this[int].set' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // set Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "set").WithArguments("Test2", "I1.this[int].set", "Test2.this[int].set", "9.0", "10.0").WithLocation(20, 9) ); } [Fact] public void IndexerModifiers_24() { var source1 = @" public interface I1 { int this[int x] { get { System.Console.WriteLine(""get_P1""); return 0; } internal set { System.Console.WriteLine(""set_P1""); } } void M2() {this[0] = this[1];} } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidatePropertyModifiers_24(source1, source2); } [Fact] public void IndexerModifiers_25() { var source1 = @" public interface I1 { int this[int x] { private get => throw null; set => throw null; } } public interface I2 { int this[int x] { internal get => throw null; set => throw null; } } public interface I3 { public int this[int x] { get => throw null; private set => throw null; } } public interface I4 { int this[int x] { get => throw null; internal set => throw null; } } public class Test1 : I1, I2, I3, I4 { static void Main() { int x; I1 i1 = new Test1(); I2 i2 = new Test1(); I3 i3 = new Test1(); I4 i4 = new Test1(); x = i1[0]; i1[0] = x; x = i2[0]; i2[0] = x; x = i3[0]; i3[0] = x; x = i4[0]; i4[0] = x; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (29,13): error CS0271: The property or indexer 'I1.this[int]' cannot be used in this context because the get accessor is inaccessible // x = i1[0]; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i1[0]").WithArguments("I1.this[int]").WithLocation(29, 13), // (34,9): error CS0272: The property or indexer 'I3.this[int]' cannot be used in this context because the set accessor is inaccessible // i3[0] = x; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i3[0]").WithArguments("I3.this[int]").WithLocation(34, 9) ); var source2 = @" class Test2 { static void Main() { int x; I1 i1 = new Test1(); I2 i2 = new Test1(); I3 i3 = new Test1(); I4 i4 = new Test1(); x = i1[0]; i1[0] = x; x = i2[0]; i2[0] = x; x = i3[0]; i3[0] = x; x = i4[0]; i4[0] = x; } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (12,13): error CS0271: The property or indexer 'I1.this[int]' cannot be used in this context because the get accessor is inaccessible // x = i1[0]; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i1[0]").WithArguments("I1.this[int]").WithLocation(12, 13), // (14,13): error CS0271: The property or indexer 'I2.this[int]' cannot be used in this context because the get accessor is inaccessible // x = i2[0]; Diagnostic(ErrorCode.ERR_InaccessibleGetter, "i2[0]").WithArguments("I2.this[int]").WithLocation(14, 13), // (17,9): error CS0272: The property or indexer 'I3.this[int]' cannot be used in this context because the set accessor is inaccessible // i3[0] = x; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i3[0]").WithArguments("I3.this[int]").WithLocation(17, 9), // (19,9): error CS0272: The property or indexer 'I4.this[int]' cannot be used in this context because the set accessor is inaccessible // i4[0] = x; Diagnostic(ErrorCode.ERR_InaccessibleSetter, "i4[0]").WithArguments("I4.this[int]").WithLocation(19, 9) ); } [Fact] public void IndexerModifiers_26() { var source1 = @" public interface I1 { abstract int this[sbyte x] { private get; set; } abstract int this[byte x] { get; private set; } abstract int this[short x] { internal get; } int this[ushort x] {internal get;} = 0; int this[int x] { internal get {throw null;} } int this[uint x] { internal set {throw null;} } int this[long x] { internal get => throw null; } int this[ulong x] { internal set => throw null; } int this[float x] { internal get {throw null;} private set {throw null;}} int this[double x] { internal get => throw null; private set => throw null;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (7,40): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // int this[ushort x] {internal get;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(7, 40), // (4,42): error CS0442: 'I1.this[sbyte].get': abstract properties cannot have private accessors // abstract int this[sbyte x] { private get; set; } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "get").WithArguments("I1.this[sbyte].get").WithLocation(4, 42), // (5,46): error CS0442: 'I1.this[byte].set': abstract properties cannot have private accessors // abstract int this[byte x] { get; private set; } Diagnostic(ErrorCode.ERR_PrivateAbstractAccessor, "set").WithArguments("I1.this[byte].set").WithLocation(5, 46), // (6,18): error CS0276: 'I1.this[short]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // abstract int this[short x] { internal get; } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[short]").WithLocation(6, 18), // (7,9): error CS0276: 'I1.this[ushort]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int this[ushort x] {internal get;} = 0; Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[ushort]").WithLocation(7, 9), // (8,9): error CS0276: 'I1.this[int]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int this[int x] { internal get {throw null;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[int]").WithLocation(8, 9), // (9,9): error CS0276: 'I1.this[uint]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int this[uint x] { internal set {throw null;} } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[uint]").WithLocation(9, 9), // (10,9): error CS0276: 'I1.this[long]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int this[long x] { internal get => throw null; } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[long]").WithLocation(10, 9), // (11,9): error CS0276: 'I1.this[ulong]': accessibility modifiers on accessors may only be used if the property or indexer has both a get and a set accessor // int this[ulong x] { internal set => throw null; } Diagnostic(ErrorCode.ERR_AccessModMissingAccessor, "this").WithArguments("I1.this[ulong]").WithLocation(11, 9), // (12,9): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.this[float]' // int this[float x] { internal get {throw null;} private set {throw null;}} Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "this").WithArguments("I1.this[float]").WithLocation(12, 9), // (13,9): error CS0274: Cannot specify accessibility modifiers for both accessors of the property or indexer 'I1.this[double]' // int this[double x] { internal get => throw null; private set => throw null;} Diagnostic(ErrorCode.ERR_DuplicatePropertyAccessMods, "this").WithArguments("I1.this[double]").WithLocation(13, 9) ); } [Fact] public void IndexerModifiers_27() { var source1 = @" public interface I1 { int this[short x] { private get {throw null;} set {} } int this[int x] { get {throw null;} private set {} } } class Test1 : I1 { int I1.this[short x] { get {throw null;} set {} } int I1.this[int x] { get {throw null;} set {} } } interface ITest1 : I1 { int I1.this[short x] { get {throw null;} set {} } int I1.this[int x] { get {throw null;} set {} } } public interface I2 { int this[short x] { private get {throw null;} set {} } int this[int x] { get {throw null;} private set {} } class Test3 : I2 { int I2.this[short x] { get {throw null;} set {} } int I2.this[int x] { get {throw null;} set {} } } interface ITest3 : I2 { int I2.this[short x] { get {throw null;} set {} } int I2.this[int x] { get {throw null;} set {} } } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (21,9): error CS0550: 'Test1.I1.this[short].get' adds an accessor not found in interface member 'I1.this[short]' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("Test1.I1.this[short].get", "I1.this[short]").WithLocation(21, 9), // (28,9): error CS0550: 'Test1.I1.this[int].set' adds an accessor not found in interface member 'I1.this[int]' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("Test1.I1.this[int].set", "I1.this[int]").WithLocation(28, 9), // (36,9): error CS0550: 'ITest1.I1.this[short].get' adds an accessor not found in interface member 'I1.this[short]' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("ITest1.I1.this[short].get", "I1.this[short]").WithLocation(36, 9), // (43,9): error CS0550: 'ITest1.I1.this[int].set' adds an accessor not found in interface member 'I1.this[int]' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("ITest1.I1.this[int].set", "I1.this[int]").WithLocation(43, 9), // (65,13): error CS0550: 'I2.Test3.I2.this[short].get' adds an accessor not found in interface member 'I2.this[short]' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I2.Test3.I2.this[short].get", "I2.this[short]").WithLocation(65, 13), // (72,13): error CS0550: 'I2.Test3.I2.this[int].set' adds an accessor not found in interface member 'I2.this[int]' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I2.Test3.I2.this[int].set", "I2.this[int]").WithLocation(72, 13), // (80,13): error CS0550: 'I2.ITest3.I2.this[short].get' adds an accessor not found in interface member 'I2.this[short]' // get {throw null;} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I2.ITest3.I2.this[short].get", "I2.this[short]").WithLocation(80, 13), // (87,13): error CS0550: 'I2.ITest3.I2.this[int].set' adds an accessor not found in interface member 'I2.this[int]' // set {} Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I2.ITest3.I2.this[int].set", "I2.this[int]").WithLocation(87, 13) ); } [Fact] public void EventModifiers_01() { var source1 = @" public interface I1 { public event System.Action P01; protected event System.Action P02 {add{}} protected internal event System.Action P03 {remove{}} internal event System.Action P04 {add{}} private event System.Action P05 {remove{}} static event System.Action P06 {add{}} virtual event System.Action P07 {remove{}} sealed event System.Action P08 {add{}} override event System.Action P09 {remove{}} abstract event System.Action P10 {add{}} extern event System.Action P11 {add{} remove{}} extern event System.Action P12 {add; remove;} extern event System.Action P13; private protected event System.Action P14; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( // (12,34): error CS0106: The modifier 'override' is not valid for this item // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), // (13,38): error CS8712: 'I1.P10': abstract event cannot use event accessor syntax // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.P10").WithLocation(13, 38), // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), // (15,40): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), // (15,48): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P13; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32) ); ValidateSymbolsEventModifiers_01(compilation1); } private static void ValidateSymbolsEventModifiers_01(CSharpCompilation compilation1) { var i1 = compilation1.GetTypeByMetadataName("I1"); var p01 = i1.GetMember<EventSymbol>("P01"); Assert.True(p01.IsAbstract); Assert.False(p01.IsVirtual); Assert.False(p01.IsSealed); Assert.False(p01.IsStatic); Assert.False(p01.IsExtern); Assert.False(p01.IsOverride); Assert.Equal(Accessibility.Public, p01.DeclaredAccessibility); ValidateP01Accessor(p01.AddMethod); ValidateP01Accessor(p01.RemoveMethod); void ValidateP01Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } var p02 = i1.GetMember<EventSymbol>("P02"); var p02get = p02.AddMethod; Assert.False(p02.IsAbstract); Assert.True(p02.IsVirtual); Assert.False(p02.IsSealed); Assert.False(p02.IsStatic); Assert.False(p02.IsExtern); Assert.False(p02.IsOverride); Assert.Equal(Accessibility.Protected, p02.DeclaredAccessibility); Assert.False(p02get.IsAbstract); Assert.True(p02get.IsVirtual); Assert.True(p02get.IsMetadataVirtual()); Assert.False(p02get.IsSealed); Assert.False(p02get.IsStatic); Assert.False(p02get.IsExtern); Assert.False(p02get.IsAsync); Assert.False(p02get.IsOverride); Assert.Equal(Accessibility.Protected, p02get.DeclaredAccessibility); var p03 = i1.GetMember<EventSymbol>("P03"); var p03set = p03.RemoveMethod; Assert.False(p03.IsAbstract); Assert.True(p03.IsVirtual); Assert.False(p03.IsSealed); Assert.False(p03.IsStatic); Assert.False(p03.IsExtern); Assert.False(p03.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, p03.DeclaredAccessibility); Assert.False(p03set.IsAbstract); Assert.True(p03set.IsVirtual); Assert.True(p03set.IsMetadataVirtual()); Assert.False(p03set.IsSealed); Assert.False(p03set.IsStatic); Assert.False(p03set.IsExtern); Assert.False(p03set.IsAsync); Assert.False(p03set.IsOverride); Assert.Equal(Accessibility.ProtectedOrInternal, p03set.DeclaredAccessibility); var p04 = i1.GetMember<EventSymbol>("P04"); var p04get = p04.AddMethod; Assert.False(p04.IsAbstract); Assert.True(p04.IsVirtual); Assert.False(p04.IsSealed); Assert.False(p04.IsStatic); Assert.False(p04.IsExtern); Assert.False(p04.IsOverride); Assert.Equal(Accessibility.Internal, p04.DeclaredAccessibility); Assert.False(p04get.IsAbstract); Assert.True(p04get.IsVirtual); Assert.True(p04get.IsMetadataVirtual()); Assert.False(p04get.IsSealed); Assert.False(p04get.IsStatic); Assert.False(p04get.IsExtern); Assert.False(p04get.IsAsync); Assert.False(p04get.IsOverride); Assert.Equal(Accessibility.Internal, p04get.DeclaredAccessibility); var p05 = i1.GetMember<EventSymbol>("P05"); var p05set = p05.RemoveMethod; Assert.False(p05.IsAbstract); Assert.False(p05.IsVirtual); Assert.False(p05.IsSealed); Assert.False(p05.IsStatic); Assert.False(p05.IsExtern); Assert.False(p05.IsOverride); Assert.Equal(Accessibility.Private, p05.DeclaredAccessibility); Assert.False(p05set.IsAbstract); Assert.False(p05set.IsVirtual); Assert.False(p05set.IsMetadataVirtual()); Assert.False(p05set.IsSealed); Assert.False(p05set.IsStatic); Assert.False(p05set.IsExtern); Assert.False(p05set.IsAsync); Assert.False(p05set.IsOverride); Assert.Equal(Accessibility.Private, p05set.DeclaredAccessibility); var p06 = i1.GetMember<EventSymbol>("P06"); var p06get = p06.AddMethod; Assert.False(p06.IsAbstract); Assert.False(p06.IsVirtual); Assert.False(p06.IsSealed); Assert.True(p06.IsStatic); Assert.False(p06.IsExtern); Assert.False(p06.IsOverride); Assert.Equal(Accessibility.Public, p06.DeclaredAccessibility); Assert.False(p06get.IsAbstract); Assert.False(p06get.IsVirtual); Assert.False(p06get.IsMetadataVirtual()); Assert.False(p06get.IsSealed); Assert.True(p06get.IsStatic); Assert.False(p06get.IsExtern); Assert.False(p06get.IsAsync); Assert.False(p06get.IsOverride); Assert.Equal(Accessibility.Public, p06get.DeclaredAccessibility); var p07 = i1.GetMember<EventSymbol>("P07"); var p07set = p07.RemoveMethod; Assert.False(p07.IsAbstract); Assert.True(p07.IsVirtual); Assert.False(p07.IsSealed); Assert.False(p07.IsStatic); Assert.False(p07.IsExtern); Assert.False(p07.IsOverride); Assert.Equal(Accessibility.Public, p07.DeclaredAccessibility); Assert.False(p07set.IsAbstract); Assert.True(p07set.IsVirtual); Assert.True(p07set.IsMetadataVirtual()); Assert.False(p07set.IsSealed); Assert.False(p07set.IsStatic); Assert.False(p07set.IsExtern); Assert.False(p07set.IsAsync); Assert.False(p07set.IsOverride); Assert.Equal(Accessibility.Public, p07set.DeclaredAccessibility); var p08 = i1.GetMember<EventSymbol>("P08"); var p08get = p08.AddMethod; Assert.False(p08.IsAbstract); Assert.False(p08.IsVirtual); Assert.False(p08.IsSealed); Assert.False(p08.IsStatic); Assert.False(p08.IsExtern); Assert.False(p08.IsOverride); Assert.Equal(Accessibility.Public, p08.DeclaredAccessibility); Assert.False(p08get.IsAbstract); Assert.False(p08get.IsVirtual); Assert.False(p08get.IsMetadataVirtual()); Assert.False(p08get.IsSealed); Assert.False(p08get.IsStatic); Assert.False(p08get.IsExtern); Assert.False(p08get.IsAsync); Assert.False(p08get.IsOverride); Assert.Equal(Accessibility.Public, p08get.DeclaredAccessibility); var p09 = i1.GetMember<EventSymbol>("P09"); var p09set = p09.RemoveMethod; Assert.False(p09.IsAbstract); Assert.True(p09.IsVirtual); Assert.False(p09.IsSealed); Assert.False(p09.IsStatic); Assert.False(p09.IsExtern); Assert.False(p09.IsOverride); Assert.Equal(Accessibility.Public, p09.DeclaredAccessibility); Assert.False(p09set.IsAbstract); Assert.True(p09set.IsVirtual); Assert.True(p09set.IsMetadataVirtual()); Assert.False(p09set.IsSealed); Assert.False(p09set.IsStatic); Assert.False(p09set.IsExtern); Assert.False(p09set.IsAsync); Assert.False(p09set.IsOverride); Assert.Equal(Accessibility.Public, p09set.DeclaredAccessibility); var p10 = i1.GetMember<EventSymbol>("P10"); var p10get = p10.AddMethod; Assert.True(p10.IsAbstract); Assert.False(p10.IsVirtual); Assert.False(p10.IsSealed); Assert.False(p10.IsStatic); Assert.False(p10.IsExtern); Assert.False(p10.IsOverride); Assert.Equal(Accessibility.Public, p10.DeclaredAccessibility); Assert.True(p10get.IsAbstract); Assert.False(p10get.IsVirtual); Assert.True(p10get.IsMetadataVirtual()); Assert.False(p10get.IsSealed); Assert.False(p10get.IsStatic); Assert.False(p10get.IsExtern); Assert.False(p10get.IsAsync); Assert.False(p10get.IsOverride); Assert.Equal(Accessibility.Public, p10get.DeclaredAccessibility); foreach (var name in new[] { "P11", "P12", "P13" }) { var p11 = i1.GetMember<EventSymbol>(name); Assert.False(p11.IsAbstract); Assert.True(p11.IsVirtual); Assert.False(p11.IsSealed); Assert.False(p11.IsStatic); Assert.True(p11.IsExtern); Assert.False(p11.IsOverride); Assert.Equal(Accessibility.Public, p11.DeclaredAccessibility); ValidateP11Accessor(p11.AddMethod); ValidateP11Accessor(p11.RemoveMethod); void ValidateP11Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } } var p14 = i1.GetMember<EventSymbol>("P14"); Assert.True(p14.IsAbstract); Assert.False(p14.IsVirtual); Assert.False(p14.IsSealed); Assert.False(p14.IsStatic); Assert.False(p14.IsExtern); Assert.False(p14.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, p14.DeclaredAccessibility); ValidateP14Accessor(p14.AddMethod); ValidateP14Accessor(p14.RemoveMethod); void ValidateP14Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.ProtectedAndInternal, accessor.DeclaredAccessibility); } } [Fact] public void EventModifiers_02() { var source1 = @" public interface I1 { public event System.Action P01; protected event System.Action P02 {add{}} protected internal event System.Action P03 {remove{}} internal event System.Action P04 {add{}} private event System.Action P05 {remove{}} static event System.Action P06 {add{}} virtual event System.Action P07 {remove{}} sealed event System.Action P08 {add{}} override event System.Action P09 {remove{}} abstract event System.Action P10 {add{}} extern event System.Action P11 {add{} remove{}} extern event System.Action P12 {add; remove;} extern event System.Action P13; private protected event System.Action P14; protected event System.Action P15; protected internal event System.Action P16; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( // (4,32): error CS8703: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public event System.Action P01; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P01").WithArguments("public", "7.3", "8.0").WithLocation(4, 32), // (5,40): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // protected event System.Action P02 {add{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(5, 40), // (6,49): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // protected internal event System.Action P03 {remove{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(6, 49), // (7,39): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // internal event System.Action P04 {add{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(7, 39), // (8,38): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // private event System.Action P05 {remove{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(8, 38), // (9,32): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static event System.Action P06 {add{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "P06").WithArguments("default interface implementation", "8.0").WithLocation(9, 32), // (10,38): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // virtual event System.Action P07 {remove{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(10, 38), // (11,37): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // sealed event System.Action P08 {add{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(11, 37), // (12,34): error CS0106: The modifier 'override' is not valid for this item // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), // (12,39): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(12, 39), // (13,39): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(13, 39), // (13,38): error CS8712: 'I1.P10': abstract event cannot use event accessor syntax // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.P10").WithLocation(13, 38), // (14,37): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(14, 37), // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), // (14,43): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(14, 43), // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), // (15,37): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(15, 37), // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), // (15,40): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), // (15,42): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(15, 42), // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), // (15,48): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), // (16,32): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern event System.Action P13; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P13").WithArguments("extern", "7.3", "8.0").WithLocation(16, 32), // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P13; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32), // (17,43): error CS8703: The modifier 'private protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private protected event System.Action P14; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P14").WithArguments("private protected", "7.3", "8.0").WithLocation(17, 43), // (18,35): error CS8703: The modifier 'protected' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // protected event System.Action P15; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P15").WithArguments("protected", "7.3", "8.0").WithLocation(18, 35), // (19,44): error CS8703: The modifier 'protected internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // protected internal event System.Action P16; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P16").WithArguments("protected internal", "7.3", "8.0").WithLocation(19, 44) ); ValidateSymbolsEventModifiers_01(compilation1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify( // (5,35): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected event System.Action P02 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P02").WithLocation(5, 35), // (5,40): error CS8701: Target runtime doesn't support default interface implementation. // protected event System.Action P02 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(5, 40), // (6,44): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal event System.Action P03 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P03").WithLocation(6, 44), // (6,49): error CS8701: Target runtime doesn't support default interface implementation. // protected internal event System.Action P03 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(6, 49), // (7,39): error CS8701: Target runtime doesn't support default interface implementation. // internal event System.Action P04 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(7, 39), // (8,38): error CS8701: Target runtime doesn't support default interface implementation. // private event System.Action P05 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(8, 38), // (9,37): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static event System.Action P06 {add{}} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "add").WithArguments("static members in interfaces", "15.0").WithLocation(9, 37), // (10,38): error CS8701: Target runtime doesn't support default interface implementation. // virtual event System.Action P07 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(10, 38), // (11,37): error CS8701: Target runtime doesn't support default interface implementation. // sealed event System.Action P08 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(11, 37), // (12,34): error CS0106: The modifier 'override' is not valid for this item // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), // (12,39): error CS8701: Target runtime doesn't support default interface implementation. // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(12, 39), // (13,39): error CS8701: Target runtime doesn't support default interface implementation. // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(13, 39), // (13,38): error CS8712: 'I1.P10': abstract event cannot use event accessor syntax // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.P10").WithLocation(13, 38), // (14,37): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(14, 37), // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), // (14,43): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(14, 43), // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), // (15,37): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(15, 37), // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), // (15,40): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), // (15,42): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(15, 42), // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), // (15,48): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), // (16,32): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P13; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "P13").WithLocation(16, 32), // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P13; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32), // (17,43): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected event System.Action P14; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P14").WithLocation(17, 43), // (18,35): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected event System.Action P15; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P15").WithLocation(18, 35), // (19,44): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal event System.Action P16; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P16").WithLocation(19, 44) ); ValidateSymbolsEventModifiers_01(compilation2); var expected = new[] { // (5,35): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected event System.Action P02 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P02").WithLocation(5, 35), // (5,40): error CS8701: Target runtime doesn't support default interface implementation. // protected event System.Action P02 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(5, 40), // (6,44): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal event System.Action P03 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P03").WithLocation(6, 44), // (6,49): error CS8701: Target runtime doesn't support default interface implementation. // protected internal event System.Action P03 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(6, 49), // (7,39): error CS8701: Target runtime doesn't support default interface implementation. // internal event System.Action P04 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(7, 39), // (8,38): error CS8701: Target runtime doesn't support default interface implementation. // private event System.Action P05 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(8, 38), // (10,38): error CS8701: Target runtime doesn't support default interface implementation. // virtual event System.Action P07 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(10, 38), // (11,37): error CS8701: Target runtime doesn't support default interface implementation. // sealed event System.Action P08 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(11, 37), // (12,34): error CS0106: The modifier 'override' is not valid for this item // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P09").WithArguments("override").WithLocation(12, 34), // (12,39): error CS8701: Target runtime doesn't support default interface implementation. // override event System.Action P09 {remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(12, 39), // (13,39): error CS8701: Target runtime doesn't support default interface implementation. // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(13, 39), // (13,38): error CS8712: 'I1.P10': abstract event cannot use event accessor syntax // abstract event System.Action P10 {add{}} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.P10").WithLocation(13, 38), // (14,37): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(14, 37), // (14,37): error CS0179: 'I1.P11.add' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I1.P11.add").WithLocation(14, 37), // (14,43): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(14, 43), // (14,43): error CS0179: 'I1.P11.remove' cannot be extern and declare a body // extern event System.Action P11 {add{} remove{}} Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I1.P11.remove").WithLocation(14, 43), // (15,37): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(15, 37), // (15,37): warning CS0626: Method, operator, or accessor 'I1.P12.add' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "add").WithArguments("I1.P12.add").WithLocation(15, 37), // (15,40): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 40), // (15,42): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(15, 42), // (15,42): warning CS0626: Method, operator, or accessor 'I1.P12.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "remove").WithArguments("I1.P12.remove").WithLocation(15, 42), // (15,48): error CS0073: An add or remove accessor must have a body // extern event System.Action P12 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(15, 48), // (16,32): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P13; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "P13").WithLocation(16, 32), // (16,32): warning CS0626: Method, operator, or accessor 'I1.P13.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P13; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P13").WithArguments("I1.P13.remove").WithLocation(16, 32), // (17,43): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected event System.Action P14; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P14").WithLocation(17, 43), // (18,35): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected event System.Action P15; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P15").WithLocation(18, 35), // (19,44): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal event System.Action P16; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "P16").WithLocation(19, 44) }; compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify(expected); ValidateSymbolsEventModifiers_01(compilation2); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.ERR_EventNeedsBothAccessors).Verify(expected); ValidateSymbolsEventModifiers_01(compilation2); } [Fact] public void EventModifiers_03() { ValidateEventImplementation_102(@" public interface I1 { public virtual event System.Action E1 { add => System.Console.WriteLine(""add E1""); remove => System.Console.WriteLine(""remove E1""); } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1.E1 += null; i1.E1 -= null; } } "); ValidateEventImplementation_102(@" public interface I1 { public virtual event System.Action E1 { add {System.Console.WriteLine(""add E1"");} remove {System.Console.WriteLine(""remove E1"");} } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1.E1 += null; i1.E1 -= null; } } "); } [Fact] public void EventModifiers_04() { ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 {} } class Test1 : I1 {} ", new[] { // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 {} Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: false, haveRemove: false); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { add; } } class Test1 : I1 {} ", new[] { // (6,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";"), // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: true, haveRemove: false); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { add {} } } class Test1 : I1 {} ", new[] { // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: true, haveRemove: false); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { add => throw null; } } class Test1 : I1 {} ", new[] { // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: true, haveRemove: false); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { remove; } } class Test1 : I1 {} ", new[] { // (6,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(6, 15), // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: false, haveRemove: true); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { remove {} } } class Test1 : I1 {} ", new[] { // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: false, haveRemove: true); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { remove => throw null; } } class Test1 : I1 {} ", new[] { // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: false, haveRemove: true); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 { add; remove; } } class Test1 : I1 {} ", new[] { // (6,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";"), // (7,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(7, 15) }, haveAdd: true, haveRemove: true); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1; } class Test1 : I1 {} ", new[] { // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40), // (4,40): warning CS0067: The event 'I1.E1' is never used // public virtual event System.Action E1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: true, haveRemove: true); ValidateEventImplementation_101(@" public interface I1 { public virtual event System.Action E1 = null; } class Test1 : I1 {} ", new[] { // (4,40): error CS0068: 'I1.E1': instance event in interface cannot have initializer // public virtual event System.Action E1 = null; Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "E1").WithArguments("I1.E1").WithLocation(4, 40), // (4,40): error CS0065: 'I1.E1': event property must have both add and remove accessors // public virtual event System.Action E1 = null; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "E1").WithArguments("I1.E1").WithLocation(4, 40), // (4,40): warning CS0067: The event 'I1.E1' is never used // public virtual event System.Action E1 = null; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "E1").WithArguments("I1.E1").WithLocation(4, 40) }, haveAdd: true, haveRemove: true); } [Fact] public void EventModifiers_05() { var source1 = @" public interface I1 { public abstract event System.Action P1; } public interface I2 { event System.Action P2; } class Test1 : I1 { public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove => System.Console.WriteLine(""set_P1""); } } class Test2 : I2 { public event System.Action P2 { add { System.Console.WriteLine(""get_P2""); } remove => System.Console.WriteLine(""set_P2""); } static void Main() { I1 x = new Test1(); x.P1 += null; x.P1 -= null; I2 y = new Test2(); y.P2 += null; y.P2 -= null; } } "; ValidateEventModifiers_05(source1); } private void ValidateEventModifiers_05(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: @"get_P1 set_P1 get_P2 set_P2", symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { for (int i = 1; i <= 2; i++) { var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleEvent(i1); var test1P1 = GetSingleEvent(test1); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor(p1.AddMethod, test1P1.AddMethod); ValidateAccessor(p1.RemoveMethod, test1P1.RemoveMethod); void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(implementation, test1.FindImplementationForInterfaceMember(accessor)); } } } } private static EventSymbol GetSingleEvent(NamedTypeSymbol container) { return container.GetMembers().OfType<EventSymbol>().Single(); } private static EventSymbol GetSingleEvent(CSharpCompilation compilation, string containerName) { return GetSingleEvent(compilation.GetTypeByMetadataName(containerName)); } private static EventSymbol GetSingleEvent(ModuleSymbol m, string containerName) { return GetSingleEvent(m.GlobalNamespace.GetTypeMember(containerName)); } [Fact] public void EventModifiers_06() { var source1 = @" public interface I1 { public abstract event System.Action P1; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3); compilation1.VerifyDiagnostics( // (4,41): error CS8503: The modifier 'abstract' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract event System.Action P1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("abstract", "7.3", "8.0").WithLocation(4, 41), // (4,41): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public abstract event System.Action P1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("public", "7.3", "8.0").WithLocation(4, 41) ); ValidateEventModifiers_06(compilation1); } private static void ValidateEventModifiers_06(CSharpCompilation compilation1) { var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<EventSymbol>("P1"); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); ValidateAccessor(p1.AddMethod); ValidateAccessor(p1.RemoveMethod); void ValidateAccessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); } } [Fact] public void EventModifiers_07() { var source1 = @" public interface I1 { public static event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } internal static event System.Action P2 { add { System.Console.WriteLine(""get_P2""); P3 += value; } remove { System.Console.WriteLine(""set_P2""); P3 -= value; } } private static event System.Action P3 { add => System.Console.WriteLine(""get_P3""); remove => System.Console.WriteLine(""set_P3""); } } class Test1 : I1 { static void Main() { I1.P1 += null; I1.P1 -= null; I1.P2 += null; I1.P2 -= null; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var expected = @"get_P1 set_P1 get_P2 get_P3 set_P2 set_P3"; CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expected, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var tuple in new[] { (name: "P1", access: Accessibility.Public), (name: "P2", access: Accessibility.Internal), (name: "P3", access: Accessibility.Private)}) { var p1 = i1.GetMember<EventSymbol>(tuple.name); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(tuple.access, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor(p1.AddMethod); ValidateAccessor(p1.RemoveMethod); void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(tuple.access, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } var source2 = @" public interface I1 { public static event System.Action P1; internal static event System.Action P2 { add; remove; } private static event System.Action P3 = null; } class Test1 : I1 { static void Main() { } } "; var compilation2 = CreateCompilation(source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyEmitDiagnostics( // (4,39): warning CS0067: The event 'I1.P1' is never used // public static event System.Action P1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P1").WithArguments("I1.P1").WithLocation(4, 39), // (8,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 12), // (9,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(9, 15), // (12,40): warning CS0414: The field 'I1.P3' is assigned but its value is never used // private static event System.Action P3 = null; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "P3").WithArguments("I1.P3").WithLocation(12, 40) ); Validate(compilation2.SourceModule); var compilation3 = CreateCompilation(source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation3.VerifyEmitDiagnostics( // (4,39): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static event System.Action P1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "P1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 39), // (4,39): warning CS0067: The event 'I1.P1' is never used // public static event System.Action P1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P1").WithArguments("I1.P1").WithLocation(4, 39), // (8,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // add; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "add").WithArguments("static members in interfaces", "15.0").WithLocation(8, 9), // (8,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 12), // (9,9): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // remove; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "remove").WithArguments("static members in interfaces", "15.0").WithLocation(9, 9), // (9,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(9, 15), // (12,40): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static event System.Action P3 = null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "P3").WithArguments("static members in interfaces", "15.0").WithLocation(12, 40), // (12,40): warning CS0414: The field 'I1.P3' is assigned but its value is never used // private static event System.Action P3 = null; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "P3").WithArguments("I1.P3").WithLocation(12, 40) ); Validate(compilation3.SourceModule); var expected2 = new[] { // (4,39): warning CS0067: The event 'I1.P1' is never used // public static event System.Action P1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P1").WithArguments("I1.P1").WithLocation(4, 39), // (8,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 12), // (9,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(9, 15), // (12,40): warning CS0414: The field 'I1.P3' is assigned but its value is never used // private static event System.Action P3 = null; Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "P3").WithArguments("I1.P3").WithLocation(12, 40) }; compilation3 = CreateCompilation(source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation3.VerifyEmitDiagnostics(expected2); Validate(compilation3.SourceModule); compilation3 = CreateCompilation(source2, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); compilation3.VerifyEmitDiagnostics(expected2); Validate(compilation3.SourceModule); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation4, expectedOutput: expected, symbolValidator: Validate); Validate(compilation4.SourceModule); compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation4, expectedOutput: expected, symbolValidator: Validate); Validate(compilation4.SourceModule); } [Fact] public void EventModifiers_08() { var source1 = @" public interface I1 { abstract static event System.Action P1; virtual static event System.Action P2 {add {} remove{}} sealed static event System.Action P3 {add; remove;} } class Test1 : I1 { event System.Action I1.P1 {add {} remove{}} event System.Action I1.P2 {add {} remove{}} event System.Action I1.P3 {add {} remove{}} } class Test2 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,41): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // abstract static event System.Action P1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("abstract", "9.0", "11.0").WithLocation(4, 41), // (6,40): error CS8703: The modifier 'virtual' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // virtual static event System.Action P2 {add {} remove{}} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P2").WithArguments("virtual", "9.0", "11.0").WithLocation(6, 40), // (8,39): error CS8703: The modifier 'sealed' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // sealed static event System.Action P3 {add; remove;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("sealed", "9.0", "11.0").WithLocation(8, 39), // (8,46): error CS0073: An add or remove accessor must have a body // sealed static event System.Action P3 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 46), // (8,54): error CS0073: An add or remove accessor must have a body // sealed static event System.Action P3 {add; remove;} Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(8, 54), // (13,28): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I1.P1 {add {} remove{}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(13, 28), // (14,28): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I1.P2 {add {} remove{}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(14, 28), // (15,28): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I1.P3 {add {} remove{}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(15, 28), // (18,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(18, 15), // (11,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(11, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<EventSymbol>("P1"); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor1(p1.AddMethod); ValidateAccessor1(p1.RemoveMethod); void ValidateAccessor1(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } var p2 = i1.GetMember<EventSymbol>("P2"); Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.True(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); ValidateAccessor2(p2.AddMethod); ValidateAccessor2(p2.RemoveMethod); void ValidateAccessor2(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); } var p3 = i1.GetMember<EventSymbol>("P3"); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.False(p3.IsSealed); Assert.True(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); ValidateAccessor3(p3.AddMethod); ValidateAccessor3(p3.RemoveMethod); void ValidateAccessor3(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } [Fact] public void EventModifiers_09() { var source1 = @" public interface I1 { private event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } sealed void M() { P1 += null; P1 -= null; } } public interface I2 { private event System.Action P2 { add => System.Console.WriteLine(""get_P2""); remove => System.Console.WriteLine(""set_P2""); } sealed void M() { P2 += null; P2 -= null; } } class Test1 : I1, I2 { static void Main() { I1 x1 = new Test1(); x1.M(); I2 x2 = new Test1(); x2.M(); } } "; ValidateEventModifiers_09(source1); } private void ValidateEventModifiers_09(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); for (int i = 1; i <= 2; i++) { var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleEvent(i1); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor(p1.AddMethod); ValidateAccessor(p1.RemoveMethod); void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } } [Fact] public void EventModifiers_10() { var source1 = @" public interface I1 { abstract private event System.Action P1; virtual private event System.Action P2; sealed private event System.Action P3 { add => throw null; remove {} } private event System.Action P4 = null; } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,42): error CS0621: 'I1.P1': virtual or abstract members cannot be private // abstract private event System.Action P1; Diagnostic(ErrorCode.ERR_VirtualPrivate, "P1").WithArguments("I1.P1").WithLocation(4, 42), // (6,41): error CS0065: 'I1.P2': event property must have both add and remove accessors // virtual private event System.Action P2; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P2").WithArguments("I1.P2").WithLocation(6, 41), // (6,41): error CS0621: 'I1.P2': virtual or abstract members cannot be private // virtual private event System.Action P2; Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I1.P2").WithLocation(6, 41), // (6,41): warning CS0067: The event 'I1.P2' is never used // virtual private event System.Action P2; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P2").WithArguments("I1.P2").WithLocation(6, 41), // (8,40): error CS0238: 'I1.P3' cannot be sealed because it is not an override // sealed private event System.Action P3 Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I1.P3").WithLocation(8, 40), // (14,33): error CS0068: 'I1.P4': instance event in interface cannot have initializer // private event System.Action P4 = null; Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P4").WithArguments("I1.P4").WithLocation(14, 33), // (14,33): error CS0065: 'I1.P4': event property must have both add and remove accessors // private event System.Action P4 = null; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P4").WithArguments("I1.P4").WithLocation(14, 33), // (17,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1"), // (14,33): warning CS0067: The event 'I1.P4' is never used // private event System.Action P4 = null; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P4").WithArguments("I1.P4").WithLocation(14, 33) ); ValidateEventModifiers_10(compilation1); } private static void ValidateEventModifiers_10(CSharpCompilation compilation1) { var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMembers().OfType<EventSymbol>().ElementAt(0); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Private, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); ValidateP1Accessor(p1.AddMethod); ValidateP1Accessor(p1.RemoveMethod); void ValidateP1Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } var p2 = i1.GetMembers().OfType<EventSymbol>().ElementAt(1); Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); ValidateP2Accessor(p2.AddMethod); ValidateP2Accessor(p2.RemoveMethod); void ValidateP2Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); } var p3 = i1.GetMembers().OfType<EventSymbol>().ElementAt(2); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.True(p3.IsSealed); Assert.False(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Private, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.AddMethod); ValidateP3Accessor(p3.RemoveMethod); void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.True(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } var p4 = i1.GetMembers().OfType<EventSymbol>().ElementAt(3); Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); Assert.False(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); ValidateP4Accessor(p4.AddMethod); ValidateP4Accessor(p4.RemoveMethod); void ValidateP4Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } [Fact] public void EventModifiers_11_01() { var source1 = @" public interface I1 { internal abstract event System.Action P1; sealed void Test() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11(source1, source2, Accessibility.Internal, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(12, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(16, 9) ), expectedNoImplementation: ExpectedDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(12, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(16, 9) ) ); } private void ValidateEventModifiers_11(string source1, string source2, Accessibility accessibility, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedNoImplementation) { ValidateEventModifiers_11(source1, source2, accessibility, expectedIn9, expectedAcrossAssemblyBoundaries: Array.Empty<DiagnosticDescription>(), expectedNoImplementation); } private void ValidateEventModifiers_11(string source1, string source2, Accessibility accessibility, DiagnosticDescription[] expectedIn9, DiagnosticDescription[] expectedAcrossAssemblyBoundaries, params DiagnosticDescription[] expectedNoImplementation) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expectedIn9); Validate1(compilation1.SourceModule); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => Validate1(m)).VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var p1 = GetSingleEvent(i1); var test1P1 = GetSingleEvent(test1); var p1add = p1.AddMethod; var p1remove = p1.RemoveMethod; ValidateEvent(p1); ValidateMethod(p1add); ValidateMethod(p1remove); Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test1P1.AddMethod, test1.FindImplementationForInterfaceMember(p1add)); Assert.Same(test1P1.RemoveMethod, test1.FindImplementationForInterfaceMember(p1remove)); } void ValidateEvent(EventSymbol p1) { Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(accessibility, p1.DeclaredAccessibility); } void ValidateMethod(MethodSymbol m1) { Assert.True(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(accessibility, m1.DeclaredAccessibility); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var p1 = GetSingleEvent(i1); ValidateEvent(p1); ValidateMethod(p1.AddMethod); ValidateMethod(p1.RemoveMethod); } var source3 = @" class Test2 : I1 { } "; foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); Validate1(compilation3.SourceModule); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => Validate1(m)).VerifyDiagnostics(); } Validate1(compilation3.SourceModule); var compilation5 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics(expectedNoImplementation); ValidateEventNotImplemented_11(compilation5, "Test2"); } } private static void ValidateEventNotImplemented_11(CSharpCompilation compilation, string className) { var test2 = compilation.GetTypeByMetadataName(className); var i1 = compilation.GetTypeByMetadataName("I1"); var p1 = GetSingleEvent(i1); Assert.Null(test2.FindImplementationForInterfaceMember(p1)); Assert.Null(test2.FindImplementationForInterfaceMember(p1.AddMethod)); Assert.Null(test2.FindImplementationForInterfaceMember(p1.RemoveMethod)); } [Fact] public void EventModifiers_11_02() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(11, 9), // (15,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(15, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(11, 9), // (15,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(15, 9) ) ); } private void ValidateEventModifiers_11_02(string source1, string source2, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(expectedIn9); ValidateEventImplementation_11(compilation1.SourceModule); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateEventImplementation_11(m)).VerifyDiagnostics(); ValidateEventImplementation_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); ValidateEventImplementation_11(compilation3.SourceModule); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateEventImplementation_11(m)).VerifyDiagnostics(); } ValidateEventImplementation_11(compilation3.SourceModule); } } private static void ValidateEventImplementation_11(ModuleSymbol m) { ValidateEventImplementation_11(m, implementedByBase: false); } private static void ValidateEventImplementationByBase_11(ModuleSymbol m) { ValidateEventImplementation_11(m, implementedByBase: true); } private static void ValidateEventImplementation_11(ModuleSymbol m, bool implementedByBase) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var p1 = GetSingleEvent(i1); var test1P1 = GetSingleEvent(implementedByBase ? test1.BaseTypeNoUseSiteDiagnostics : test1); var p1Add = p1.AddMethod; var p1Remove = p1.RemoveMethod; Assert.Same(test1P1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test1P1.AddMethod, test1.FindImplementationForInterfaceMember(p1Add)); Assert.Same(test1P1.RemoveMethod, test1.FindImplementationForInterfaceMember(p1Remove)); Assert.True(test1P1.AddMethod.IsMetadataVirtual()); Assert.True(test1P1.RemoveMethod.IsMetadataVirtual()); } [Fact] public void EventModifiers_11_03() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } event System.Action I1.P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_03(source1, source2, TargetFramework.Standard, // (9,28): error CS0122: 'I1.P1' is inaccessible due to its protection level // event System.Action I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(9, 28) ); } private void ValidateEventModifiers_11_03(string source1, string source2, TargetFramework targetFramework, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, targetFramework: targetFramework, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: !(targetFramework == TargetFramework.Standard || ExecutionConditionUtil.IsMonoOrCoreClr) ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidateEventImplementation_11); ValidateEventImplementation_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: targetFramework, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: targetFramework); compilation3.VerifyDiagnostics(expected); if (expected.Length == 0) { CompileAndVerify(compilation3, expectedOutput: !(targetFramework == TargetFramework.Standard || ExecutionConditionUtil.IsMonoOrCoreClr) ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidateEventImplementation_11); } ValidateEventImplementation_11(compilation3.SourceModule); } } [Fact] public void EventModifiers_11_04() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } public class Test2 : I1 { event System.Action I1.P1 { add { System.Console.WriteLine(""Test2.get_P1""); } remove { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(11, 9), // (15,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(15, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(11, 9), // (15,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(15, 9) ) ); } [Fact] public void EventModifiers_11_05() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } public class Test2 : I1 { event System.Action I1.P1 { add { System.Console.WriteLine(""Test2.get_P1""); } remove { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(11, 9), // (15,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(15, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(11, 9), // (15,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(15, 9) ) ); } [Fact] public void EventModifiers_11_06() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } public class Test2 : I1 { event System.Action I1.P1 { add { System.Console.WriteLine(""Test2.get_P1""); } remove { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @"abstract class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test3()); } public abstract event System.Action P1; } class Test3 : Test1 { public override event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (9,41): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract event System.Action P1; Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "P1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(9, 41), // (9,41): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // public abstract event System.Action P1; Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "P1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(9, 41) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (9,41): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // public abstract event System.Action P1; Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "P1").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(9, 41), // (9,41): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // public abstract event System.Action P1; Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "P1").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(9, 41) ) ); } [Fact] public void EventModifiers_11_07() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } public class Test2 : I1 { event System.Action I1.P1 { add { System.Console.WriteLine(""Test2.get_P1""); } remove { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1, I2 { static void Main() { TestHelper.CallP1(new Test1()); } public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } public interface I2 { event System.Action P1; } "; ValidateEventModifiers_11_02(source1, source2, expectedIn9: ExpectedDiagnostics( // (11,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(11, 9), // (15,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(15, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (11,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(11, 9), // (15,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(15, 9) ) ); } [Fact] public void EventModifiers_11_08() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } public class Test2 : I1 { event System.Action I1.P1 { add { System.Console.WriteLine(""Test2.get_P1""); } remove { System.Console.WriteLine(""Test2.set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual event System.Action<object> P1 { add { System.Console.WriteLine(""Test1.get_P1""); } remove { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidateEventModifiers_11_08(source1, source2); } private void ValidateEventModifiers_11_08(string source1, string source2) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation1, expectedOutput: @"Test2.get_P1 Test2.set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidateEventImplementationByBase_11); ValidateEventImplementationByBase_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation3, expectedOutput: @"Test2.get_P1 Test2.set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidateEventImplementationByBase_11); ValidateEventImplementationByBase_11(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); CompileAndVerify(compilation4, expectedOutput: @"Test2.get_P1 Test2.set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: ValidateEventImplementationByBase_11); ValidateEventImplementationByBase_11(compilation4.SourceModule); } [Fact] public void EventModifiers_11_09() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } public class TestHelper { public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { TestHelper.CallP1(new Test1()); } public virtual event System.Action<object> P1 { add { System.Console.WriteLine(""Test1.get_P1""); } remove { System.Console.WriteLine(""Test1.set_P1""); } } } "; ValidateEventModifiers_11_09(source1, source2, // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.P1'. 'Test1.P1' cannot implement 'I1.P1' because it does not have the matching return type of 'Action'. // class Test1 : I1 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I1").WithArguments("Test1", "I1.P1", "Test1.P1", "System.Action").WithLocation(2, 15) ); } private void ValidateEventModifiers_11_09(string source1, string source2, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics(expected); ValidateEventNotImplemented_11(compilation1, "Test1"); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation3.VerifyDiagnostics(expected); ValidateEventNotImplemented_11(compilation3, "Test1"); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation4.VerifyDiagnostics(expected); ValidateEventNotImplemented_11(compilation4, "Test1"); } [Fact] public void EventModifiers_11_10() { var source1 = @" public interface I1 { internal abstract event System.Action P1; sealed void Test() { P1 += null; P1 -= null; } } "; var source2 = @" public class Test2 : I1 { public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidateEventModifiers_11_10(source1, source2, expectedIn9: ExpectedDiagnostics( // (6,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.add'. 'Test2.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test2", "I1.P1.add", "Test2.P1.add", "9.0", "10.0").WithLocation(6, 9), // (10,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.remove'. 'Test2.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test2", "I1.P1.remove", "Test2.P1.remove", "9.0", "10.0").WithLocation(10, 9) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (6,9): error CS9044: 'Test2' does not implement interface member 'I1.P1.add'. 'Test2.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test2", "I1.P1.add", "Test2.P1.add").WithLocation(6, 9), // (10,9): error CS9044: 'Test2' does not implement interface member 'I1.P1.remove'. 'Test2.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test2", "I1.P1.remove", "Test2.P1.remove").WithLocation(10, 9) ) ); } private void ValidateEventModifiers_11_10(string source1, string source2, DiagnosticDescription[] expectedIn9, params DiagnosticDescription[] expectedAcrossAssemblyBoundaries) { var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(expectedIn9); ValidateEventImplementationByBase_11(compilation1.SourceModule); compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateEventImplementationByBase_11(m)).VerifyDiagnostics(); ValidateEventImplementationByBase_11(compilation1.SourceModule); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); foreach (var reference in new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }) { var compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries.Length != 0 ? expectedAcrossAssemblyBoundaries : expectedIn9); ValidateEventImplementationByBase_11(compilation3.SourceModule); compilation3 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); if (expectedAcrossAssemblyBoundaries.Length != 0) { compilation3.VerifyDiagnostics(expectedAcrossAssemblyBoundaries); } else { CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateEventImplementationByBase_11(m)).VerifyDiagnostics(); } ValidateEventImplementationByBase_11(compilation3.SourceModule); } } [Fact] public void EventModifiers_11_11() { var source1 = @" public interface I1 { internal abstract event System.Action P1; sealed void Test() { P1 += null; P1 -= null; } } public class Test2 : I1 { public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; var source2 = @" class Test1 : Test2, I1 { static void Main() { I1 x = new Test1(); x.Test(); } } "; ValidateEventModifiers_11_11(source1, source2, // (16,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.add'. 'Test2.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test2", "I1.P1.add", "Test2.P1.add", "9.0", "10.0").WithLocation(16, 9), // (20,9): error CS8704: 'Test2' does not implement interface member 'I1.P1.remove'. 'Test2.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test2", "I1.P1.remove", "Test2.P1.remove", "9.0", "10.0").WithLocation(20, 9) ); } private void ValidateEventModifiers_11_11(string source1, string source2, params DiagnosticDescription[] expected) { var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp, assemblyName: "EventModifiers_11_11"); compilation2.VerifyDiagnostics(expected); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp, assemblyName: "EventModifiers_11_11"); compilation2.VerifyDiagnostics(); var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1", verify: VerifyOnMonoOrCoreClr, symbolValidator: (m) => ValidateEventImplementationByBase_11(m)).VerifyDiagnostics(); ValidateEventImplementationByBase_11(compilation3.SourceModule); } [Fact] public void EventModifiers_12() { var source1 = @" public interface I1 { internal abstract event System.Action P1; } class Test1 : I1 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (7,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(7, 15) ); var test1 = compilation1.GetTypeByMetadataName("Test1"); var i1 = compilation1.GetTypeByMetadataName("I1"); var p1 = i1.GetMember<EventSymbol>("P1"); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test1.FindImplementationForInterfaceMember(p1.AddMethod)); Assert.Null(test1.FindImplementationForInterfaceMember(p1.RemoveMethod)); } [Fact] public void EventModifiers_13() { var source1 = @" public interface I1 { public sealed event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } public interface I2 { public sealed event System.Action P2 { add => System.Console.WriteLine(""get_P2""); remove => System.Console.WriteLine(""set_P2""); } } class Test1 : I1 { static void Main() { I1 i1 = new Test1(); i1.P1 += null; i1.P1 -= null; I2 i2 = new Test2(); i2.P2 += null; i2.P2 -= null; } public event System.Action P1 { add => throw null; remove => throw null; } } class Test2 : I2 { public event System.Action P2 { add => throw null; remove => throw null; } } "; ValidateEventModifiers_13(source1); } private void ValidateEventModifiers_13(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); void Validate(ModuleSymbol m) { for (int i = 1; i <= 2; i++) { var test1 = m.GlobalNamespace.GetTypeMember("Test" + i); var i1 = m.GlobalNamespace.GetTypeMember("I" + i); var p1 = GetSingleEvent(i1); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor(p1.AddMethod); ValidateAccessor(p1.RemoveMethod); void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); } [Fact] public void EventModifiers_14() { var source1 = @" public interface I1 { public sealed event System.Action P1 = null; } public interface I2 { abstract sealed event System.Action P2 {add; remove;} } public interface I3 { virtual sealed event System.Action P3 { add {} remove {} } } class Test1 : I1, I2, I3 { event System.Action I1.P1 { add => throw null; remove => throw null; } event System.Action I2.P2 { add => throw null; remove => throw null; } event System.Action I3.P3 { add => throw null; remove => throw null; } } class Test2 : I1, I2, I3 {} "; ValidateEventModifiers_14(source1, // (4,39): error CS0068: 'I1.P1': instance event in interface cannot have initializer // public sealed event System.Action P1 = null; Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P1").WithArguments("I1.P1").WithLocation(4, 39), // (4,39): error CS0065: 'I1.P1': event property must have both add and remove accessors // public sealed event System.Action P1; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P1").WithArguments("I1.P1").WithLocation(4, 39), // (8,41): error CS0238: 'I2.P2' cannot be sealed because it is not an override // abstract sealed event System.Action P2 {add; remove;} Diagnostic(ErrorCode.ERR_SealedNonOverride, "P2").WithArguments("I2.P2").WithLocation(8, 41), // (8,44): error CS8712: 'I2.P2': abstract event cannot use event accessor syntax // abstract sealed event System.Action P2 {add; remove;} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I2.P2").WithLocation(8, 44), // (12,40): error CS0238: 'I3.P3' cannot be sealed because it is not an override // virtual sealed event System.Action P3 Diagnostic(ErrorCode.ERR_SealedNonOverride, "P3").WithArguments("I3.P3").WithLocation(12, 40), // (21,28): error CS0539: 'Test1.P1' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I1.P1 { add => throw null; remove => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P1").WithArguments("Test1.P1").WithLocation(21, 28), // (22,28): error CS0539: 'Test1.P2' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I2.P2 { add => throw null; remove => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P2").WithArguments("Test1.P2").WithLocation(22, 28), // (23,28): error CS0539: 'Test1.P3' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I3.P3 { add => throw null; remove => throw null; } Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test1.P3").WithLocation(23, 28), // (4,39): warning CS0067: The event 'I1.P1' is never used // public sealed event System.Action P1 = null; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P1").WithArguments("I1.P1").WithLocation(4, 39) ); } private void ValidateEventModifiers_14(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var p1 = GetSingleEvent(compilation1, "I1"); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Null(test2.FindImplementationForInterfaceMember(p1)); Validate1(p1.AddMethod); Validate1(p1.RemoveMethod); void Validate1(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p2 = GetSingleEvent(compilation1, "I2"); var test1P2 = test1.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); Assert.True(p2.IsAbstract); Assert.False(p2.IsVirtual); Assert.True(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p2)); Assert.Null(test2.FindImplementationForInterfaceMember(p2)); Validate2(p2.AddMethod); Validate2(p2.RemoveMethod); void Validate2(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.True(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p3 = GetSingleEvent(compilation1, "I3"); var test1P3 = test1.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I3.")).Single(); Assert.False(p3.IsAbstract); Assert.True(p3.IsVirtual); Assert.True(p3.IsSealed); Assert.False(p3.IsStatic); Assert.False(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); Validate3(p3.AddMethod); Validate3(p3.RemoveMethod); void Validate3(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.True(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } [Fact] public void EventModifiers_15() { var source1 = @" public interface I0 { abstract virtual event System.Action P0; } public interface I1 { abstract virtual event System.Action P1 { add { throw null; } } } public interface I2 { virtual abstract event System.Action P2 { add { throw null; } remove { throw null; } } } public interface I3 { abstract virtual event System.Action P3 { remove { throw null; } } } public interface I4 { abstract virtual event System.Action P4 { add => throw null; } } public interface I5 { abstract virtual event System.Action P5 { add => throw null; remove => throw null; } } public interface I6 { abstract virtual event System.Action P6 { remove => throw null; } } public interface I7 { abstract virtual event System.Action P7 { add; } } public interface I8 { abstract virtual event System.Action P8 { remove; } } class Test1 : I0, I1, I2, I3, I4, I5, I6, I7, I8 { event System.Action I0.P0 { add { throw null; } remove { throw null; } } event System.Action I1.P1 { add { throw null; } } event System.Action I2.P2 { add { throw null; } remove { throw null; } } event System.Action I3.P3 { remove { throw null; } } event System.Action I4.P4 { add { throw null; } } event System.Action I5.P5 { add { throw null; } remove { throw null; } } event System.Action I6.P6 { remove { throw null; } } event System.Action I7.P7 { add { throw null; } } event System.Action I8.P8 { remove { throw null; } } } class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 {} "; ValidateEventModifiers_15(source1, // (4,42): error CS0503: The abstract event 'I0.P0' cannot be marked virtual // abstract virtual event System.Action P0; Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P0").WithArguments("event", "I0.P0").WithLocation(4, 42), // (8,42): error CS0503: The abstract event 'I1.P1' cannot be marked virtual // abstract virtual event System.Action P1 { add { throw null; } } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P1").WithArguments("event", "I1.P1").WithLocation(8, 42), // (8,45): error CS8712: 'I1.P1': abstract event cannot use event accessor syntax // abstract virtual event System.Action P1 { add { throw null; } } Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.P1").WithLocation(8, 45), // (12,42): error CS0503: The abstract event 'I2.P2' cannot be marked virtual // virtual abstract event System.Action P2 Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P2").WithArguments("event", "I2.P2").WithLocation(12, 42), // (13,5): error CS8712: 'I2.P2': abstract event cannot use event accessor syntax // { Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I2.P2").WithLocation(13, 5), // (20,42): error CS0503: The abstract event 'I3.P3' cannot be marked virtual // abstract virtual event System.Action P3 { remove { throw null; } } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P3").WithArguments("event", "I3.P3").WithLocation(20, 42), // (20,45): error CS8712: 'I3.P3': abstract event cannot use event accessor syntax // abstract virtual event System.Action P3 { remove { throw null; } } Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I3.P3").WithLocation(20, 45), // (24,42): error CS0503: The abstract event 'I4.P4' cannot be marked virtual // abstract virtual event System.Action P4 { add => throw null; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P4").WithArguments("event", "I4.P4").WithLocation(24, 42), // (24,45): error CS8712: 'I4.P4': abstract event cannot use event accessor syntax // abstract virtual event System.Action P4 { add => throw null; } Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I4.P4").WithLocation(24, 45), // (28,42): error CS0503: The abstract event 'I5.P5' cannot be marked virtual // abstract virtual event System.Action P5 Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P5").WithArguments("event", "I5.P5").WithLocation(28, 42), // (29,5): error CS8712: 'I5.P5': abstract event cannot use event accessor syntax // { Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I5.P5").WithLocation(29, 5), // (36,42): error CS0503: The abstract event 'I6.P6' cannot be marked virtual // abstract virtual event System.Action P6 { remove => throw null; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P6").WithArguments("event", "I6.P6").WithLocation(36, 42), // (36,45): error CS8712: 'I6.P6': abstract event cannot use event accessor syntax // abstract virtual event System.Action P6 { remove => throw null; } Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I6.P6").WithLocation(36, 45), // (40,42): error CS0503: The abstract event 'I7.P7' cannot be marked virtual // abstract virtual event System.Action P7 { add; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P7").WithArguments("event", "I7.P7").WithLocation(40, 42), // (40,45): error CS8712: 'I7.P7': abstract event cannot use event accessor syntax // abstract virtual event System.Action P7 { add; } Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I7.P7").WithLocation(40, 45), // (44,42): error CS0503: The abstract event 'I8.P8' cannot be marked virtual // abstract virtual event System.Action P8 { remove; } Diagnostic(ErrorCode.ERR_AbstractNotVirtual, "P8").WithArguments("event", "I8.P8").WithLocation(44, 42), // (44,45): error CS8712: 'I8.P8': abstract event cannot use event accessor syntax // abstract virtual event System.Action P8 { remove; } Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I8.P8").WithLocation(44, 45), // (54,28): error CS0065: 'Test1.I1.P1': event property must have both add and remove accessors // event System.Action I1.P1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P1").WithArguments("Test1.I1.P1").WithLocation(54, 28), // (63,28): error CS0065: 'Test1.I3.P3': event property must have both add and remove accessors // event System.Action I3.P3 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P3").WithArguments("Test1.I3.P3").WithLocation(63, 28), // (67,28): error CS0065: 'Test1.I4.P4': event property must have both add and remove accessors // event System.Action I4.P4 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P4").WithArguments("Test1.I4.P4").WithLocation(67, 28), // (76,28): error CS0065: 'Test1.I6.P6': event property must have both add and remove accessors // event System.Action I6.P6 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P6").WithArguments("Test1.I6.P6").WithLocation(76, 28), // (80,28): error CS0065: 'Test1.I7.P7': event property must have both add and remove accessors // event System.Action I7.P7 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P7").WithArguments("Test1.I7.P7").WithLocation(80, 28), // (84,28): error CS0065: 'Test1.I8.P8': event property must have both add and remove accessors // event System.Action I8.P8 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "P8").WithArguments("Test1.I8.P8").WithLocation(84, 28), // (90,15): error CS0535: 'Test2' does not implement interface member 'I0.P0' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0").WithArguments("Test2", "I0.P0").WithLocation(90, 15), // (90,19): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(90, 19), // (90,23): error CS0535: 'Test2' does not implement interface member 'I2.P2' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test2", "I2.P2").WithLocation(90, 23), // (90,27): error CS0535: 'Test2' does not implement interface member 'I3.P3' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test2", "I3.P3").WithLocation(90, 27), // (90,31): error CS0535: 'Test2' does not implement interface member 'I4.P4' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.P4").WithLocation(90, 31), // (90,35): error CS0535: 'Test2' does not implement interface member 'I5.P5' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test2", "I5.P5").WithLocation(90, 35), // (90,39): error CS0535: 'Test2' does not implement interface member 'I6.P6' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I6").WithArguments("Test2", "I6.P6").WithLocation(90, 39), // (90,43): error CS0535: 'Test2' does not implement interface member 'I7.P7' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I7").WithArguments("Test2", "I7.P7").WithLocation(90, 43), // (90,47): error CS0535: 'Test2' does not implement interface member 'I8.P8' // class Test2 : I0, I1, I2, I3, I4, I5, I6, I7, I8 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I8").WithArguments("Test2", "I8.P8").WithLocation(90, 47) ); } private void ValidateEventModifiers_15(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); for (int i = 0; i <= 8; i++) { var i1 = compilation1.GetTypeByMetadataName("I" + i); var p2 = GetSingleEvent(i1); var test1P2 = test1.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith(i1.Name)).Single(); Assert.True(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(test1P2, test1.FindImplementationForInterfaceMember(p2)); Assert.Null(test2.FindImplementationForInterfaceMember(p2)); switch (i) { case 3: case 6: case 8: Assert.Null(p2.AddMethod); ValidateAccessor(p2.RemoveMethod, test1P2.RemoveMethod); break; case 1: case 4: case 7: Assert.Null(p2.RemoveMethod); ValidateAccessor(p2.AddMethod, test1P2.AddMethod); break; default: ValidateAccessor(p2.AddMethod, test1P2.AddMethod); ValidateAccessor(p2.RemoveMethod, test1P2.RemoveMethod); break; } void ValidateAccessor(MethodSymbol accessor, MethodSymbol implementedBy) { Assert.True(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(implementedBy, test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } } [Fact] public void EventModifiers_16() { var source1 = @" public interface I1 { extern event System.Action P1; } public interface I2 { virtual extern event System.Action P2; } public interface I3 { static extern event System.Action P3; } public interface I4 { private extern event System.Action P4; } public interface I5 { extern sealed event System.Action P5; } public interface I6 { static event System.Action P6 { add => throw null; remove => throw null; } } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { event System.Action I1.P1 { add{} remove{} } event System.Action I2.P2 { add{} remove{} } } "; ValidateEventModifiers_16(source1); } private void ValidateEventModifiers_16(string source1) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var test2 = m.GlobalNamespace.GetTypeMember("Test2"); bool isSource = !(m is PEModuleSymbol); var p1 = GetSingleEvent(m, "I1"); var test2P1 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I1.")).Single(); Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.Equal(isSource, p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); ValidateP1Accessor(p1.AddMethod, test2P1.AddMethod); ValidateP1Accessor(p1.RemoveMethod, test2P1.RemoveMethod); void ValidateP1Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.Equal(isSource, accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p2 = GetSingleEvent(m, "I2"); var test2P2 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.Equal(isSource, p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); ValidateP2Accessor(p2.AddMethod, test2P2.AddMethod); ValidateP2Accessor(p2.RemoveMethod, test2P2.RemoveMethod); void ValidateP2Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.Equal(isSource, accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var i3 = m.ContainingAssembly.GetTypeByMetadataName("I3"); var p3 = GetSingleEvent(i3); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.False(p3.IsSealed); Assert.True(p3.IsStatic); Assert.Equal(isSource, p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.AddMethod); ValidateP3Accessor(p3.RemoveMethod); void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.Equal(isSource, accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p4 = GetSingleEvent(m, "I4"); Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); Assert.Equal(isSource, p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.Null(test2.FindImplementationForInterfaceMember(p4)); ValidateP4Accessor(p4.AddMethod); ValidateP4Accessor(p4.RemoveMethod); void ValidateP4Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.Equal(isSource, accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p5 = GetSingleEvent(m, "I5"); Assert.False(p5.IsAbstract); Assert.False(p5.IsVirtual); Assert.False(p5.IsSealed); Assert.False(p5.IsStatic); Assert.Equal(isSource, p5.IsExtern); Assert.False(p5.IsOverride); Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); ValidateP5Accessor(p5.AddMethod); ValidateP5Accessor(p5.RemoveMethod); void ValidateP5Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.Equal(isSource, accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (4,32): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern event System.Action P1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P1").WithArguments("extern", "7.3", "8.0").WithLocation(4, 32), // (8,40): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern event System.Action P2; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P2").WithArguments("extern", "7.3", "8.0").WithLocation(8, 40), // (8,40): error CS8703: The modifier 'virtual' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // virtual extern event System.Action P2; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P2").WithArguments("virtual", "7.3", "8.0").WithLocation(8, 40), // (12,39): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static extern event System.Action P3; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("static", "7.3", "8.0").WithLocation(12, 39), // (12,39): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static extern event System.Action P3; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P3").WithArguments("extern", "7.3", "8.0").WithLocation(12, 39), // (16,40): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern event System.Action P4; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P4").WithArguments("private", "7.3", "8.0").WithLocation(16, 40), // (16,40): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private extern event System.Action P4; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P4").WithArguments("extern", "7.3", "8.0").WithLocation(16, 40), // (20,39): error CS8703: The modifier 'sealed' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed event System.Action P5; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P5").WithArguments("sealed", "7.3", "8.0").WithLocation(20, 39), // (20,39): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern sealed event System.Action P5; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P5").WithArguments("extern", "7.3", "8.0").WithLocation(20, 39), // (24,32): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static event System.Action P6 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "P6").WithArguments("default interface implementation", "8.0").WithLocation(24, 32), // (8,40): warning CS0626: Method, operator, or accessor 'I2.P2.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern event System.Action P2; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P2").WithArguments("I2.P2.remove").WithLocation(8, 40), // (12,39): warning CS0626: Method, operator, or accessor 'I3.P3.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern event System.Action P3; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P3").WithArguments("I3.P3.remove").WithLocation(12, 39), // (16,40): warning CS0626: Method, operator, or accessor 'I4.P4.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern event System.Action P4; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P4").WithArguments("I4.P4.remove").WithLocation(16, 40), // (20,39): warning CS0626: Method, operator, or accessor 'I5.P5.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed event System.Action P5; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P5").WithArguments("I5.P5.remove").WithLocation(20, 39), // (4,32): warning CS0626: Method, operator, or accessor 'I1.P1.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P1; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P1").WithArguments("I1.P1.remove").WithLocation(4, 32) ); Validate(compilation2.SourceModule); var compilation3 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); Assert.False(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (4,32): error CS8701: Target runtime doesn't support default interface implementation. // extern event System.Action P1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "P1").WithLocation(4, 32), // (8,40): error CS8701: Target runtime doesn't support default interface implementation. // virtual extern event System.Action P2; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "P2").WithLocation(8, 40), // (16,40): error CS8701: Target runtime doesn't support default interface implementation. // private extern event System.Action P4; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "P4").WithLocation(16, 40), // (20,39): error CS8701: Target runtime doesn't support default interface implementation. // extern sealed event System.Action P5; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "P5").WithLocation(20, 39), // (8,40): warning CS0626: Method, operator, or accessor 'I2.P2.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // virtual extern event System.Action P2; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P2").WithArguments("I2.P2.remove").WithLocation(8, 40), // (12,39): warning CS0626: Method, operator, or accessor 'I3.P3.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern event System.Action P3; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P3").WithArguments("I3.P3.remove").WithLocation(12, 39), // (16,40): warning CS0626: Method, operator, or accessor 'I4.P4.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // private extern event System.Action P4; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P4").WithArguments("I4.P4.remove").WithLocation(16, 40), // (20,39): warning CS0626: Method, operator, or accessor 'I5.P5.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern sealed event System.Action P5; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P5").WithArguments("I5.P5.remove").WithLocation(20, 39), // (4,32): warning CS0626: Method, operator, or accessor 'I1.P1.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P1; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P1").WithArguments("I1.P1.remove").WithLocation(4, 32) ); Validate(compilation3.SourceModule); } [Fact] public void EventModifiers_17() { var source1 = @" public interface I1 { abstract extern event System.Action P1; } public interface I2 { extern event System.Action P2 = null; } public interface I3 { static extern event System.Action P3 {add => throw null; remove => throw null;} } public interface I4 { private extern event System.Action P4 { add {throw null;} remove {throw null;}} } class Test1 : I1, I2, I3, I4 { } class Test2 : I1, I2, I3, I4 { event System.Action I1.P1 { add => throw null; remove => throw null;} event System.Action I2.P2 { add => throw null; remove => throw null;} event System.Action I3.P3 { add => throw null; remove => throw null;} event System.Action I4.P4 { add => throw null; remove => throw null;} } "; ValidateEventModifiers_17(source1, // (4,41): error CS0180: 'I1.P1' cannot be both extern and abstract // abstract extern event System.Action P1; Diagnostic(ErrorCode.ERR_AbstractAndExtern, "P1").WithArguments("I1.P1").WithLocation(4, 41), // (8,32): error CS0068: 'I2.P2': instance event in interface cannot have initializer // extern event System.Action P2 = null; Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P2").WithArguments("I2.P2").WithLocation(8, 32), // (12,43): error CS0179: 'I3.P3.add' cannot be extern and declare a body // static extern event System.Action P3 {add => throw null; remove => throw null;} Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I3.P3.add").WithLocation(12, 43), // (12,62): error CS0179: 'I3.P3.remove' cannot be extern and declare a body // static extern event System.Action P3 {add => throw null; remove => throw null;} Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I3.P3.remove").WithLocation(12, 62), // (16,45): error CS0179: 'I4.P4.add' cannot be extern and declare a body // private extern event System.Action P4 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("I4.P4.add").WithLocation(16, 45), // (16,63): error CS0179: 'I4.P4.remove' cannot be extern and declare a body // private extern event System.Action P4 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("I4.P4.remove").WithLocation(16, 63), // (19,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1, I2, I3, I4 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(19, 15), // (27,28): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I3.P3 { add => throw null; remove => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(27, 28), // (28,28): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I4.P4 { add => throw null; remove => throw null;} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(28, 28), // (8,32): warning CS0626: Method, operator, or accessor 'I2.P2.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern event System.Action P2 = null; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P2").WithArguments("I2.P2.remove").WithLocation(8, 32), // (8,32): warning CS0067: The event 'I2.P2' is never used // extern event System.Action P2 = null; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P2").WithArguments("I2.P2").WithLocation(8, 32) ); } private void ValidateEventModifiers_17(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var p1 = GetSingleEvent(compilation1, "I1"); var test2P1 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I1.")).Single(); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.True(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); ValidateP1Accessor(p1.AddMethod, test2P1.AddMethod); ValidateP1Accessor(p1.RemoveMethod, test2P1.RemoveMethod); void ValidateP1Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p2 = GetSingleEvent(compilation1, "I2"); var test2P2 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); Assert.False(p2.IsAbstract); Assert.True(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.True(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Public, p2.DeclaredAccessibility); Assert.Same(p2, test1.FindImplementationForInterfaceMember(p2)); Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); ValidateP2Accessor(p2.AddMethod, test2P2.AddMethod); ValidateP2Accessor(p2.RemoveMethod, test2P2.RemoveMethod); void ValidateP2Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.False(accessor.IsAbstract); Assert.True(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Same(accessor, test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p3 = GetSingleEvent(compilation1, "I3"); var test2P3 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I3.")).Single(); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.False(p3.IsSealed); Assert.True(p3.IsStatic); Assert.True(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.AddMethod); ValidateP3Accessor(p3.RemoveMethod); void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p4 = GetSingleEvent(compilation1, "I4"); Assert.False(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.False(p4.IsStatic); Assert.True(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Private, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.Null(test2.FindImplementationForInterfaceMember(p4)); ValidateP4Accessor(p4.AddMethod); ValidateP4Accessor(p4.RemoveMethod); void ValidateP4Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } [Fact] public void EventModifiers_18() { var source1 = @" public interface I1 { abstract event System.Action P1 {add => throw null; remove => throw null;} } public interface I2 { abstract private event System.Action P2 = null; } public interface I3 { static extern event System.Action P3; } public interface I4 { abstract static event System.Action P4 { add {throw null;} remove {throw null;}} } public interface I5 { override sealed event System.Action P5 { add {throw null;} remove {throw null;}} } class Test1 : I1, I2, I3, I4, I5 { } class Test2 : I1, I2, I3, I4, I5 { event System.Action I1.P1 { add {throw null;} remove {throw null;}} event System.Action I2.P2 { add {throw null;} remove {throw null;}} event System.Action I3.P3 { add {throw null;} remove {throw null;}} event System.Action I4.P4 { add {throw null;} remove {throw null;}} event System.Action I5.P5 { add {throw null;} remove {throw null;}} } "; ValidateEventModifiers_18(source1, // (4,37): error CS8712: 'I1.P1': abstract event cannot use event accessor syntax // abstract event System.Action P1 {add => throw null; remove => throw null;} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.P1").WithLocation(4, 37), // (8,42): error CS0068: 'I2.P2': instance event in interface cannot have initializer // abstract private event System.Action P2 = null; Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "P2").WithArguments("I2.P2").WithLocation(8, 42), // (16,41): error CS8703: The modifier 'abstract' is not valid for this item in C# 9.0. Please use language version '11.0' or greater. // abstract static event System.Action P4 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "P4").WithArguments("abstract", "9.0", "11.0").WithLocation(16, 41), // (16,44): error CS8712: 'I4.P4': abstract event cannot use event accessor syntax // abstract static event System.Action P4 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I4.P4").WithLocation(16, 44), // (20,41): error CS0106: The modifier 'override' is not valid for this item // override sealed event System.Action P5 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_BadMemberFlag, "P5").WithArguments("override").WithLocation(20, 41), // (12,39): warning CS0626: Method, operator, or accessor 'I3.P3.remove' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern event System.Action P3; Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "P3").WithArguments("I3.P3.remove").WithLocation(12, 39), // (8,42): error CS0621: 'I2.P2': virtual or abstract members cannot be private // abstract private event System.Action P2 = null; Diagnostic(ErrorCode.ERR_VirtualPrivate, "P2").WithArguments("I2.P2").WithLocation(8, 42), // (23,15): error CS0535: 'Test1' does not implement interface member 'I1.P1' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.P1").WithLocation(23, 15), // (23,19): error CS0535: 'Test1' does not implement interface member 'I2.P2' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I2.P2").WithLocation(23, 19), // (23,27): error CS0535: 'Test1' does not implement interface member 'I4.P4' // class Test1 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test1", "I4.P4").WithLocation(23, 27), // (30,28): error CS0122: 'I2.P2' is inaccessible due to its protection level // event System.Action I2.P2 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I2.P2").WithLocation(30, 28), // (31,28): error CS0539: 'Test2.P3' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I3.P3 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P3").WithArguments("Test2.P3").WithLocation(31, 28), // (32,28): error CS0539: 'Test2.P4' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I4.P4 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P4").WithArguments("Test2.P4").WithLocation(32, 28), // (33,28): error CS0539: 'Test2.P5' in explicit interface declaration is not found among members of the interface that can be implemented // event System.Action I5.P5 { add {throw null;} remove {throw null;}} Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "P5").WithArguments("Test2.P5").WithLocation(33, 28), // (27,27): error CS0535: 'Test2' does not implement interface member 'I4.P4' // class Test2 : I1, I2, I3, I4, I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I4.P4").WithLocation(27, 27), // (8,42): warning CS0067: The event 'I2.P2' is never used // abstract private event System.Action P2 = null; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "P2").WithArguments("I2.P2").WithLocation(8, 42) ); } private void ValidateEventModifiers_18(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); var test1 = compilation1.GetTypeByMetadataName("Test1"); var test2 = compilation1.GetTypeByMetadataName("Test2"); var p1 = GetSingleEvent(compilation1, "I1"); var test2P1 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I1.")).Single(); Assert.True(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(Accessibility.Public, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); Assert.Same(test2P1, test2.FindImplementationForInterfaceMember(p1)); ValidateP1Accessor(p1.AddMethod, test2P1.AddMethod); ValidateP1Accessor(p1.RemoveMethod, test2P1.RemoveMethod); void ValidateP1Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p2 = GetSingleEvent(compilation1, "I2"); var test2P2 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); Assert.True(p2.IsAbstract); Assert.False(p2.IsVirtual); Assert.False(p2.IsSealed); Assert.False(p2.IsStatic); Assert.False(p2.IsExtern); Assert.False(p2.IsOverride); Assert.Equal(Accessibility.Private, p2.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p2)); Assert.Same(test2P2, test2.FindImplementationForInterfaceMember(p2)); ValidateP2Accessor(p2.AddMethod, test2P2.AddMethod); ValidateP2Accessor(p2.RemoveMethod, test2P2.RemoveMethod); void ValidateP2Accessor(MethodSymbol accessor, MethodSymbol implementation) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Private, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Same(implementation, test2.FindImplementationForInterfaceMember(accessor)); } var p3 = GetSingleEvent(compilation1, "I3"); var test2P3 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I3.")).Single(); Assert.False(p3.IsAbstract); Assert.False(p3.IsVirtual); Assert.False(p3.IsSealed); Assert.True(p3.IsStatic); Assert.True(p3.IsExtern); Assert.False(p3.IsOverride); Assert.Equal(Accessibility.Public, p3.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p3)); Assert.Null(test2.FindImplementationForInterfaceMember(p3)); ValidateP3Accessor(p3.AddMethod); ValidateP3Accessor(p3.RemoveMethod); void ValidateP3Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.True(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p4 = GetSingleEvent(compilation1, "I4"); var test2P4 = test2.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I4.")).Single(); Assert.True(p4.IsAbstract); Assert.False(p4.IsVirtual); Assert.False(p4.IsSealed); Assert.True(p4.IsStatic); Assert.False(p4.IsExtern); Assert.False(p4.IsOverride); Assert.Equal(Accessibility.Public, p4.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p4)); Assert.Null(test2.FindImplementationForInterfaceMember(p4)); ValidateP4Accessor(p4.AddMethod); ValidateP4Accessor(p4.RemoveMethod); void ValidateP4Accessor(MethodSymbol accessor) { Assert.True(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.True(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } var p5 = GetSingleEvent(compilation1, "I5"); Assert.False(p5.IsAbstract); Assert.False(p5.IsVirtual); Assert.False(p5.IsSealed); Assert.False(p5.IsStatic); Assert.False(p5.IsExtern); Assert.False(p5.IsOverride); Assert.Equal(Accessibility.Public, p5.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p5)); Assert.Null(test2.FindImplementationForInterfaceMember(p5)); ValidateP5Accessor(p5.AddMethod); ValidateP5Accessor(p5.RemoveMethod); void ValidateP5Accessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.False(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(Accessibility.Public, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); Assert.Null(test2.FindImplementationForInterfaceMember(accessor)); } } [Fact] public void EventModifiers_20() { var source1 = @" public interface I1 { internal event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } void M2() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidateEventModifiers_20(source1, source2, Accessibility.Internal); } private void ValidateEventModifiers_20(string source1, string source2, Accessibility accessibility) { var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Single(); var p1 = GetSingleEvent(i1); var p1add = p1.AddMethod; var p1remove = p1.RemoveMethod; ValidateEvent(p1); ValidateMethod(p1add); ValidateMethod(p1remove); Assert.Same(p1, test1.FindImplementationForInterfaceMember(p1)); Assert.Same(p1add, test1.FindImplementationForInterfaceMember(p1add)); Assert.Same(p1remove, test1.FindImplementationForInterfaceMember(p1remove)); } void ValidateEvent(EventSymbol p1) { Assert.False(p1.IsAbstract); Assert.True(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.False(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(accessibility, p1.DeclaredAccessibility); } void ValidateMethod(MethodSymbol m1) { Assert.False(m1.IsAbstract); Assert.True(m1.IsVirtual); Assert.True(m1.IsMetadataVirtual()); Assert.False(m1.IsSealed); Assert.False(m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(accessibility, m1.DeclaredAccessibility); } var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); { var i1 = compilation2.GetTypeByMetadataName("I1"); var p1 = GetSingleEvent(i1); ValidateEvent(p1); ValidateMethod(p1.AddMethod); ValidateMethod(p1.RemoveMethod); } var compilation3 = CreateCompilation(source2, new[] { compilation2.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, new[] { compilation2.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 ", verify: VerifyOnMonoOrCoreClr, symbolValidator: Validate1); Validate1(compilation4.SourceModule); } [Fact] public void EventModifiers_21() { var source1 = @" public interface I1 { private static event System.Action P1 { add => throw null; remove => throw null; } internal static event System.Action P2 { add => throw null; remove => throw null; } public static event System.Action P3 { add => throw null; remove => throw null; } static event System.Action P4 { add => throw null; remove => throw null; } } class Test1 { static void Main() { I1.P1 += null; I1.P1 -= null; I1.P2 += null; I1.P2 -= null; I1.P3 += null; I1.P3 -= null; I1.P4 += null; I1.P4 -= null; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (17,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(17, 12), // (18,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(18, 12) ); var source2 = @" class Test2 { static void Main() { I1.P1 += null; I1.P1 -= null; I1.P2 += null; I1.P2 -= null; I1.P3 += null; I1.P3 -= null; I1.P4 += null; I1.P4 -= null; } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics( // (6,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(6, 12), // (7,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(7, 12), // (8,12): error CS0122: 'I1.P2' is inaccessible due to its protection level // I1.P2 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(8, 12), // (9,12): error CS0122: 'I1.P2' is inaccessible due to its protection level // I1.P2 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(9, 12) ); } [Fact] public void EventModifiers_22() { var source0 = @" public interface I1 { protected static event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } protected internal static event System.Action P2 { add { System.Console.WriteLine(""get_P2""); } remove { System.Console.WriteLine(""set_P2""); } } private protected static event System.Action P3 { add => System.Console.WriteLine(""get_P3""); remove => System.Console.WriteLine(""set_P3""); } } "; var source1 = @" class Test1 : I1 { static void Main() { I1.P1 += null; I1.P1 -= null; I1.P2 += null; I1.P2 -= null; I1.P3 += null; I1.P3 -= null; } } "; var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2 get_P3 set_P3", symbolValidator: validate, verify: VerifyOnMonoOrCoreClr_FailsIlVerify); validate(compilation1.SourceModule); var source2 = @" class Test1 { static void Main() { I1.P2 += null; I1.P2 -= null; } } "; var compilation2 = CreateCompilation(source0 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P2 set_P2", verify: VerifyOnMonoOrCoreClr); var compilation3 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); var source3 = @" class Test1 : I1 { static void Main() { I1.P1 += null; I1.P1 -= null; I1.P2 += null; I1.P2 -= null; } } "; var source4 = @" class Test1 { static void Main() { I1.P1 += null; I1.P1 -= null; I1.P2 += null; I1.P2 -= null; I1.P3 += null; I1.P3 -= null; } } "; foreach (var reference in new[] { compilation3.ToMetadataReference(), compilation3.EmitToImageReference() }) { var compilation4 = CreateCompilation(source3, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"get_P1 set_P1 get_P2 set_P2", verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation5 = CreateCompilation(source4, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics( // (6,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(6, 12), // (7,12): error CS0122: 'I1.P1' is inaccessible due to its protection level // I1.P1 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(7, 12), // (8,12): error CS0122: 'I1.P2' is inaccessible due to its protection level // I1.P2 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(8, 12), // (9,12): error CS0122: 'I1.P2' is inaccessible due to its protection level // I1.P2 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P2").WithArguments("I1.P2").WithLocation(9, 12), // (10,12): error CS0122: 'I1.P3' is inaccessible due to its protection level // I1.P3 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(10, 12), // (11,12): error CS0122: 'I1.P3' is inaccessible due to its protection level // I1.P3 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(11, 12) ); var compilation6 = CreateCompilation(source1, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation6.VerifyDiagnostics( // (10,12): error CS0122: 'I1.P3' is inaccessible due to its protection level // I1.P3 += null; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(10, 12), // (11,12): error CS0122: 'I1.P3' is inaccessible due to its protection level // I1.P3 -= null; Diagnostic(ErrorCode.ERR_BadAccess, "P3").WithArguments("I1.P3").WithLocation(11, 12) ); } void validate(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = m.GlobalNamespace.GetTypeMember("I1"); foreach (var tuple in new[] { (name: "P1", access: Accessibility.Protected), (name: "P2", access: Accessibility.ProtectedOrInternal), (name: "P3", access: Accessibility.ProtectedAndInternal)}) { var p1 = i1.GetMember<EventSymbol>(tuple.name); Assert.False(p1.IsAbstract); Assert.False(p1.IsVirtual); Assert.False(p1.IsSealed); Assert.True(p1.IsStatic); Assert.False(p1.IsExtern); Assert.False(p1.IsOverride); Assert.Equal(tuple.access, p1.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(p1)); ValidateAccessor(p1.AddMethod); ValidateAccessor(p1.RemoveMethod); void ValidateAccessor(MethodSymbol accessor) { Assert.False(accessor.IsAbstract); Assert.False(accessor.IsVirtual); Assert.False(accessor.IsMetadataVirtual()); Assert.False(accessor.IsSealed); Assert.True(accessor.IsStatic); Assert.False(accessor.IsExtern); Assert.False(accessor.IsAsync); Assert.False(accessor.IsOverride); Assert.Equal(tuple.access, accessor.DeclaredAccessibility); Assert.Null(test1.FindImplementationForInterfaceMember(accessor)); } } } } [Fact] public void EventModifiers_23() { var source1 = @" public interface I1 { protected abstract event System.Action P1; sealed void Test() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11(source1, source2, Accessibility.Protected, new DiagnosticDescription[] { // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(12, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(16, 9) }, // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ); } [Fact] public void EventModifiers_24() { var source1 = @" public interface I1 { protected internal abstract event System.Action P1; sealed void Test() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11(source1, source2, Accessibility.ProtectedOrInternal, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(12, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(16, 9) ), expectedNoImplementation: ExpectedDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ) ); } [Fact] public void EventModifiers_25() { var source1 = @" public interface I1 { private protected abstract event System.Action P1; sealed void Test() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.Test(); } public event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11(source1, source2, Accessibility.ProtectedAndInternal, expectedIn9: ExpectedDiagnostics( // (12,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add", "9.0", "10.0").WithLocation(12, 9), // (16,9): error CS8704: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement a non-public member in C# 9.0. Please use language version '10.0' or greater. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfNonPublicInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove", "9.0", "10.0").WithLocation(16, 9) ), expectedNoImplementation: ExpectedDiagnostics( // (2,15): error CS0535: 'Test2' does not implement interface member 'I1.P1' // class Test2 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test2", "I1.P1").WithLocation(2, 15) ), expectedAcrossAssemblyBoundaries: ExpectedDiagnostics( // (12,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.add'. 'Test1.P1.add' cannot implicitly implement an inaccessible member. // add Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "add").WithArguments("Test1", "I1.P1.add", "Test1.P1.add").WithLocation(12, 9), // (16,9): error CS9044: 'Test1' does not implement interface member 'I1.P1.remove'. 'Test1.P1.remove' cannot implicitly implement an inaccessible member. // remove Diagnostic(ErrorCode.ERR_ImplicitImplementationOfInaccessibleInterfaceMember, "remove").WithArguments("Test1", "I1.P1.remove", "Test1.P1.remove").WithLocation(16, 9) ) ); } [Fact] public void EventModifiers_26() { var source1 = @" public interface I1 { protected abstract event System.Action P1; public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } event System.Action I1.P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_03(source1, source2, TargetFramework.NetCoreApp); } [Fact] public void EventModifiers_27() { var source1 = @" public interface I1 { protected internal abstract event System.Action P1; public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } event System.Action I1.P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_03(source1, source2, TargetFramework.NetCoreApp); } [Fact] public void EventModifiers_28() { var source1 = @" public interface I1 { private protected abstract event System.Action P1; public static void CallP1(I1 x) { x.P1 += null; x.P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1.CallP1(new Test1()); } event System.Action I1.P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } } "; ValidateEventModifiers_11_03(source1, source2, TargetFramework.NetCoreApp, // (9,28): error CS0122: 'I1.P1' is inaccessible due to its protection level // event System.Action I1.P1 Diagnostic(ErrorCode.ERR_BadAccess, "P1").WithArguments("I1.P1").WithLocation(9, 28) ); } [Fact] public void EventModifiers_29() { var source1 = @" public interface I1 { protected event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } void M2() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidateEventModifiers_20(source1, source2, Accessibility.Protected); } [Fact] public void EventModifiers_30() { var source1 = @" public interface I1 { protected internal event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } void M2() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidateEventModifiers_20(source1, source2, Accessibility.ProtectedOrInternal); } [Fact] public void EventModifiers_31() { var source1 = @" public interface I1 { private protected event System.Action P1 { add { System.Console.WriteLine(""get_P1""); } remove { System.Console.WriteLine(""set_P1""); } } void M2() { P1 += null; P1 -= null; } } "; var source2 = @" class Test1 : I1 { static void Main() { I1 x = new Test1(); x.M2(); } } "; ValidateEventModifiers_20(source1, source2, Accessibility.ProtectedAndInternal); } [Fact] public void NestedTypes_01() { var source1 = @" public interface I1 { interface T1 { void M1(); } class T2 {} struct T3 {} enum T4 { B } delegate void T5(); } class Test1 : I1.T1 { static void Main() { I1.T1 a = new Test1(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } public void M1() { System.Console.WriteLine(""M1""); } } "; ValidateNestedTypes_01(source1); } private void ValidateNestedTypes_01(string source1, Accessibility expected = Accessibility.Public, TargetFramework targetFramework = TargetFramework.Standard, bool execute = true, Verification verify = default) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: targetFramework); for (int i = 1; i <= 5; i++) { Assert.Equal(expected, compilation1.GetMember("I1.T" + i).DeclaredAccessibility); } CompileAndVerify(compilation1, expectedOutput: !execute ? null : @"M1 I1+T2 I1+T3 B I1+T5", verify: verify); } [Fact] public void NestedTypes_02() { var source1 = @" public interface I1 { interface T1 { void M1(); } class T2 {} struct T3 {} enum T4 { B } } class Test1 : I1.T1 { static void Main() { I1.T1 a = new Test1(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); } public void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3); for (int i = 1; i <= 4; i++) { Assert.Equal(Accessibility.Public, compilation1.GetMember("I1.T" + i).DeclaredAccessibility); } compilation1.VerifyDiagnostics( // (4,15): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // interface T1 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "T1").WithArguments("default interface implementation", "8.0").WithLocation(4, 15), // (9,11): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // class T2 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "T2").WithArguments("default interface implementation", "8.0").WithLocation(9, 11), // (12,12): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // struct T3 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "T3").WithArguments("default interface implementation", "8.0").WithLocation(12, 12), // (15,10): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // enum T4 Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "T4").WithArguments("default interface implementation", "8.0").WithLocation(15, 10) ); } [Fact] public void NestedTypes_03() { var source1 = @" public interface I1 { public interface T1 { void M1(); } public class T2 {} public struct T3 {} public enum T4 { B } public delegate void T5(); } class Test1 : I1.T1 { static void Main() { I1.T1 a = new Test1(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } public void M1() { System.Console.WriteLine(""M1""); } } "; ValidateNestedTypes_01(source1); } [Fact] public void NestedTypes_04() { var source0 = @" public interface I1 { protected interface T1 { void M1(); } protected class T2 {} protected struct T3 {} protected enum T4 { B } protected delegate void T5(); } "; var source1 = @" class Test1 : I1 { static void Main() { I1.T1 a = new Test2(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } class Test2 : I1.T1 { public void M1() { System.Console.WriteLine(""M1""); } } } "; ValidateNestedTypes_01(source0 + source1, Accessibility.Protected, targetFramework: TargetFramework.NetCoreApp, execute: ExecutionConditionUtil.IsMonoOrCoreClr, verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); for (int i = 1; i <= 5; i++) { Assert.Equal(Accessibility.Protected, compilation1.GetMember("I1.T" + i).DeclaredAccessibility); } compilation1.VerifyDiagnostics( // (4,25): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected interface T1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T1").WithLocation(4, 25), // (9,21): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected class T2 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T2").WithLocation(9, 21), // (12,22): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected struct T3 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T3").WithLocation(12, 22), // (15,20): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected enum T4 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T4").WithLocation(15, 20), // (20,29): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected delegate void T5(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T5").WithLocation(20, 29) ); var source2 = @" class Test1 { static void Main() { I1.T1 a = new Test2(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } class Test2 : I1.T1 { public void M1() { System.Console.WriteLine(""M1""); } } } "; var compilation2 = CreateCompilation(source2 + source0, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var expected = new DiagnosticDescription[] { // (6,12): error CS0122: 'I1.T1' is inaccessible due to its protection level // I1.T1 a = new Test2(); Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(6, 12), // (7,11): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // a.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(7, 11), // (8,41): error CS0122: 'I1.T2' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T2()); Diagnostic(ErrorCode.ERR_BadAccess, "T2").WithArguments("I1.T2").WithLocation(8, 41), // (9,41): error CS0122: 'I1.T3' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T3()); Diagnostic(ErrorCode.ERR_BadAccess, "T3").WithArguments("I1.T3").WithLocation(9, 41), // (10,37): error CS0122: 'I1.T4' is inaccessible due to its protection level // System.Console.WriteLine(I1.T4.B); Diagnostic(ErrorCode.ERR_BadAccess, "T4").WithArguments("I1.T4").WithLocation(10, 37), // (11,41): error CS0122: 'I1.T5' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "T5").WithArguments("I1.T5").WithLocation(11, 41), // (11,46): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(11, 46), // (14,22): error CS0122: 'I1.T1' is inaccessible due to its protection level // class Test2 : I1.T1 Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(14, 22) }; compilation2.VerifyDiagnostics(expected); var compilation3 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); foreach (var reference in new[] { compilation3.ToMetadataReference(), compilation3.EmitToImageReference() }) { var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics(); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M1 I1+T2 I1+T3 B I1+T5", verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation5 = CreateCompilation(source2, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics(expected); } } [Fact] public void NestedTypes_05() { var source0 = @" public interface I1 { protected internal interface T1 { void M1(); } protected internal class T2 {} protected internal struct T3 {} protected internal enum T4 { B } protected internal delegate void T5(); } "; var source1 = @" class Test1 : I1 { static void Main() { I1.T1 a = new Test2(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } class Test2 : I1.T1 { public void M1() { System.Console.WriteLine(""M1""); } } } "; var source2 = @" class Test1 { static void Main() { I1.T1 a = new Test2(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } class Test2 : I1.T1 { public void M1() { System.Console.WriteLine(""M1""); } } } "; ValidateNestedTypes_01(source0 + source1, Accessibility.ProtectedOrInternal, targetFramework: TargetFramework.NetCoreApp, execute: ExecutionConditionUtil.IsMonoOrCoreClr, verify: VerifyOnMonoOrCoreClr); ValidateNestedTypes_01(source0 + source2, Accessibility.ProtectedOrInternal, targetFramework: TargetFramework.NetCoreApp, execute: ExecutionConditionUtil.IsMonoOrCoreClr, verify: VerifyOnMonoOrCoreClr); var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); for (int i = 1; i <= 5; i++) { Assert.Equal(Accessibility.ProtectedOrInternal, compilation1.GetMember("I1.T" + i).DeclaredAccessibility); } compilation1.VerifyDiagnostics( // (4,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal interface T1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T1").WithLocation(4, 34), // (9,30): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal class T2 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T2").WithLocation(9, 30), // (12,31): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal struct T3 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T3").WithLocation(12, 31), // (15,29): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal enum T4 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T4").WithLocation(15, 29), // (20,38): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal delegate void T5(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T5").WithLocation(20, 38) ); var compilation3 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); foreach (var reference in new[] { compilation3.ToMetadataReference(), compilation3.EmitToImageReference() }) { var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics(); CompileAndVerify(compilation4, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"M1 I1+T2 I1+T3 B I1+T5", verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation5 = CreateCompilation(source2, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics( // (6,12): error CS0122: 'I1.T1' is inaccessible due to its protection level // I1.T1 a = new Test2(); Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(6, 12), // (7,11): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // a.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(7, 11), // (8,41): error CS0122: 'I1.T2' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T2()); Diagnostic(ErrorCode.ERR_BadAccess, "T2").WithArguments("I1.T2").WithLocation(8, 41), // (9,41): error CS0122: 'I1.T3' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T3()); Diagnostic(ErrorCode.ERR_BadAccess, "T3").WithArguments("I1.T3").WithLocation(9, 41), // (10,37): error CS0122: 'I1.T4' is inaccessible due to its protection level // System.Console.WriteLine(I1.T4.B); Diagnostic(ErrorCode.ERR_BadAccess, "T4").WithArguments("I1.T4").WithLocation(10, 37), // (11,41): error CS0122: 'I1.T5' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "T5").WithArguments("I1.T5").WithLocation(11, 41), // (11,46): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(11, 46), // (14,22): error CS0122: 'I1.T1' is inaccessible due to its protection level // class Test2 : I1.T1 Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(14, 22) ); } } [Fact] public void NestedTypes_06() { var source1 = @" public interface I1 { internal interface T1 { void M1(); } internal class T2 {} internal struct T3 {} internal enum T4 { B } internal delegate void T5(); } "; var source2 = @" class Test1 : I1.T1 { static void Main() { I1.T1 a = new Test1(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } public void M1() { System.Console.WriteLine(""M1""); } } "; ValidateNestedTypes_01(source1 + source2, Accessibility.Internal); var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe); var expected = new[] { // (2,18): error CS0122: 'I1.T1' is inaccessible due to its protection level // class Test1 : I1.T1 Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(2, 18), // (6,12): error CS0122: 'I1.T1' is inaccessible due to its protection level // I1.T1 a = new Test1(); Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(6, 12), // (7,11): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // a.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(7, 11), // (8,41): error CS0122: 'I1.T2' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T2()); Diagnostic(ErrorCode.ERR_BadAccess, "T2").WithArguments("I1.T2").WithLocation(8, 41), // (9,41): error CS0122: 'I1.T3' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T3()); Diagnostic(ErrorCode.ERR_BadAccess, "T3").WithArguments("I1.T3").WithLocation(9, 41), // (10,37): error CS0122: 'I1.T4' is inaccessible due to its protection level // System.Console.WriteLine(I1.T4.B); Diagnostic(ErrorCode.ERR_BadAccess, "T4").WithArguments("I1.T4").WithLocation(10, 37), // (11,41): error CS0122: 'I1.T5' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "T5").WithArguments("I1.T5").WithLocation(11, 41), // (11,46): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(11, 46) }; compilation2.VerifyDiagnostics(expected); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe); compilation3.VerifyDiagnostics(expected); } [Fact] public void NestedTypes_07() { var source1 = @" public interface I1 { private interface T1 { void M1(); } private class T2 {} private struct T3 {} private enum T4 { B } private delegate void T5(); class Test1 : I1.T1 { static void Main() { I1.T1 a = new Test1(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } public void M1() { System.Console.WriteLine(""M1""); } } } "; ValidateNestedTypes_01(source1, Accessibility.Private); } [Fact] public void NestedTypes_08() { var source1 = @" public interface I1 { private interface T1 { void M1(); } private class T2 {} private struct T3 {} private enum T4 { B } } class Test1 : I1.T1 { static void Main() { I1.T1 a = new Test1(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); } public void M1() { System.Console.WriteLine(""M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (21,18): error CS0122: 'I1.T1' is inaccessible due to its protection level // class Test1 : I1.T1 Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(21, 18), // (25,12): error CS0122: 'I1.T1' is inaccessible due to its protection level // I1.T1 a = new Test1(); Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(25, 12), // (26,11): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // a.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(26, 11), // (27,41): error CS0122: 'I1.T2' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T2()); Diagnostic(ErrorCode.ERR_BadAccess, "T2").WithArguments("I1.T2").WithLocation(27, 41), // (28,41): error CS0122: 'I1.T3' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T3()); Diagnostic(ErrorCode.ERR_BadAccess, "T3").WithArguments("I1.T3").WithLocation(28, 41), // (29,37): error CS0122: 'I1.T4' is inaccessible due to its protection level // System.Console.WriteLine(I1.T4.B); Diagnostic(ErrorCode.ERR_BadAccess, "T4").WithArguments("I1.T4").WithLocation(29, 37) ); } [Fact] public void NestedTypes_09() { var source0 = @" public interface I1 { private protected interface T1 { void M1(); } private protected class T2 {} private protected struct T3 {} private protected enum T4 { B } private protected delegate void T5(); } "; var source1 = @" class Test1 : I1 { static void Main() { I1.T1 a = new Test2(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } class Test2 : I1.T1 { public void M1() { System.Console.WriteLine(""M1""); } } } "; var source2 = @" class Test1 { static void Main() { I1.T1 a = new Test2(); a.M1(); System.Console.WriteLine(new I1.T2()); System.Console.WriteLine(new I1.T3()); System.Console.WriteLine(I1.T4.B); System.Console.WriteLine(new I1.T5(a.M1)); } class Test2 : I1.T1 { public void M1() { System.Console.WriteLine(""M1""); } } } "; ValidateNestedTypes_01(source0 + source1, Accessibility.ProtectedAndInternal, targetFramework: TargetFramework.NetCoreApp, execute: ExecutionConditionUtil.IsMonoOrCoreClr, verify: VerifyOnMonoOrCoreClr_FailsIlVerify); var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Mscorlib461Extended); for (int i = 1; i <= 5; i++) { Assert.Equal(Accessibility.ProtectedAndInternal, compilation1.GetMember("I1.T" + i).DeclaredAccessibility); } compilation1.VerifyDiagnostics( // (4,33): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected interface T1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T1").WithLocation(4, 33), // (9,29): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected class T2 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T2").WithLocation(9, 29), // (12,30): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected struct T3 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T3").WithLocation(12, 30), // (15,28): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected enum T4 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T4").WithLocation(15, 28), // (20,37): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected delegate void T5(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "T5").WithLocation(20, 37) ); var compilation2 = CreateCompilation(source2 + source0, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); var expected = new DiagnosticDescription[] { // (6,12): error CS0122: 'I1.T1' is inaccessible due to its protection level // I1.T1 a = new Test2(); Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(6, 12), // (7,11): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // a.M1(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(7, 11), // (8,41): error CS0122: 'I1.T2' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T2()); Diagnostic(ErrorCode.ERR_BadAccess, "T2").WithArguments("I1.T2").WithLocation(8, 41), // (9,41): error CS0122: 'I1.T3' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T3()); Diagnostic(ErrorCode.ERR_BadAccess, "T3").WithArguments("I1.T3").WithLocation(9, 41), // (10,37): error CS0122: 'I1.T4' is inaccessible due to its protection level // System.Console.WriteLine(I1.T4.B); Diagnostic(ErrorCode.ERR_BadAccess, "T4").WithArguments("I1.T4").WithLocation(10, 37), // (11,41): error CS0122: 'I1.T5' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "T5").WithArguments("I1.T5").WithLocation(11, 41), // (11,46): error CS0122: 'I1.T1.M1()' is inaccessible due to its protection level // System.Console.WriteLine(new I1.T5(a.M1)); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I1.T1.M1()").WithLocation(11, 46), // (14,22): error CS0122: 'I1.T1' is inaccessible due to its protection level // class Test2 : I1.T1 Diagnostic(ErrorCode.ERR_BadAccess, "T1").WithArguments("I1.T1").WithLocation(14, 22) }; compilation2.VerifyDiagnostics(expected); var compilation3 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); foreach (var reference in new[] { compilation3.ToMetadataReference(), compilation3.EmitToImageReference() }) { var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics(expected); var compilation5 = CreateCompilation(source2, options: TestOptions.DebugExe, references: new[] { reference }, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics(expected); } } [Fact] [WorkItem(34704, "https://github.com/dotnet/roslyn/issues/34704")] public void NestedTypes_10() { var source1 = @" interface I1 { protected interface I2 { } } class C1 { protected interface I2 { } } interface I3 : I1, I1.I2 { private void M1(I1.I2 x) { } } interface I4 : I1, I2 { I2 MI4(); } interface I5 : I1.I2, I1 { private void M1(I1.I2 x) { } } interface I6 : I2, I1 { I2 MI6(); } class C3 : I1, I1.I2 { private void M1(I1.I2 x) { } } class C4 : I1, I2 { void MC4(I2 x) { } } class C5 : I1.I2, I1 { private void M1(I1.I2 x) { } } class C6 : I2, I1 { void MC6(I2 x) { } } class C33 : C1, C1.I2 { protected void M1(C1.I2 x) { } } class C44 : C1, I2 { void M1(I2 x) { } } interface I7 : I8 { public interface I8 : I7 { } } class C7 : I8 { public interface I8 { } } interface I9 : I9.I10 { public interface I10 : I9 { } } interface I11 { public interface I12 : I13 { } public interface I13 { } public interface I14 : I11.I13 { } } class C11 { public interface I12 : I13 { } public interface I13 { } public interface I14 : I11.I13 { } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (16,23): error CS0122: 'I1.I2' is inaccessible due to its protection level // interface I3 : I1, I1.I2 Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1.I2").WithLocation(16, 23), // (21,20): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // interface I4 : I1, I2 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(21, 20), // (23,8): error CS0050: Inconsistent accessibility: return type 'I1.I2' is less accessible than method 'I4.MI4()' // I2 MI4(); Diagnostic(ErrorCode.ERR_BadVisReturnType, "MI4").WithArguments("I4.MI4()", "I1.I2").WithLocation(23, 8), // (26,19): error CS0122: 'I1.I2' is inaccessible due to its protection level // interface I5 : I1.I2, I1 Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1.I2").WithLocation(26, 19), // (31,16): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // interface I6 : I2, I1 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(31, 16), // (33,8): error CS0050: Inconsistent accessibility: return type 'I1.I2' is less accessible than method 'I6.MI6()' // I2 MI6(); Diagnostic(ErrorCode.ERR_BadVisReturnType, "MI6").WithArguments("I6.MI6()", "I1.I2").WithLocation(33, 8), // (36,19): error CS0122: 'I1.I2' is inaccessible due to its protection level // class C3 : I1, I1.I2 Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1.I2").WithLocation(36, 19), // (41,16): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // class C4 : I1, I2 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(41, 16), // (43,14): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // void MC4(I2 x) { } Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(43, 14), // (46,15): error CS0122: 'I1.I2' is inaccessible due to its protection level // class C5 : I1.I2, I1 Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("I1.I2").WithLocation(46, 15), // (51,12): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // class C6 : I2, I1 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(51, 12), // (53,14): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // void MC6(I2 x) { } Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(53, 14), // (56,20): error CS0122: 'C1.I2' is inaccessible due to its protection level // class C33 : C1, C1.I2 Diagnostic(ErrorCode.ERR_BadAccess, "I2").WithArguments("C1.I2").WithLocation(56, 20), // (61,17): error CS0246: The type or namespace name 'I2' could not be found (are you missing a using directive or an assembly reference?) // class C44 : C1, I2 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I2").WithArguments("I2").WithLocation(61, 17), // (66,16): error CS0246: The type or namespace name 'I8' could not be found (are you missing a using directive or an assembly reference?) // interface I7 : I8 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I8").WithArguments("I8").WithLocation(66, 16), // (73,12): error CS0246: The type or namespace name 'I8' could not be found (are you missing a using directive or an assembly reference?) // class C7 : I8 Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "I8").WithArguments("I8").WithLocation(73, 12), // (80,11): error CS0529: Inherited interface 'I9.I10' causes a cycle in the interface hierarchy of 'I9' // interface I9 : I9.I10 Diagnostic(ErrorCode.ERR_CycleInInterfaceInheritance, "I9").WithArguments("I9", "I9.I10").WithLocation(80, 11), // (82,22): error CS0529: Inherited interface 'I9' causes a cycle in the interface hierarchy of 'I9.I10' // public interface I10 : I9 Diagnostic(ErrorCode.ERR_CycleInInterfaceInheritance, "I10").WithArguments("I9.I10", "I9").WithLocation(82, 22) ); } [Fact] [WorkItem(38735, "https://github.com/dotnet/roslyn/issues/38735")] public void NestedTypes_52() { var source1 = @" interface I1 : IA<int>.NF { } interface IQ<T> { } interface IA<T> : IB<IQ<T>> { } interface IB<T> : IA<IQ<T>> { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (2,24): error CS0426: The type name 'NF' does not exist in the type 'IA<int>' // interface I1 : IA<int>.NF { } Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "NF").WithArguments("NF", "IA<int>").WithLocation(2, 24), // (6,11): error CS0529: Inherited interface 'IB<IQ<T>>' causes a cycle in the interface hierarchy of 'IA<T>' // interface IA<T> : IB<IQ<T>> { } Diagnostic(ErrorCode.ERR_CycleInInterfaceInheritance, "IA").WithArguments("IA<T>", "IB<IQ<T>>").WithLocation(6, 11), // (8,11): error CS0529: Inherited interface 'IA<IQ<T>>' causes a cycle in the interface hierarchy of 'IB<T>' // interface IB<T> : IA<IQ<T>> { } Diagnostic(ErrorCode.ERR_CycleInInterfaceInheritance, "IB").WithArguments("IB<T>", "IA<IQ<T>>").WithLocation(8, 11) ); } [Fact] [WorkItem(58424, "https://github.com/dotnet/roslyn/issues/58424")] public void NestedTypes_53() { var source1 = @" public class Test : Test.IInner.IOuter { public interface IInner : Other { public interface IOuter { } } } public interface Other { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); } [Fact] [WorkItem(58424, "https://github.com/dotnet/roslyn/issues/58424")] public void NestedTypes_54() { var source1 = @" public class Test : Test.IInner.IOuter { public interface IInner : Other { } } public interface Other { public interface IOuter { } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (2,33): error CS0426: The type name 'IOuter' does not exist in the type 'Test.IInner' // public class Test : Test.IInner.IOuter Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "IOuter").WithArguments("IOuter", "Test.IInner").WithLocation(2, 33), // (4,31): error CS0146: Circular base type dependency involving 'Test' and 'Test.IInner' // public interface IInner : Other Diagnostic(ErrorCode.ERR_CircularBase, "Other").WithArguments("Test", "Test.IInner").WithLocation(4, 31) ); } [Fact] [WorkItem(58424, "https://github.com/dotnet/roslyn/issues/58424")] [WorkItem(62795, "https://github.com/dotnet/roslyn/issues/62795")] public void NestedTypes_55() { var source1 = @" namespace Ns0 { public class Test : Test.IInner.IOuter { public interface IInner : global::Ns0.Other { new public interface IOuter { } } } public interface Other { public interface IOuter { void M1(); } } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); } [Theory] [CombinatorialData] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void MethodImplementationInDerived_01(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I4 { " + modifiers + @"void M1(); } public interface I5 : I4 { } public interface I1 : I2, I5 { " + implModifiers + @"void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"void I4.M1() { System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source2 = @" class Test1 : I1 { "; if (!isStatic) { source2 += @" static void Main() { I2 i2 = new Test1(); I4 i4 = new Test1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source2 += @" i2.M1(); i4.M1(); } } "; ValidateMethodImplementationInDerived_01(source1, source2, isStatic); } private void ValidateMethodImplementationInDerived_01(string source1, string source2, bool isStatic, string name = "M1") { var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateMethodImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); void validateMethodImplementationInDerived_01(ModuleSymbol m) { ValidateMethodImplementationInDerived_01(m, i4M1IsAbstract: false, isStatic: isStatic, name: name); } } private static void ValidateMethodImplementationInDerived_01(ModuleSymbol m, bool isStatic) { ValidateMethodImplementationInDerived_01(m, i4M1IsAbstract: false, isStatic: isStatic); } private static void ValidateMethodImplementationInDerived_01(ModuleSymbol m, bool i4M1IsAbstract, bool isStatic, string name = "M1") { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var i1i2m1 = i1.GetMember<MethodSymbol>(i1.OriginalDefinition.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I2").Single().ToDisplayString() + "." + name); var i1i4m1 = i1.GetMember<MethodSymbol>(i1.OriginalDefinition.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I4").Single().ToDisplayString() + "." + name); var i2 = i1.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I2").Single(); var i2m1 = i2.GetMember<MethodSymbol>(name); var i4 = i1.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I4").Single(); var i4m1 = i4.GetMember<MethodSymbol>(name); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); ValidateExplicitImplementation(i1i2m1, isStatic: isStatic); ValidateExplicitImplementation(i1i4m1, i4M1IsAbstract, isStatic: isStatic); Assert.Null(test1.FindImplementationForInterfaceMember(i1i2m1)); Assert.Null(test1.FindImplementationForInterfaceMember(i1i4m1)); Assert.Equal(i1i2m1, test1.FindImplementationForInterfaceMember(i2m1)); Assert.Equal(i4M1IsAbstract ? null : i1i4m1, test1.FindImplementationForInterfaceMember(i4m1)); Assert.Null(i1.FindImplementationForInterfaceMember(i1i2m1)); Assert.Null(i1.FindImplementationForInterfaceMember(i1i4m1)); Assert.Equal(i1i2m1, i1.FindImplementationForInterfaceMember(i2m1)); Assert.Equal(i4M1IsAbstract ? null : i1i4m1, i1.FindImplementationForInterfaceMember(i4m1)); Assert.Null(i2.FindImplementationForInterfaceMember(i2m1)); Assert.Null(i4.FindImplementationForInterfaceMember(i4m1)); var i3 = i1.ContainingNamespace.GetTypeMember("I3"); i1 = i3.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); i1i2m1 = i1.GetMember<MethodSymbol>(i1.OriginalDefinition.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I2").Single().ToDisplayString() + "." + name); i1i4m1 = i1.GetMember<MethodSymbol>(i1.OriginalDefinition.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I4").Single().ToDisplayString() + "." + name); i2 = i1.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I2").Single(); i2m1 = i2.GetMember<MethodSymbol>(name); i4 = i1.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I4").Single(); i4m1 = i4.GetMember<MethodSymbol>(name); Assert.Equal(i1i2m1, i3.FindImplementationForInterfaceMember(i2m1)); Assert.Equal(i4M1IsAbstract ? null : i1i4m1, i3.FindImplementationForInterfaceMember(i4m1)); } private static void ValidateExplicitImplementation(MethodSymbol m1, bool isAbstract = false, bool isStatic = false) { Assert.Equal(isAbstract || !isStatic, m1.IsMetadataVirtual()); Assert.Equal(isAbstract || !isStatic, m1.IsMetadataFinal); Assert.False(m1.IsMetadataNewSlot()); Assert.Equal(isAbstract, m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.Equal(isAbstract, m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); if (m1.ContainingModule is PEModuleSymbol peModule) { int rva; peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)m1.OriginalDefinition).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } } [Fact] public void MethodImplementationInDerived_02() { var source1 = @" public interface I2 { void M1(); } public interface I4 { void M1(); } public interface I1 : I2, I4 { void I2.M1() { System.Console.WriteLine(""I2.M1""); } void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,13): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // void I2.M1() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M1").WithArguments("default interface implementation", "8.0").WithLocation(14, 13), // (18,13): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // void I4.M1() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M1").WithArguments("default interface implementation", "8.0").WithLocation(18, 13) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, isStatic: false); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (6,15): error CS8506: 'I1.I2.M1()' cannot implement interface member 'I2.M1()' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1()", "I2.M1()", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15), // (6,15): error CS8506: 'I1.I4.M1()' cannot implement interface member 'I4.M1()' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1()", "I4.M1()", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15) ); ValidateMethodImplementationInDerived_01(compilation2.SourceModule, isStatic: false); } [Fact] public void MethodImplementationInDerived_Static_02() { var source1 = @" public interface I2 { static abstract void M1(); } public interface I4 { static abstract void M1(); } public interface I1 : I2, I4 { static void I2.M1() { System.Console.WriteLine(""I2.M1""); } static void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular10, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,26): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(4, 26), // (9,26): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(9, 26), // (14,20): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static void I2.M1() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(14, 20), // (18,20): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static void I4.M1() Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(18, 20) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, isStatic: true); CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60).VerifyEmitDiagnostics(); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular10, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (6,15): error CS8706: 'I1.I2.M1()' cannot implement interface member 'I2.M1()' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1()", "I2.M1()", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15), // (6,15): error CS8706: 'I1.I4.M1()' cannot implement interface member 'I4.M1()' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1()", "I4.M1()", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15) ); ValidateMethodImplementationInDerived_01(compilation2.SourceModule, isStatic: true); CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60).VerifyEmitDiagnostics(); } [Fact] public void MethodImplementationInDerived_03() { var source1 = @" public interface I2 { void M1(); } public interface I4 { void M1(); } public interface I1 : I2, I4 { void I2.M1() { System.Console.WriteLine(""I2.M1""); } void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular, skipUsesIsNullable: true); Assert.False(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,13): error CS8501: Target runtime doesn't support default interface implementation. // void I2.M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(14, 13), // (18,13): error CS8501: Target runtime doesn't support default interface implementation. // void I4.M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(18, 13) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, isStatic: false); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (6,15): error CS8502: 'I1.I2.M1()' cannot implement interface member 'I2.M1()' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1()", "I2.M1()", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I4.M1()' cannot implement interface member 'I4.M1()' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1()", "I4.M1()", "Test1").WithLocation(6, 15) ); } [Fact] public void MethodImplementationInDerived_Static_03() { var source1 = @" public interface I2 { static abstract void M1(); } public interface I4 { static abstract void M1(); } public interface I1 : I2, I4 { static void I2.M1() { System.Console.WriteLine(""I2.M1""); } static void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); compilation1.VerifyDiagnostics( // (4,26): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract void M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(4, 26), // (9,26): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract void M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(9, 26), // (14,20): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static void I2.M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(14, 20), // (18,20): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static void I4.M1() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(18, 20) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, isStatic: true); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.RegularPreview); compilation2.VerifyDiagnostics( // (6,15): error CS8929: 'I1.I2.M1()' cannot implement interface member 'I2.M1()' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I2.M1()", "I2.M1()", "Test1").WithLocation(6, 15), // (6,15): error CS8929: 'I1.I4.M1()' cannot implement interface member 'I4.M1()' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I4.M1()", "I4.M1()", "Test1").WithLocation(6, 15) ); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_04(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I4 { " + modifiers + @"void M1(); } public interface I1 : I2, I4 { " + implModifiers + @"void I2.M1(); " + implModifiers + @"void I4.M1(); } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (15,13): error CS0501: 'I1.I4.M1()' must declare a body because it is not marked abstract, extern, or partial // void I4.M1(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M1").WithArguments("I1.I4.M1()").WithLocation(15, 13 + implModifiers.Length), // (14,13): error CS0501: 'I1.I2.M1()' must declare a body because it is not marked abstract, extern, or partial // void I2.M1(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "M1").WithArguments("I1.I2.M1()").WithLocation(14, 13 + implModifiers.Length) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, isStatic: isStatic); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_05(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I4 { " + modifiers + @"void M1(); } public interface I1 { " + implModifiers + @"void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"void I4.M1() { System.Console.WriteLine(""I2.M1""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (18,10): error CS0540: 'I1.I4.M1()': containing type does not implement interface 'I4' // void I4.M1() Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I4").WithArguments("I1.I4.M1()", "I4").WithLocation(18, 10 + implModifiers.Length), // (14,10): error CS0540: 'I1.I2.M1()': containing type does not implement interface 'I2' // void I2.M1() Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I2").WithArguments("I1.I2.M1()", "I2").WithLocation(14, 10 + implModifiers.Length) ); } [Fact] public void MethodImplementationInDerived_06() { var source1 = @" public interface I2 { void M1(); } public interface I4 { void M1(); } public interface I1 : I2, I4 { public static void I2.M1() { System.Console.WriteLine(""I2.M1""); } internal virtual void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,27): error CS0106: The modifier 'public' is not valid for this item // public static void I2.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("public").WithLocation(14, 27), // (14,27): error CS0539: 'I1.M1()' in explicit interface declaration is not found among members of the interface that can be implemented // public static void I2.M1() Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.M1()").WithLocation(14, 27), // (18,30): error CS0106: The modifier 'internal' is not valid for this item // internal virtual void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("internal").WithLocation(18, 30), // (18,30): error CS0106: The modifier 'virtual' is not valid for this item // internal virtual void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("virtual").WithLocation(18, 30), // (28,15): error CS0535: 'Test1' does not implement interface member 'I2.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I2.M1()").WithLocation(28, 15) ); } [Fact] public void MethodImplementationInDerived_Static_06() { var source1 = @" public interface I2 { static abstract void M1(); } public interface I4 { static abstract void M1(); } public interface I1 : I2, I4 { public void I2.M1() { System.Console.WriteLine(""I2.M1""); } internal virtual static void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,20): error CS0106: The modifier 'public' is not valid for this item // public void I2.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("public").WithLocation(14, 20), // (14,20): error CS0539: 'I1.M1()' in explicit interface declaration is not found among members of the interface that can be implemented // public void I2.M1() Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.M1()").WithLocation(14, 20), // (18,37): error CS0106: The modifier 'internal' is not valid for this item // internal virtual static void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("internal").WithLocation(18, 37), // (18,37): error CS0106: The modifier 'virtual' is not valid for this item // internal virtual static void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("virtual").WithLocation(18, 37), // (28,15): error CS0535: 'Test1' does not implement interface member 'I2.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I2.M1()").WithLocation(28, 15) ); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_07(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I4 { " + modifiers + @"void M1(); } public interface I1 : I2, I4 { " + implModifiers + @"private sealed void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"protected abstract void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,28): error CS0106: The modifier 'sealed' is not valid for this item // private sealed void I2.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("sealed").WithLocation(14, 28 + implModifiers.Length), // (14,28): error CS0106: The modifier 'private' is not valid for this item // private sealed void I2.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private").WithLocation(14, 28 + implModifiers.Length), // (18,32): error CS0106: The modifier 'protected' is not valid for this item // protected abstract void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected").WithLocation(18, 32 + implModifiers.Length), // (18,32): error CS0500: 'I1.I4.M1()' cannot declare a body because it is marked abstract // protected abstract void I4.M1() Diagnostic(ErrorCode.ERR_AbstractHasBody, "M1").WithArguments("I1.I4.M1()").WithLocation(18, 32 + implModifiers.Length), // (28,15): error CS0535: 'Test1' does not implement interface member 'I4.M1()' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I4.M1()").WithLocation(28, 15) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, i4M1IsAbstract: true, isStatic: isStatic); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_08(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I4 { " + modifiers + @"void M1(); } public interface I1 : I2, I4 { " + implModifiers + @"private protected void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"internal protected override void I4.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,31): error CS0106: The modifier 'private protected' is not valid for this item // private protected void I2.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private protected").WithLocation(14, 31 + implModifiers.Length), // (18,41): error CS0106: The modifier 'protected internal' is not valid for this item // internal protected override void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected internal").WithLocation(18, 41 + implModifiers.Length), // (18,41): error CS0106: The modifier 'override' is not valid for this item // internal protected override void I4.M1() Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("override").WithLocation(18, 41 + implModifiers.Length) ); ValidateMethodImplementationInDerived_01(compilation1.SourceModule, isStatic: isStatic); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_09(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I1 : I2 { " + implModifiers + @"extern void I2.M1(); } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (9,20): warning CS0626: Method, operator, or accessor 'I1.I2.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void I2.M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.I2.M1()").WithLocation(9, 20 + implModifiers.Length) ); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var i1i2m1 = i1.GetMember<MethodSymbol>("I2.M1"); var i2 = i1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I2").Single(); var i2m1 = i2.GetMembers().OfType<MethodSymbol>().Single(); var i3 = i1.ContainingNamespace.GetTypeMember("I3"); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); ValidateExplicitExternImplementation(i1i2m1, isStatic: isStatic); Assert.Null(test1.FindImplementationForInterfaceMember(i1i2m1)); Assert.Same(i1i2m1, test1.FindImplementationForInterfaceMember(i2m1)); Assert.Null(i1.FindImplementationForInterfaceMember(i1i2m1)); Assert.Same(i1i2m1, i1.FindImplementationForInterfaceMember(i2m1)); Assert.Null(i2.FindImplementationForInterfaceMember(i2m1)); Assert.Same(i1i2m1, i3.FindImplementationForInterfaceMember(i2m1)); } CompileAndVerify(compilation1, verify: Verify(isStatic), symbolValidator: Validate1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); if (!isStatic) { compilation2.VerifyDiagnostics( // (9,20): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern void I2.M1(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "M1").WithArguments("default interface implementation", "8.0").WithLocation(9, 20), // (9,20): warning CS0626: Method, operator, or accessor 'I1.I2.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void I2.M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.I2.M1()").WithLocation(9, 20) ); } else { compilation2.VerifyDiagnostics( // (4,26): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract void M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(4, 26), // (9,27): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static extern void I2.M1(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(9, 27), // (9,27): warning CS0626: Method, operator, or accessor 'I1.I2.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern void I2.M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.I2.M1()").WithLocation(9, 27) ); } Validate1(compilation2.SourceModule); var compilation3 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); if (!isStatic) { compilation3.VerifyDiagnostics( // (9,20): error CS8501: Target runtime doesn't support default interface implementation. // extern void I2.M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "M1").WithLocation(9, 20), // (9,20): warning CS0626: Method, operator, or accessor 'I1.I2.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern void I2.M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.I2.M1()").WithLocation(9, 20) ); } else { compilation3.VerifyDiagnostics( // (4,26): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract void M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(4, 26), // (9,27): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static extern void I2.M1(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(9, 27), // (9,27): warning CS0626: Method, operator, or accessor 'I1.I2.M1()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern void I2.M1(); Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "M1").WithArguments("I1.I2.M1()").WithLocation(9, 27) ); } Validate1(compilation3.SourceModule); var source2 = @" public interface I2 { " + modifiers + @"void M1(); } public interface I1 : I2 { " + implModifiers + @"extern void I2.M1() {} } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation4 = CreateCompilation(source2, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics( // (9,20): error CS0179: 'I1.I2.M1()' cannot be extern and declare a body // extern void I2.M1() Diagnostic(ErrorCode.ERR_ExternHasBody, "M1").WithArguments("I1.I2.M1()").WithLocation(9, 20 + implModifiers.Length) ); Validate1(compilation4.SourceModule); } private static void ValidateExplicitExternImplementation(MethodSymbol m1, bool isStatic = false) { Assert.Equal(!isStatic, m1.IsMetadataVirtual()); Assert.Equal(!isStatic, m1.IsMetadataFinal); Assert.False(m1.IsMetadataNewSlot()); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.NotEqual(m1.OriginalDefinition is PEMethodSymbol, m1.IsExtern); Assert.False(m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); if (m1.ContainingModule is PEModuleSymbol peModule) { int rva; peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)m1).Handle, out _, out _, out _, out rva); Assert.Equal(0, rva); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_10(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" using System.Threading.Tasks; public interface I2 { " + modifiers + @"Task M1(); } public interface I1 : I2 { " + implModifiers + @"async Task I2.M1() { await Task.Factory.StartNew(() => System.Console.WriteLine(""I2.M1"")); } } public interface I3 : I1 { } class Test1 : I1 { "; if (!isStatic) { source1 += @" static void Main() { I2 i2 = new Test1(); "; } else { source1 += @" static void Main() { Test<Test1>(); } static void Test<i2>() where i2 : I2 { "; } source1 += @" i2.M1().Wait(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var i1i2m1 = i1.GetMember<MethodSymbol>("I2.M1"); var i2 = i1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I2").Single(); var i2m1 = i2.GetMembers().OfType<MethodSymbol>().Single(); var i3 = i1.ContainingNamespace.GetTypeMember("I3"); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); Validate2(i1i2m1); Assert.Null(test1.FindImplementationForInterfaceMember(i1i2m1)); Assert.Equal("System.Threading.Tasks.Task I1.I2.M1()", test1.FindImplementationForInterfaceMember(i2m1).ToTestDisplayString()); Assert.Null(i1.FindImplementationForInterfaceMember(i1i2m1)); Assert.Equal("System.Threading.Tasks.Task I1.I2.M1()", i1.FindImplementationForInterfaceMember(i2m1).ToTestDisplayString()); Assert.Null(i2.FindImplementationForInterfaceMember(i2m1)); Assert.Equal("System.Threading.Tasks.Task I1.I2.M1()", i3.FindImplementationForInterfaceMember(i2m1).ToTestDisplayString()); } void Validate2(MethodSymbol m1) { Assert.Equal(!isStatic, m1.IsMetadataVirtual()); Assert.Equal(!isStatic, m1.IsMetadataFinal); Assert.False(m1.IsMetadataNewSlot()); Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.False(m1.IsExtern); Assert.NotEqual(m1 is PEMethodSymbol, m1.IsAsync); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); if (m1.ContainingModule is PEModuleSymbol peModule) { int rva; peModule.Module.GetMethodDefPropsOrThrow(((PEMethodSymbol)m1).Handle, out _, out _, out _, out rva); Assert.NotEqual(0, rva); } } CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : "I2.M1", verify: Verify(isStatic), symbolValidator: Validate1); } [Theory] [CombinatorialData] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void MethodImplementationInDerived_11(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"internal void M1(); } public interface I4 { " + modifiers + @"internal void M1(); } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source1 += @" i2.M1(); i4.M1(); } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"void I4.M1() { System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { TestHelper.Test(new Test1(), new Test1()); "; } else { source3 += @" static void Main() { TestHelper.Test<Test1, Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateMethodImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); var compilation2 = CreateCompilation(source3, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); var compilation3 = CreateCompilation(source3, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); var compilation5 = CreateCompilation(source2 + source3, new[] { compilation4.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics( // (8,13): error CS0122: 'I4.M1()' is inaccessible due to its protection level // void I4.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I4.M1()").WithLocation(8, 13 + implModifiers.Length), // (4,13): error CS0122: 'I2.M1()' is inaccessible due to its protection level // void I2.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1()").WithLocation(4, 13 + implModifiers.Length) ); var compilation6 = CreateCompilation(source2 + source3, new[] { compilation4.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation6.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation6.SourceModule); compilation6.VerifyDiagnostics( // (8,13): error CS0122: 'I4.M1()' is inaccessible due to its protection level // void I4.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I4.M1()").WithLocation(8, 13 + implModifiers.Length), // (4,13): error CS0122: 'I2.M1()' is inaccessible due to its protection level // void I2.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1()").WithLocation(4, 13 + implModifiers.Length) ); void validateMethodImplementationInDerived_01(ModuleSymbol m) { ValidateMethodImplementationInDerived_01(m, isStatic: isStatic); } } [Theory] [CombinatorialData] [WorkItem(20083, "https://github.com/dotnet/roslyn/issues/20083")] public void MethodImplementationInDerived_12(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"void M1(){ System.Console.WriteLine(""Unexpected!!!""); } } public interface I2 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""I2.I1.M1""); } } public interface I3 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""I3.I1.M1""); } } public interface I4 : I1 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""I4.I1.M1""); } } public interface I5 : I2, I3 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""I5.I1.M1""); } } public interface I6 : I1, I2, I3, I5 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = i1.GetMember<MethodSymbol>("M1"); var i2 = FindType(m, "I2"); var i2m1 = i2.GetMember<MethodSymbol>("I1.M1"); var i5 = FindType(m, "I5"); var i5m1 = i5.GetMember<MethodSymbol>("I1.M1"); var i6 = FindType(m, "I6"); ValidateExplicitImplementation(i2m1, isStatic: isStatic); ValidateExplicitImplementation(i5m1, isStatic: isStatic); Assert.Same(i1m1, i1.FindImplementationForInterfaceMember(i1m1)); Assert.Same(i2m1, i2.FindImplementationForInterfaceMember(i1m1)); Assert.Same(i5m1, i5.FindImplementationForInterfaceMember(i1m1)); Assert.Same(i5m1, i6.FindImplementationForInterfaceMember(i1m1)); } CompileAndVerify(compilation1, verify: Verify(isStatic), symbolValidator: Validate1); var refs1 = new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }; var source2 = @" public interface I7 : I2, I3 {} public interface I8 : I1, I2, I3, I5, I4 {} "; var source3 = @" class Test1 : I2, I3 {} class Test2 : I7 {} class Test3 : I1, I2, I3, I4 {} class Test4 : I1, I2, I3, I5, I4 {} class Test5 : I8 {} "; var source4 = @" class Test5 : I2 {} class Test6 : I1, I2, I3, I5 {} class Test7 : I6 { "; if (!isStatic) { source4 += @" static void Main() { I1 i5 = new Test5(); I1 i6 = new Test6(); I1 i7 = new Test7(); "; } else { source4 += @" static void Main() { Test<Test5, Test6, Test7>(); } static void Test<i5, i6, i7>() where i5 : I1 where i6 : I1 where i7 : I1 { "; } source4 += @" i5.M1(); i6.M1(); i7.M1(); } } "; var source5 = @" class Test8 : I2, I3 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test8.I1.M1""); } "; if (!isStatic) { source5 += @" static void Main() { I1 i8 = new Test8(); I1 i9 = new Test9(); I1 i10 = new Test10(); I1 i11 = new Test11(); I1 i12 = new Test12(); "; } else { source5 += @" static void Main() { Test<Test8, Test9, Test10, Test11, Test12>(); } static void Test<i8, i9, i10, i11, i12>() where i8 : I1 where i9 : I1 where i10 : I1 where i11 : I1 where i12 : I1 { "; } source5 += @" i8.M1(); i9.M1(); i10.M1(); i11.M1(); i12.M1(); } } class Test9 : I7 { " + implModifiers + @"void I1.M1() { System.Console.WriteLine(""Test9.I1.M1""); } } class Test10 : I1, I2, I3, I4 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test10.M1""); } } class Test11 : I1, I2, I3, I5, I4 { " + implModifiers + @"public void M1() { System.Console.WriteLine(""Test11.M1""); } } class Test12 : I8 { " + implModifiers + @"public " + (isStatic ? "" : "virtual") + @" void M1() { System.Console.WriteLine(""Test12.M1""); } } "; foreach (var ref1 in refs1) { var compilation2 = CreateCompilation(source2, new[] { ref1 }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); // According to LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-06-14.md, // we do not require interfaces to have a most specific implementation of all members. Therefore, there are no // errors in this compilation. compilation2.VerifyDiagnostics(); Validate2(compilation2.SourceModule); void Validate2(ModuleSymbol m) { Validate1(m); var i1 = FindType(m, "I1"); var i1m1 = i1.GetMember<MethodSymbol>("M1"); var i7 = FindType(m, "I7"); var i8 = FindType(m, "I8"); Assert.Null(i7.FindImplementationForInterfaceMember(i1m1)); Assert.Null(i8.FindImplementationForInterfaceMember(i1m1)); } CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: Validate2); compilation2 = CreateCompilation(source2, new[] { ref1 }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); Validate2(compilation2.SourceModule); CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: Validate2); var refs2 = new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }; var compilation4 = CreateCompilation(source4, new[] { ref1 }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); Validate4(compilation4.SourceModule); void Validate4(ModuleSymbol m) { Validate1(m); var i1 = FindType(m, "I1"); var i1m1 = i1.GetMember<MethodSymbol>("M1"); var i2 = FindType(m, "I2"); var i2m1 = i2.GetMember<MethodSymbol>("I1.M1"); var i5 = FindType(m, "I5"); var i5m1 = i5.GetMember<MethodSymbol>("I1.M1"); var test5 = FindType(m, "Test5"); var test6 = FindType(m, "Test6"); var test7 = FindType(m, "Test7"); Assert.Same(i2m1, test5.FindImplementationForInterfaceMember(i1m1)); Assert.Same(i5m1, test6.FindImplementationForInterfaceMember(i1m1)); Assert.Same(i5m1, test7.FindImplementationForInterfaceMember(i1m1)); } CompileAndVerify(compilation4, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.I1.M1 I5.I1.M1 I5.I1.M1 " , verify: Verify(isStatic), symbolValidator: Validate4); foreach (var ref2 in refs2) { var compilation3 = CreateCompilation(source3, new[] { ref1, ref2 }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(2, 15), // (5,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific. // class Test2 : I7 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I7").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(5, 15), // (8,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific. // class Test3 : I1, I2, I3, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(8, 15), // (11,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I5.I1.M1()', nor 'I4.I1.M1()' are most specific. // class Test4 : I1, I2, I3, I5, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.M1()", "I5.I1.M1()", "I4.I1.M1()").WithLocation(11, 15), // (14,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I5.I1.M1()', nor 'I4.I1.M1()' are most specific. // class Test5 : I8 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I8").WithArguments("I1.M1()", "I5.I1.M1()", "I4.I1.M1()").WithLocation(14, 15) ); Validate3(compilation3.SourceModule); void Validate3(ModuleSymbol m) { Validate1(m); Validate2(m); var i1 = FindType(m, "I1"); var i1m1 = i1.GetMember<MethodSymbol>("M1"); var test1 = FindType(m, "Test1"); var test2 = FindType(m, "Test2"); var test3 = FindType(m, "Test3"); var test4 = FindType(m, "Test4"); var test5 = FindType(m, "Test5"); Assert.Null(test1.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test2.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test3.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test4.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test5.FindImplementationForInterfaceMember(i1m1)); } var compilation5 = CreateCompilation(source5, new[] { ref1, ref2 }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics(); Validate5(compilation5.SourceModule); void Validate5(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = i1.GetMember<MethodSymbol>("M1"); var test8 = FindType(m, "Test8"); var test9 = FindType(m, "Test9"); var test10 = FindType(m, "Test10"); var test11 = FindType(m, "Test11"); var test12 = FindType(m, "Test12"); Assert.Same(test8.GetMember<MethodSymbol>("I1.M1"), test8.FindImplementationForInterfaceMember(i1m1)); Assert.Same(test9.GetMember<MethodSymbol>("I1.M1"), test9.FindImplementationForInterfaceMember(i1m1)); Assert.Same(test10.GetMember<MethodSymbol>("M1"), test10.FindImplementationForInterfaceMember(i1m1)); Assert.Same(test11.GetMember<MethodSymbol>("M1"), test11.FindImplementationForInterfaceMember(i1m1)); Assert.Same(test12.GetMember<MethodSymbol>("M1"), test12.FindImplementationForInterfaceMember(i1m1)); } CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"Test8.I1.M1 Test9.I1.M1 Test10.M1 Test11.M1 Test12.M1 ", verify: Verify(isStatic), symbolValidator: Validate5); } } } private static NamedTypeSymbol FindType(ModuleSymbol m, string name) { var result = m.GlobalNamespace.GetMember<NamedTypeSymbol>(name); if ((object)result != null) { return result; } foreach (var assembly in m.ReferencedAssemblySymbols) { result = assembly.Modules[0].GlobalNamespace.GetMember<NamedTypeSymbol>(name); if ((object)result != null) { return result; } } Assert.NotNull(result); return result; } [Theory] [CombinatorialData] public void MethodImplementationInDerived_13(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"void M1(); } public interface I2 : I1 { " + implModifiers + @"void I1.M1() { } } public interface I3 : I1 { " + implModifiers + @"void I1.M1() { } } "; var source2 = @" class Test1 : I2, I3 { " + implModifiers + @"public int M1() => 1; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (2,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implement 'I1.M1()' because it does not have the matching return type of 'void'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.M1()", "Test1.M1()", "void").WithLocation(2, 15) ); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8505: Interface member 'I1.M1()' does not have a most specific implementation. Neither 'I2.I1.M1()', nor 'I3.I1.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1()", "I2.I1.M1()", "I3.I1.M1()").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1()'. 'Test1.M1()' cannot implement 'I1.M1()' because it does not have the matching return type of 'void'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.M1()", "Test1.M1()", "void").WithLocation(2, 15) ); } [Theory] [CombinatorialData] [WorkItem(20084, "https://github.com/dotnet/roslyn/issues/20084")] public void MethodImplementationInDerived_14(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1<T> { " + modifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } " + modifiers + @"void M2<S>() { System.Console.WriteLine(""I1.M2""); } } public interface I2<T> : I1<T> { " + implModifiers + @"void I1<T>.M1() { System.Console.WriteLine(""I2.I1.M1""); } " + implModifiers + @"void I1<T>.M2<S>() { System.Console.WriteLine(""I2.I1.M2""); } } public interface I3<T> : I1<T> {} "; var source2 = @" class Test1 : I1<int> { "; if (!isStatic) { source2 += @" static void Main() { I1<int> i1Int = new Test1(); I1<long> i1Long = new Test2(); "; } else { source2 += @" static void Main() { Test<Test1, Test2>(); } static void Test<i1Int, i1Long>() where i1Int : I1<int> where i1Long : I1<long> { "; } source2 += @" i1Int.M1(); i1Int.M2<int>(); i1Long.M1(); i1Long.M2<int>(); } } class Test2 : I2<long> {} "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = i1.GetMember<MethodSymbol>("M1"); var i1m2 = i1.GetMember<MethodSymbol>("M2"); var i2 = FindType(m, "I2"); var i2m1 = i2.GetMember<MethodSymbol>("I1<T>.M1"); var i2m2 = i2.GetMember<MethodSymbol>("I1<T>.M2"); var i2i1 = i2.InterfacesNoUseSiteDiagnostics().Single(); var i2i1m1 = i2i1.GetMember<MethodSymbol>("M1"); var i2i1m2 = i2i1.GetMember<MethodSymbol>("M2"); var i3 = FindType(m, "I3"); var i3i1 = i3.InterfacesNoUseSiteDiagnostics().Single(); var i3i1m1 = i3i1.GetMember<MethodSymbol>("M1"); var i3i1m2 = i3i1.GetMember<MethodSymbol>("M2"); Assert.Same(i1m1, i1.FindImplementationForInterfaceMember(i1m1)); Assert.Same(i1m2, i1.FindImplementationForInterfaceMember(i1m2)); Assert.Null(i2.FindImplementationForInterfaceMember(i1m1)); Assert.Null(i2.FindImplementationForInterfaceMember(i1m2)); Assert.Null(i2.FindImplementationForInterfaceMember(i3i1m1)); Assert.Null(i2.FindImplementationForInterfaceMember(i3i1m2)); Assert.Same(i2m1, i2.FindImplementationForInterfaceMember(i2i1m1)); Assert.Same(i2m2, i2.FindImplementationForInterfaceMember(i2i1m2)); Assert.Null(i3.FindImplementationForInterfaceMember(i1m1)); Assert.Null(i3.FindImplementationForInterfaceMember(i1m2)); Assert.Null(i3.FindImplementationForInterfaceMember(i2i1m1)); Assert.Null(i3.FindImplementationForInterfaceMember(i2i1m2)); Assert.Same(i3i1m1, i3.FindImplementationForInterfaceMember(i3i1m1)); Assert.Same(i3i1m2, i3.FindImplementationForInterfaceMember(i3i1m2)); ValidateExplicitImplementation(i2m1, isStatic: isStatic); ValidateExplicitImplementation(i2m2, isStatic: isStatic); var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var test1i1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32)); var test1i1m1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32)).GetMember<MethodSymbol>("M1"); var test1i1m2 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32)).GetMember<MethodSymbol>("M2"); var test2 = m.GlobalNamespace.GetTypeMember("Test2"); var test2i1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)); var test2i1m1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)).GetMember<MethodSymbol>("M1"); var test2i1m2 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)).GetMember<MethodSymbol>("M2"); var test2i2 = i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)); var test2i2m1 = i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)).GetMember<MethodSymbol>("I1<T>.M1"); var test2i2m2 = i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)).GetMember<MethodSymbol>("I1<T>.M2"); Assert.NotSame(test1i1, test1i1m1.ContainingType); Assert.NotSame(test1i1, test1i1m2.ContainingType); Assert.NotSame(test2i1, test2i1m1.ContainingType); Assert.NotSame(test2i1, test2i1m2.ContainingType); Assert.NotSame(test2i2, test2i2m1.ContainingType); Assert.NotSame(test2i2, test2i2m2.ContainingType); Assert.Null(test1i1.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test1i1.FindImplementationForInterfaceMember(i1m2)); Assert.Equal(test1i1m1, test1i1.FindImplementationForInterfaceMember(test1i1m1)); Assert.Equal(test1i1m2, test1i1.FindImplementationForInterfaceMember(test1i1m2)); Assert.Equal(test2i1m1, test2i1.FindImplementationForInterfaceMember(test2i1m1)); Assert.Equal(test2i1m2, test2i1.FindImplementationForInterfaceMember(test2i1m2)); Assert.Null(test2i2.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test2i2.FindImplementationForInterfaceMember(i1m2)); Assert.Equal(test2i2m1, test2i2.FindImplementationForInterfaceMember(test2i1m1)); Assert.Equal(test2i2m2, test2i2.FindImplementationForInterfaceMember(test2i1m2)); ValidateExplicitImplementation(test2i2m1, isStatic: isStatic); ValidateExplicitImplementation(test2i2m2, isStatic: isStatic); Assert.Null(test1.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test1.FindImplementationForInterfaceMember(i1m2)); Assert.Equal(test1i1m1, test1.FindImplementationForInterfaceMember(test1i1m1)); Assert.Equal(test1i1m2, test1.FindImplementationForInterfaceMember(test1i1m2)); Assert.Null(test2.FindImplementationForInterfaceMember(i1m1)); Assert.Null(test2.FindImplementationForInterfaceMember(i1m2)); Assert.Equal(test2i2m1, test2.FindImplementationForInterfaceMember(test2i1m1)); Assert.Equal(test2i2m2, test2.FindImplementationForInterfaceMember(test2i1m2)); } CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1 I1.M2 I2.I1.M1 I2.I1.M2 ", verify: Verify(isStatic), symbolValidator: Validate); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1 I1.M2 I2.I1.M1 I2.I1.M2 ", verify: Verify(isStatic), symbolValidator: Validate); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1 I1.M2 I2.I1.M1 I2.I1.M2 ", verify: Verify(isStatic), symbolValidator: Validate); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_15(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { " + implModifiers + @"void I1<string>.M1() { } } public interface I3 : I1<string?> { " + implModifiers + @"void I1<string?>.M1() { } } "; var source2 = @"#nullable enable warnings class Test1 : I2, I3 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (2,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(2, 7), // (2,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(2, 15), // (2,19): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I3").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(2, 19) ); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation3.VerifyDiagnostics( // (2,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(2, 7), // (2,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(2, 15), // (2,19): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I3").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(2, 19) ); test1 = compilation3.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_16(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { " + implModifiers + @"void I1<string>.M1() { } } public interface I3 : I1<string?> { " + implModifiers + @"void I1<string?>.M1() { } } "; var source2 = @"#nullable enable warnings class Test1 : I2, I3, I1<string> { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (2,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(2, 7), // (2,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(2, 15), // (2,19): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I3").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(2, 19), // (2,23): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1<string>").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(2, 23) ); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[4].GetMember("M1"))); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation3.VerifyDiagnostics( // (2,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(2, 7), // (2,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(2, 15), // (2,19): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I3").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(2, 19), // (2,23): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1<string>").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(2, 23) ); test1 = compilation3.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[4].GetMember("M1"))); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_17(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { " + implModifiers + @"void I1<string>.M1() { } } #nullable enable public interface I3 : I1<string?> { " + implModifiers + @"void I1<string?>.M1() { } } "; var source2 = @" #nullable enable class Test1 : I2, I3, I1<string> { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (3,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(3, 15), // (3,19): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I3").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(3, 19), // (3,23): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1<string>").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(3, 23) ); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[4].GetMember("M1"))); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation3.VerifyDiagnostics( // (3,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(3, 15), // (3,19): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I3").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(3, 19), // (3,23): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1<string>").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(3, 23) ); test1 = compilation3.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[4].GetMember("M1"))); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_18(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { " + implModifiers + @"void I1<string>.M1() { } } public interface I3 : I1<string?> { " + implModifiers + @"void I1<string?>.M1() { } } "; var source2 = @" #nullable enable class Test1 : I2, I3, I1<string?> { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3, I1<string?> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string?> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(4, 15), // (4,23): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string?>.M1()' are most specific. // class Test1 : I2, I3, I1<string?> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1<string?>").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string?>.M1()").WithLocation(4, 23) ); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation3.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3, I1<string?> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,15): error CS8705: Interface member 'I1<string>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string?> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1<string>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(4, 15), // (4,23): error CS8705: Interface member 'I1<string?>.M1()' does not have a most specific implementation. Neither 'I2.I1<string>.M1()', nor 'I3.I1<string>.M1()' are most specific. // class Test1 : I2, I3, I1<string?> Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1<string?>").WithArguments("I1<string?>.M1()", "I2.I1<string>.M1()", "I3.I1<string>.M1()").WithLocation(4, 23) ); test1 = compilation3.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_19(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { } public interface I3 : I2, I1<string?> { " + implModifiers + @"void I1<string>.M1() { } " + implModifiers + @"void I1<string?>.M1() { } } "; var source2 = @" #nullable enable class Test1 : I3 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (13,18): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'I3' with different nullability of reference types. // public interface I3 : I2, I1<string?> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "I3").WithArguments("I1<string?>", "I3").WithLocation(13, 18), // (13,18): error CS8646: 'I1<string>.M1()' is explicitly implemented more than once. // public interface I3 : I2, I1<string?> Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "I3").WithArguments("I1<string>.M1()").WithLocation(13, 18), // (13,18): error CS8646: 'I1<string?>.M1()' is explicitly implemented more than once. // public interface I3 : I2, I1<string?> Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "I3").WithArguments("I1<string?>.M1()").WithLocation(13, 18) ); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,15): error CS0535: 'Test1' does not implement interface member 'I1<string>.M1()' // class Test1 : I3 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test1", "I1<string>.M1()").WithLocation(4, 15), // (4,15): error CS0535: 'Test1' does not implement interface member 'I1<string?>.M1()' // class Test1 : I3 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test1", "I1<string?>.M1()").WithLocation(4, 15) ); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I3", "I2", "I1<System.String>", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); } [Theory] [CombinatorialData] public void MethodImplementationInDerived_20(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2 : I1<string> { } public interface I3 : I1<string?> { " + implModifiers + @"void I1<string?>.M1() { System.Console.WriteLine(""I3.M1""); } } "; var source2 = @" #nullable enable class Test1 : I2, I3 { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>", "I3", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I3.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I3.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,15): warning CS8644: 'Test1' does not implement interface member 'I1<string>.M1()'. Nullability of reference types in interface implemented by the base type doesn't match. // class Test1 : I2, I3 Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I2").WithArguments("Test1", "I1<string>.M1()").WithLocation(4, 15) ); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I3.M1 I3.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_21(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2 : I1<string> { } public interface I3 : I1<string?> { " + implModifiers + @"void I1<string?>.M1() { System.Console.WriteLine(""I3.M1""); } } "; var source2 = @" #nullable enable class Test1 : I3, I2 { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I3", "I1<System.String?>", "I2", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I3.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I3.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I3, I2 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string>", "Test1").WithLocation(4, 7), // (4,19): warning CS8644: 'Test1' does not implement interface member 'I1<string>.M1()'. Nullability of reference types in interface implemented by the base type doesn't match. // class Test1 : I3, I2 Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I2").WithArguments("Test1", "I1<string>.M1()").WithLocation(4, 19) ); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I3.M1 I3.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_22(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2<T> : I1<T> { " + implModifiers + @"void I1<T>.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I2<string> { } public interface I4 : I2<string?> { } "; var source2 = @" #nullable enable class Test1 : I3, I4 { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I3", "I2<System.String>", "I1<System.String>", "I4", "I2<System.String?>", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I2<System.String?>.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I2<System.String?>.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[5].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I2<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I3, I4 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I2<string?>", "Test1").WithLocation(4, 7), // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I3, I4 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7) ); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I2.M1 I2.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_23(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1() { System.Console.WriteLine(""I1.M1""); } } public interface I2<T> : I1<T> { " + implModifiers + @"void I1<T>.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3 : I2<string> { } public interface I4 : I2<string?> { } "; var source2 = @" #nullable enable class Test1 : I4, I3 { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I4", "I2<System.String?>", "I1<System.String?>", "I3", "I2<System.String>", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I2<System.String>.I1<System.String>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I2<System.String>.I1<System.String>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[5].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I2<string>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I4, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I2<string>", "Test1").WithLocation(4, 7), // (4,7): warning CS8645: 'I1<string>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I4, I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string>", "Test1").WithLocation(4, 7) ); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I2.M1 I2.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_24(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { " + implModifiers + @"void I1<string?>.M1() { System.Console.WriteLine(""I2.M1""); } } "; var source2 = @" #nullable enable class Test1 : I2 { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (11,10): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void I1<string?>.M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "I1<string?>").WithLocation(11, 10 + implModifiers.Length) ); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2", "I1<System.String>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I2.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[1].GetMember("M1")).ToTestDisplayString()); if (!isStatic) { compilation2.VerifyDiagnostics(); } else { compilation2.VerifyDiagnostics( // (9,9): warning CS8631: The type 'Test1' cannot be used as type parameter 'i11' in the generic type or method 'Test1.Test<i11, i12>()'. Nullability of type argument 'Test1' doesn't match constraint type 'I1<string?>'. // Test<Test1, Test1>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Test<Test1, Test1>").WithArguments("Test1.Test<i11, i12>()", "I1<string?>", "i11", "Test1").WithLocation(9, 9) ); } CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I2.M1 I2.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_25(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string> { " + implModifiers + @"void I1<string>.M1() { System.Console.WriteLine(""I2.M1""); } } "; var source2 = @" #nullable enable class Test1 : I2, I1<string?> { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2, I1<string?> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,19): warning CS8644: 'Test1' does not implement interface member 'I1<string?>.M1()'. Nullability of reference types in interface implemented by the base type doesn't match. // class Test1 : I2, I1<string?> Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I1<string?>").WithArguments("Test1", "I1<string?>.M1()").WithLocation(4, 19) ); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I2.M1 I2.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_26(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2 : I1<string?> { " + implModifiers + @"void I1<string>.M1() { System.Console.WriteLine(""I2.M1""); } } "; var source2 = @" #nullable enable class Test1 : I2, I1<string?> { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (11,10): warning CS8643: Nullability of reference types in explicit interface specifier doesn't match interface implemented by the type. // void I1<string>.M1() Diagnostic(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface, "I1<string>").WithLocation(11, 10 + implModifiers.Length) ); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); if (!isStatic) { compilation2.VerifyDiagnostics(); } else { compilation2.VerifyDiagnostics( // (9,9): warning CS8631: The type 'Test1' cannot be used as type parameter 'i12' in the generic type or method 'Test1.Test<i11, i12>()'. Nullability of type argument 'Test1' doesn't match constraint type 'I1<string>'. // Test<Test1, Test1>(); Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "Test<Test1, Test1>").WithArguments("Test1.Test<i11, i12>()", "I1<string>", "i12", "Test1").WithLocation(9, 9) ); } CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I2.M1 I2.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_27(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"void M1(); } public interface I2<T>: I1<T> { " + implModifiers + @"void I1<T>.M1() { System.Console.WriteLine(""I2.M1""); } } public interface I3<T> : I1<T> { " + implModifiers + @"void I1<T>.M1() { System.Console.WriteLine(""I3.M1""); } } public interface I4 : I2<string?>, I3<string?> { " + implModifiers + @"void I1<string?>.M1() { System.Console.WriteLine(""I4.M1""); } } "; var source2 = @" #nullable enable class Test1 : I2<string>, I3<string>, I4 { "; if (!isStatic) { source2 += @" static void Main() { ((I1<string?>)new Test1()).M1(); ((I1<string>)new Test1()).M1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i11, i12>() where i11 : I1<string?> where i12 : I1<string> { i11.M1(); i12.M1(); "; } source2 += @" } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics(); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I2<System.String>", "I3<System.String>", "I1<System.String>", "I4", "I2<System.String?>", "I3<System.String?>", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Equal("void I4.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1")).ToTestDisplayString()); Assert.Equal("void I4.I1<System.String?>.M1()", test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[6].GetMember("M1")).ToTestDisplayString()); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I2<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2<string>, I3<string>, I4 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I2<string?>", "Test1").WithLocation(4, 7), // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2<string>, I3<string>, I4 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,7): warning CS8645: 'I3<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I2<string>, I3<string>, I4 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I3<string?>", "Test1").WithLocation(4, 7), // (4,15): warning CS8644: 'Test1' does not implement interface member 'I1<string>.M1()'. Nullability of reference types in interface implemented by the base type doesn't match. // class Test1 : I2<string>, I3<string>, I4 Diagnostic(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase, "I2<string>").WithArguments("Test1", "I1<string>.M1()").WithLocation(4, 15) ); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @" I4.M1 I4.M1 ", verify: Verify(isStatic)); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_28(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"protected void M1(); } public interface I4 { " + modifiers + @"protected void M1(); } public interface I5 : I4 { "; if (!isStatic) { source1 += @" static void Test(I5 i4) { "; } else { source1 += @" static void Test<i4>() where i4 : I5 { "; } source1 += @" i4.M1(); } } public interface I6 : I2 { "; if (!isStatic) { source1 += @" static void Test(I6 i2) { "; } else { source1 += @" static void Test<i2>() where i2 : I6 { "; } source1 += @" i2.M1(); } } "; var source2 = @" public interface I1 : I6, I5 { " + implModifiers + @"void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"void I4.M1() { System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { I6.Test(new Test1()); I5.Test(new Test1()); "; } else { source3 += @" static void Main() { I6.Test<Test1>(); I5.Test<Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateMethodImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: VerifyFailsIlVerify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics(); CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); } void validateMethodImplementationInDerived_01(ModuleSymbol m) { ValidateMethodImplementationInDerived_01(m, isStatic: isStatic); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_29(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"protected internal void M1(); } public interface I4 { " + modifiers + @"protected internal void M1(); } public interface I5 : I4 { "; if (!isStatic) { source1 += @" static void Test(I5 i4) { "; } else { source1 += @" static void Test<i4>() where i4 : I5 { "; } source1 += @" i4.M1(); } } public interface I6 : I2 { "; if (!isStatic) { source1 += @" static void Test(I6 i2) { "; } else { source1 += @" static void Test<i2>() where i2 : I6 { "; } source1 += @" i2.M1(); } } "; var source2 = @" public interface I1 : I6, I5 { " + implModifiers + @"void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"void I4.M1() { System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { I6.Test(new Test1()); I5.Test(new Test1()); "; } else { source3 += @" static void Main() { I6.Test<Test1>(); I5.Test<Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateMethodImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics(); CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); } void validateMethodImplementationInDerived_01(ModuleSymbol m) { ValidateMethodImplementationInDerived_01(m, isStatic: isStatic); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_30(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"private protected void M1(); } public interface I4 { " + modifiers + @"private protected void M1(); } public interface I5 : I4 { "; if (!isStatic) { source1 += @" static void Test(I5 i4) { "; } else { source1 += @" static void Test<i4>() where i4 : I5 { "; } source1 += @" i4.M1(); } } public interface I6 : I2 { "; if (!isStatic) { source1 += @" static void Test(I6 i2) { "; } else { source1 += @" static void Test<i2>() where i2 : I6 { "; } source1 += @" i2.M1(); } } "; var source2 = @" public interface I1 : I6, I5 { " + implModifiers + @"void I2.M1() { System.Console.WriteLine(""I2.M1""); } " + implModifiers + @"void I4.M1() { System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { I6.Test(new Test1()); I5.Test(new Test1()); "; } else { source3 += @" static void Main() { I6.Test<Test1>(); I5.Test<Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateMethodImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: VerifyFailsIlVerify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validateMethodImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateMethodImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics( // (4,13): error CS0122: 'I2.M1()' is inaccessible due to its protection level // void I2.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1()").WithLocation(4, 13 + implModifiers.Length), // (8,13): error CS0122: 'I4.M1()' is inaccessible due to its protection level // void I4.M1() Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I4.M1()").WithLocation(8, 13 + implModifiers.Length) ); } void validateMethodImplementationInDerived_01(ModuleSymbol m) { ValidateMethodImplementationInDerived_01(m, isStatic: isStatic); } } [Theory] [CombinatorialData] public void MethodImplementationInDerived_31(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"void M1(); " + modifiers + @"void M2(); } public interface I2 : I1 { " + implModifiers + @"public virtual void M1() {} " + implModifiers + @"new public virtual void M2() {} } public interface I3 : I1, I2 { } class Test1 : I1, I2 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (10,25): warning CS0108: 'I2.M1()' hides inherited member 'I1.M1()'. Use the new keyword if hiding was intended. // public virtual void M1() Diagnostic(ErrorCode.WRN_NewRequired, "M1").WithArguments("I2.M1()", "I1.M1()").WithLocation(10, 25 + implModifiers.Length), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M2()' // class Test1 : I1, I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M2()").WithLocation(20, 15), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M1()' // class Test1 : I1, I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I1.M1()").WithLocation(20, 15) ); } [Fact] public void PartialMethodAccessibility() { var source1 = @" public partial interface I { partial void M(); partial void M() { } } "; var comp = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(comp.Assembly.RuntimeSupportsDefaultInterfaceImplementation); comp.VerifyDiagnostics(); var @interface = comp.SourceModule.GlobalNamespace.GetTypeMember("I"); var method = @interface.GetMembers().OfType<MethodSymbol>().Single(); Assert.Equal(Accessibility.Private, method.DeclaredAccessibility); } [Theory] [CombinatorialData] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void PropertyImplementationInDerived_01(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get;} } public interface I4 { " + modifiers + @"int M1 {set;} } public interface I5 : I4 { } public interface I1 : I2, I5 { " + implModifiers + @"int I2.M1 { get { System.Console.WriteLine(""I2.M1""); return 1; } } " + implModifiers + @"int I4.M1 { set => System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source2 = @" class Test1 : I1 { "; if (!isStatic) { source2 += @" static void Main() { I2 i2 = new Test1(); I4 i4 = new Test1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source2 += @" _ = i2.M1; i4.M1 = 0; } } "; ValidatePropertyImplementationInDerived_01(source1, source2, isStatic); } private void ValidatePropertyImplementationInDerived_01(string source1, string source2, bool isStatic = false) { foreach (var options in new[] { TestOptions.DebugExe, TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All) }) { var compilation1 = CreateCompilation(source1 + source2, options: options, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validatePropertyImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validatePropertyImplementationInDerived_01); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: options, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validatePropertyImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validatePropertyImplementationInDerived_01); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: options, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validatePropertyImplementationInDerived_01(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 ", verify: Verify(isStatic), symbolValidator: validatePropertyImplementationInDerived_01); } void validatePropertyImplementationInDerived_01(ModuleSymbol m) { ValidatePropertyImplementationInDerived_01(m, isStatic: isStatic); } } private static void ValidatePropertyImplementationInDerived_01(ModuleSymbol m, bool isStatic) { ValidatePropertyImplementationInDerived_01(m, i4M1IsAbstract: false, isStatic: isStatic); } private static void ValidatePropertyImplementationInDerived_01(ModuleSymbol m, bool i4M1IsAbstract, bool isStatic) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var i1i2m1 = i1.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); var i1i4m1 = i1.GetMembers().OfType<PropertySymbol>().Where(p => p.Name.StartsWith("I4.")).Single(); var i2 = i1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I2").Single(); var i2m1 = i2.GetMembers().OfType<PropertySymbol>().Single(); var i4 = i1.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I4").Single(); var i4m1 = i4.GetMembers().OfType<PropertySymbol>().Single(); var i3 = i1.ContainingNamespace.GetTypeMember("I3"); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); ValidateExplicitImplementation(i1i2m1, isStatic: isStatic); ValidateExplicitImplementation(i1i4m1, i4M1IsAbstract, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1i2m1); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1i4m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, test1, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4M1IsAbstract ? null : i1i4m1, test1, i4m1); VerifyFindImplementationForInterfaceMemberSame(null, i1, i1i2m1); VerifyFindImplementationForInterfaceMemberSame(null, i1, i1i4m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, i1, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4M1IsAbstract ? null : i1i4m1, i1, i4m1); VerifyFindImplementationForInterfaceMemberSame(i2m1.IsAbstract ? null : i2m1, i2, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4m1.IsAbstract ? null : i4m1, i4, i4m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, i3, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4M1IsAbstract ? null : i1i4m1, i3, i4m1); } private static void VerifyFindImplementationForInterfaceMemberSame(PropertySymbol expected, NamedTypeSymbol implementingType, PropertySymbol interfaceProperty) { Assert.Same(expected, implementingType.FindImplementationForInterfaceMember(interfaceProperty)); ValidateAccessor(expected?.GetMethod, interfaceProperty.GetMethod); ValidateAccessor(expected?.SetMethod, interfaceProperty.SetMethod); void ValidateAccessor(MethodSymbol accessor, MethodSymbol interfaceAccessor) { if ((object)interfaceAccessor != null) { Assert.Same(interfaceAccessor.DeclaredAccessibility == Accessibility.Private ? null : accessor, implementingType.FindImplementationForInterfaceMember(interfaceAccessor)); } else { Assert.Null(accessor); } } } private static void VerifyFindImplementationForInterfaceMemberEqual(PropertySymbol expected, NamedTypeSymbol implementingType, PropertySymbol interfaceProperty) { Assert.Equal(expected, implementingType.FindImplementationForInterfaceMember(interfaceProperty)); ValidateAccessor(expected?.GetMethod, interfaceProperty.GetMethod); ValidateAccessor(expected?.SetMethod, interfaceProperty.SetMethod); void ValidateAccessor(MethodSymbol accessor, MethodSymbol interfaceAccessor) { if ((object)interfaceAccessor != null) { Assert.Equal(accessor, implementingType.FindImplementationForInterfaceMember(interfaceAccessor)); } else { Assert.Null(accessor); } } } private static void ValidateExplicitImplementation(PropertySymbol m1, bool isAbstract = false, bool isStatic = false) { Assert.Equal(isAbstract, m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.Equal(isAbstract, m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); ValidateAccessor(m1.GetMethod, isAbstract, isStatic); ValidateAccessor(m1.SetMethod, isAbstract, isStatic); static void ValidateAccessor(MethodSymbol accessor, bool isAbstract, bool isStatic) { if ((object)accessor != null) { ValidateExplicitImplementation(accessor, isAbstract, isStatic); } } } [Fact] public void PropertyImplementationInDerived_02() { var source1 = @" public interface I2 { int M1 {get;} } public interface I4 { int M1 {set;} } public interface I1 : I2, I4 { int I2.M1 => Getter(); private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } int I4.M1 { set { System.Console.WriteLine(""I2.M1""); } } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_02(source1, isStatic: false, new DiagnosticDescription[] { // (14,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int I2.M1 => Getter(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "Getter()").WithArguments("default interface implementation", "8.0").WithLocation(14, 18), // (16,17): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // private int Getter() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "Getter").WithArguments("default interface implementation", "8.0").WithLocation(16, 17), // (24,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // set Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(24, 9) }, // (6,15): error CS8506: 'I1.I2.M1.get' cannot implement interface member 'I2.M1.get' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.get", "I2.M1.get", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15), // (6,15): error CS8506: 'I1.I4.M1.set' cannot implement interface member 'I4.M1.set' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.set", "I4.M1.set", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15) ); } [Fact] public void PropertyImplementationInDerived_Static_02() { var source1 = @" public interface I2 { static abstract int M1 {get;} } public interface I4 { static abstract int M1 {set;} } public interface I1 : I2, I4 { static int I2.M1 => Getter(); static private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } static int I4.M1 { set { System.Console.WriteLine(""I2.M1""); } } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_02(source1, isStatic: true, new DiagnosticDescription[] { // (4,25): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract int M1 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(4, 25), // (9,25): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract int M1 {set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(9, 25), // (14,19): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static int I2.M1 => Getter(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(14, 19), // (22,19): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static int I4.M1 Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(22, 19) }, // (6,15): error CS8706: 'I1.I2.M1.get' cannot implement interface member 'I2.M1.get' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.get", "I2.M1.get", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15), // (6,15): error CS8706: 'I1.I4.M1.set' cannot implement interface member 'I4.M1.set' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.set", "I4.M1.set", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15) ); } private void ValidatePropertyImplementationInDerived_02(string source1, bool isStatic, DiagnosticDescription[] expected1, params DiagnosticDescription[] expected2) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected1); ValidatePropertyImplementationInDerived_01(compilation1.SourceModule, isStatic: isStatic); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(expected2); ValidatePropertyImplementationInDerived_01(compilation2.SourceModule, isStatic: isStatic); } [Fact] public void PropertyImplementationInDerived_03() { var source1 = @" public interface I2 { int M1 {get; set;} } public interface I4 { int M1 {set;} } public interface I1 : I2, I4 { int I2.M1 { get { System.Console.WriteLine(""I2.M1""); return 1; } set { System.Console.WriteLine(""I2.M1""); } } int I4.M1 { set { System.Console.WriteLine(""I2.M1""); } } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_03(source1, isStatic: false, new DiagnosticDescription[] { // (16,9): error CS8501: Target runtime doesn't support default interface implementation. // get Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(16, 9), // (21,9): error CS8501: Target runtime doesn't support default interface implementation. // set Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(21, 9), // (29,9): error CS8501: Target runtime doesn't support default interface implementation. // set Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(29, 9) }, // (6,15): error CS8502: 'I1.I2.M1.set' cannot implement interface member 'I2.M1.set' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.set", "I2.M1.set", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I2.M1.get' cannot implement interface member 'I2.M1.get' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.get", "I2.M1.get", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I4.M1.set' cannot implement interface member 'I4.M1.set' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.set", "I4.M1.set", "Test1").WithLocation(6, 15) ); } private void ValidatePropertyImplementationInDerived_03(string source1, bool isStatic, DiagnosticDescription[] expected1, params DiagnosticDescription[] expected2) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); compilation1.VerifyDiagnostics(expected1); ValidatePropertyImplementationInDerived_01(compilation1.SourceModule, isStatic); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); compilation2.VerifyDiagnostics(expected2); } [Fact] public void PropertyImplementationInDerived_Static_03() { var source1 = @" public interface I2 { static abstract int M1 {get; set;} } public interface I4 { static abstract int M1 {set;} } public interface I1 : I2, I4 { static int I2.M1 { get { System.Console.WriteLine(""I2.M1""); return 1; } set { System.Console.WriteLine(""I2.M1""); } } static int I4.M1 { set { System.Console.WriteLine(""I2.M1""); } } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_03(source1, isStatic: true, new DiagnosticDescription[] { // (4,29): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract int M1 {get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "get").WithLocation(4, 29), // (4,34): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract int M1 {get; set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "set").WithLocation(4, 34), // (9,29): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract int M1 {set;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "set").WithLocation(9, 29), // (14,19): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static int I2.M1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(14, 19), // (27,19): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static int I4.M1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(27, 19) }, // (6,15): error CS8929: 'I1.I2.M1.get' cannot implement interface member 'I2.M1.get' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I2.M1.get", "I2.M1.get", "Test1").WithLocation(6, 15), // (6,15): error CS8929: 'I1.I2.M1.set' cannot implement interface member 'I2.M1.set' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I2.M1.set", "I2.M1.set", "Test1").WithLocation(6, 15), // (6,15): error CS8929: 'I1.I4.M1.set' cannot implement interface member 'I4.M1.set' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I4.M1.set", "I4.M1.set", "Test1").WithLocation(6, 15) ); } [Fact] public void PropertyImplementationInDerived_04() { var source1 = @" public interface I2 { int M1 {get;} } public interface I4 { int M1 {set;} } public interface I1 : I2, I4 { int I2.M1 {get;} int I4.M1 {set;} } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic: false, // (14,16): error CS0501: 'I1.I2.M1.get' must declare a body because it is not marked abstract, extern, or partial // int I2.M1 {get;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.I2.M1.get").WithLocation(14, 16), // (15,16): error CS0501: 'I1.I4.M1.set' must declare a body because it is not marked abstract, extern, or partial // int I4.M1 {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.I4.M1.set").WithLocation(15, 16) ); } private void ValidatePropertyImplementationInDerived_04(string source1, bool isStatic, params DiagnosticDescription[] expected) { ValidatePropertyImplementationInDerived_04(source1, i4M1IsAbstract: false, isStatic, expected); } private void ValidatePropertyImplementationInDerived_04(string source1, bool i4M1IsAbstract, bool isStatic, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); ValidatePropertyImplementationInDerived_01(compilation1.SourceModule, i4M1IsAbstract, isStatic: isStatic); } [Fact] public void PropertyImplementationInDerived_Static_04() { var source1 = @" public interface I2 { static abstract int M1 {get;} } public interface I4 { static abstract int M1 {set;} } public interface I1 : I2, I4 { static int I2.M1 {get;} static int I4.M1 {set;} } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic: true, // (15,23): error CS8051: Auto-implemented properties must have get accessors. // static int I4.M1 {set;} Diagnostic(ErrorCode.ERR_AutoPropertyMustHaveGetAccessor, "set").WithLocation(15, 23) ); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_05(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get;} } public interface I4 { " + modifiers + @"int M1 {set;} } public interface I1 { " + implModifiers + @"int I2.M1 {get => throw null;} " + implModifiers + @"int I4.M1 {set => throw null;} } "; ValidatePropertyImplementationInDerived_05(source1, // (14,9): error CS0540: 'I1.I2.M1': containing type does not implement interface 'I2' // int I2.M1 {get => throw null;} Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I2").WithArguments("I1.I2.M1", "I2").WithLocation(14, 9 + implModifiers.Length), // (15,9): error CS0540: 'I1.I4.M1': containing type does not implement interface 'I4' // int I4.M1 {set => throw null;} Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I4").WithArguments("I1.I4.M1", "I4").WithLocation(15, 9 + implModifiers.Length) ); } private void ValidatePropertyImplementationInDerived_05(string source1, params DiagnosticDescription[] expected) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected); } [Fact] public void PropertyImplementationInDerived_06() { var source1 = @" public interface I2 { int M1 {get; set;} } public interface I4 { int M1 {get; set;} } public interface I1 : I2, I4 { public static int I2.M1 { internal get => throw null; set => throw null; } internal virtual int I4.M1 { public get => throw null; set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (14,26): error CS0106: The modifier 'public' is not valid for this item // public static int I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("public").WithLocation(14, 26), // (14,26): error CS0539: 'I1.M1' in explicit interface declaration is not found among members of the interface that can be implemented // public static int I2.M1 Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.M1").WithLocation(14, 26), // (16,18): error CS0106: The modifier 'internal' is not valid for this item // internal get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("internal").WithLocation(16, 18), // (19,29): error CS0106: The modifier 'internal' is not valid for this item // internal virtual int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("internal").WithLocation(19, 29), // (19,29): error CS0106: The modifier 'virtual' is not valid for this item // internal virtual int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("virtual").WithLocation(19, 29), // (21,16): error CS0106: The modifier 'public' is not valid for this item // public get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(21, 16), // (30,15): error CS0535: 'Test1' does not implement interface member 'I2.M1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I2.M1").WithLocation(30, 15) ); } [Fact] public void PropertyImplementationInDerived_Static_06() { var source1 = @" public interface I2 { static abstract int M1 {get; set;} } public interface I4 { static abstract int M1 {get; set;} } public interface I1 : I2, I4 { public int I2.M1 { internal get => throw null; set => throw null; } internal static virtual int I4.M1 { public get => throw null; set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (14,19): error CS0106: The modifier 'public' is not valid for this item // public int I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("public").WithLocation(14, 19), // (14,19): error CS0539: 'I1.M1' in explicit interface declaration is not found among members of the interface that can be implemented // public int I2.M1 Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.M1").WithLocation(14, 19), // (16,18): error CS0106: The modifier 'internal' is not valid for this item // internal get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("internal").WithLocation(16, 18), // (19,36): error CS0106: The modifier 'internal' is not valid for this item // internal static virtual int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("internal").WithLocation(19, 36), // (19,36): error CS0106: The modifier 'virtual' is not valid for this item // internal static virtual int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("virtual").WithLocation(19, 36), // (21,16): error CS0106: The modifier 'public' is not valid for this item // public get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(21, 16), // (30,15): error CS0535: 'Test1' does not implement interface member 'I2.M1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I2.M1").WithLocation(30, 15) ); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_07(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get; set;} } public interface I4 { " + modifiers + @"int M1 {get; set;} } public interface I1 : I2, I4 { " + implModifiers + @"private sealed int I2.M1 { private get => throw null; set => throw null; } " + implModifiers + @"protected abstract int I4.M1 { get => throw null; protected set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, i4M1IsAbstract: true, isStatic: isStatic, // (14,27): error CS0106: The modifier 'sealed' is not valid for this item // private sealed int I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("sealed").WithLocation(14, 27 + implModifiers.Length), // (14,27): error CS0106: The modifier 'private' is not valid for this item // private sealed int I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private").WithLocation(14, 27 + implModifiers.Length), // (16,17): error CS0106: The modifier 'private' is not valid for this item // private get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(16, 17), // (19,31): error CS0106: The modifier 'protected' is not valid for this item // protected abstract int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected").WithLocation(19, 31 + implModifiers.Length), // (21,9): error CS0500: 'I1.I4.M1.get' cannot declare a body because it is marked abstract // get => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.I4.M1.get").WithLocation(21, 9), // (22,19): error CS0106: The modifier 'protected' is not valid for this item // protected set => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(22, 19), // (22,19): error CS0500: 'I1.I4.M1.set' cannot declare a body because it is marked abstract // protected set => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.I4.M1.set").WithLocation(22, 19), // (30,15): error CS0535: 'Test1' does not implement interface member 'I4.M1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I4.M1").WithLocation(30, 15) ); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_08(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get; set;} } public interface I4 { " + modifiers + @"int M1 {get; set;} } public interface I1 : I2, I4 { " + implModifiers + @"private protected int I2.M1 { private protected get => throw null; set => throw null; } " + implModifiers + @"internal protected override int I4.M1 { get => throw null; internal protected set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic: isStatic, // (14,30): error CS0106: The modifier 'private protected' is not valid for this item // private protected int I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private protected").WithLocation(14, 30 + implModifiers.Length), // (16,27): error CS0106: The modifier 'private protected' is not valid for this item // private protected get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private protected").WithLocation(16, 27), // (19,40): error CS0106: The modifier 'protected internal' is not valid for this item // internal protected override int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected internal").WithLocation(19, 40 + implModifiers.Length), // (19,40): error CS0106: The modifier 'override' is not valid for this item // internal protected override int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("override").WithLocation(19, 40 + implModifiers.Length), // (22,28): error CS0106: The modifier 'protected internal' is not valid for this item // internal protected set => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected internal").WithLocation(22, 28) ); } [Fact] public void PropertyImplementationInDerived_09() { var source1 = @" public interface I2 { int M1 {get;} } public interface I1 : I2 { extern int I2.M1 {get;} } public interface I3 : I1 { } class Test1 : I1 {} "; var source2 = @" public interface I2 { int M1 {set;} } public interface I1 : I2 { extern int I2.M1 { set {}} } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_09(source1, source2, isStatic: false, new DiagnosticDescription[] { // (9,23): warning CS0626: Method, operator, or accessor 'I1.I2.M1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int I2.M1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.M1.get").WithLocation(9, 23) }, new DiagnosticDescription[] { // (9,23): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern int I2.M1 {get;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(9, 23), // (9,23): warning CS0626: Method, operator, or accessor 'I1.I2.M1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int I2.M1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.M1.get").WithLocation(9, 23) }, new DiagnosticDescription[] { // (9,23): error CS8501: Target runtime doesn't support default interface implementation. // extern int I2.M1 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(9, 23), // (9,23): warning CS0626: Method, operator, or accessor 'I1.I2.M1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int I2.M1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.M1.get").WithLocation(9, 23) }, // (10,7): error CS0179: 'I1.I2.M1.set' cannot be extern and declare a body // { set {}} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I1.I2.M1.set").WithLocation(10, 7) ); } private void ValidatePropertyImplementationInDerived_09(string source1, string source2, bool isStatic, DiagnosticDescription[] expected1, DiagnosticDescription[] expected2, DiagnosticDescription[] expected3, params DiagnosticDescription[] expected4) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(expected1); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var i1i2m1 = GetSingleProperty(i1); var i2 = i1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I2").Single(); var i2m1 = GetSingleProperty(i2); var i3 = i1.ContainingNamespace.GetTypeMember("I3"); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); ValidateExplicitExternImplementation(i1i2m1, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1i2m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, test1, i2m1); VerifyFindImplementationForInterfaceMemberSame(null, i1, i1i2m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, i1, i2m1); VerifyFindImplementationForInterfaceMemberSame(null, i2, i2m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, i3, i2m1); } CompileAndVerify(compilation1, verify: Verify(isStatic), symbolValidator: Validate1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(expected2); Validate1(compilation2.SourceModule); var compilation3 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: isStatic ? TargetFramework.Net50 : TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); compilation3.VerifyDiagnostics(expected3); Validate1(compilation3.SourceModule); var compilation4 = CreateCompilation(source2, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(expected4); Validate1(compilation4.SourceModule); } private static void ValidateExplicitExternImplementation(PropertySymbol m1, bool isStatic) { Assert.False(m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.False(m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.NotEqual(m1.OriginalDefinition is PEPropertySymbol, m1.IsExtern); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); ValidateAccessor(m1.GetMethod); ValidateAccessor(m1.SetMethod); void ValidateAccessor(MethodSymbol accessor) { if ((object)accessor != null) { ValidateExplicitExternImplementation(accessor, isStatic: isStatic); } } } [Fact] public void PropertyImplementationInDerived_Static_09() { var source1 = @" public interface I2 { static abstract int M1 {get;} } public interface I1 : I2 { static extern int I2.M1 {get;} } public interface I3 : I1 { } class Test1 : I1 {} "; var source2 = @" public interface I2 { static abstract int M1 {set;} } public interface I1 : I2 { static extern int I2.M1 { set {}} } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_09(source1, source2, isStatic: true, new DiagnosticDescription[] { // (9,30): warning CS0626: Method, operator, or accessor 'I1.I2.M1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int I2.M1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.M1.get").WithLocation(9, 30) }, new DiagnosticDescription[] { // (4,25): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract int M1 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(4, 25), // (9,26): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static extern int I2.M1 {get;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(9, 26), // (9,30): warning CS0626: Method, operator, or accessor 'I1.I2.M1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int I2.M1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.M1.get").WithLocation(9, 30) }, new DiagnosticDescription[] { // (4,29): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract int M1 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "get").WithLocation(4, 29), // (9,26): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static extern int I2.M1 {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(9, 26), // (9,30): warning CS0626: Method, operator, or accessor 'I1.I2.M1.get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // static extern int I2.M1 {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.M1.get").WithLocation(9, 30) }, // (10,7): error CS0179: 'I1.I2.M1.set' cannot be extern and declare a body // { set {}} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I1.I2.M1.set").WithLocation(10, 7) ); } [Fact] public void PropertyImplementationInDerived_10() { var source1 = @" public interface I1 { int M1 {get;set;} int M2 {get;set;} } public interface I2 : I1 { int I1.M1 { get => throw null; } int I1.M2 { set => throw null; } } class Test1 : I2 {} public interface I3 { int M1 {get;} int M2 {set;} int M3 {get;set;} int M4 {get;set;} } public interface I4 : I3 { int I3.M1 { get => throw null; set => throw null; } int I3.M2 { get => throw null; set => throw null; } int I3.M3 {get; set;} int I3.M4 {get; set;} = 0; } class Test2 : I4 {} "; ValidatePropertyImplementationInDerived_05(source1, // (10,12): error CS0551: Explicit interface implementation 'I2.I1.M1' is missing accessor 'I1.M1.set' // int I1.M1 Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "M1").WithArguments("I2.I1.M1", "I1.M1.set").WithLocation(10, 12), // (14,12): error CS0551: Explicit interface implementation 'I2.I1.M2' is missing accessor 'I1.M2.get' // int I1.M2 Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "M2").WithArguments("I2.I1.M2", "I1.M2.get").WithLocation(14, 12), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M1' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.M1").WithLocation(20, 15), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M2' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.M2").WithLocation(20, 15), // (36,9): error CS0550: 'I4.I3.M1.set' adds an accessor not found in interface member 'I3.M1' // set => throw null; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I4.I3.M1.set", "I3.M1").WithLocation(36, 9), // (40,9): error CS0550: 'I4.I3.M2.get' adds an accessor not found in interface member 'I3.M2' // get => throw null; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I4.I3.M2.get", "I3.M2").WithLocation(40, 9), // (43,16): error CS0501: 'I4.I3.M3.get' must declare a body because it is not marked abstract, extern, or partial // int I3.M3 {get; set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I4.I3.M3.get").WithLocation(43, 16), // (43,21): error CS0501: 'I4.I3.M3.set' must declare a body because it is not marked abstract, extern, or partial // int I3.M3 {get; set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I4.I3.M3.set").WithLocation(43, 21), // (44,12): error CS8053: Instance properties in interfaces cannot have initializers. // int I3.M4 {get; set;} = 0; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "M4").WithLocation(44, 12), // (44,16): error CS0501: 'I4.I3.M4.get' must declare a body because it is not marked abstract, extern, or partial // int I3.M4 {get; set;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I4.I3.M4.get").WithLocation(44, 16), // (44,21): error CS0501: 'I4.I3.M4.set' must declare a body because it is not marked abstract, extern, or partial // int I3.M4 {get; set;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I4.I3.M4.set").WithLocation(44, 21) ); } [Fact] public void PropertyImplementationInDerived_Static_10() { var source1 = @" public interface I1 { static abstract int M1 {get;set;} static abstract int M2 {get;set;} } public interface I2 : I1 { static int I1.M1 { get => throw null; } static int I1.M2 { set => throw null; } } class Test1 : I2 {} public interface I3 { static abstract int M1 {get;} static abstract int M2 {set;} static abstract int M3 {get;set;} static abstract int M4 {get;set;} } public interface I4 : I3 { static int I3.M1 { get => throw null; set => throw null; } static int I3.M2 { get => throw null; set => throw null; } static int I3.M3 {get; set;} static int I3.M4 {get; set;} = 0; } class Test2 : I4 {} "; ValidatePropertyImplementationInDerived_05(source1, // (10,19): error CS0551: Explicit interface implementation 'I2.I1.M1' is missing accessor 'I1.M1.set' // static int I1.M1 Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "M1").WithArguments("I2.I1.M1", "I1.M1.set").WithLocation(10, 19), // (14,19): error CS0551: Explicit interface implementation 'I2.I1.M2' is missing accessor 'I1.M2.get' // static int I1.M2 Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "M2").WithArguments("I2.I1.M2", "I1.M2.get").WithLocation(14, 19), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M1' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.M1").WithLocation(20, 15), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M2' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.M2").WithLocation(20, 15), // (36,9): error CS0550: 'I4.I3.M1.set' adds an accessor not found in interface member 'I3.M1' // set => throw null; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I4.I3.M1.set", "I3.M1").WithLocation(36, 9), // (40,9): error CS0550: 'I4.I3.M2.get' adds an accessor not found in interface member 'I3.M2' // get => throw null; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I4.I3.M2.get", "I3.M2").WithLocation(40, 9) ); } [Theory] [CombinatorialData] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void PropertyImplementationInDerived_11(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"internal int M1 {get;} } public interface I4 { " + modifiers + @"int M1 {get; internal set;} } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source1 += @" _ = i2.M1; i4.M1 = i4.M1; } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"int I2.M1 => Getter(); " + implModifiers + @"private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } " + implModifiers + @"int I4.M1 { get { System.Console.WriteLine(""I4.M1""); return 1; } set => System.Console.WriteLine(""I4.M1.set""); } } public interface I3 : I1 { } "; ValidatePropertyImplementationInDerived_11(source1, source2, isStatic, // (4,12): error CS0122: 'I2.M1' is inaccessible due to its protection level // int I2.M1 => Getter(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1").WithLocation(4, 12 + implModifiers.Length), // (11,12): error CS0122: 'I4.M1.set' is inaccessible due to its protection level // int I4.M1 Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I4.M1.set").WithLocation(11, 12 + implModifiers.Length) ); } private void ValidatePropertyImplementationInDerived_11(string source1, string source2, bool isStatic, params DiagnosticDescription[] expected) { var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { TestHelper.Test(new Test1(), new Test1()); "; } else { source3 += @" static void Main() { TestHelper.Test<Test1, Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validatePropertyImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 I4.M1.set ", verify: Verify(isStatic), symbolValidator: validatePropertyImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validatePropertyImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 I4.M1.set ", verify: Verify(isStatic), symbolValidator: validatePropertyImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validatePropertyImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics(expected); if (expected.Length == 0) { CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1 I4.M1 I4.M1.set ", verify: Verify(isStatic), symbolValidator: validatePropertyImplementationInDerived_01); } } void validatePropertyImplementationInDerived_01(ModuleSymbol m) { ValidatePropertyImplementationInDerived_01(m, isStatic: isStatic); } } [Theory] [CombinatorialData] [WorkItem(20083, "https://github.com/dotnet/roslyn/issues/20083")] public void PropertyImplementationInDerived_12(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"int M1 { get => throw null; set => throw null;} } public interface I2 : I1 { " + implModifiers + @"int I1.M1 { get { System.Console.WriteLine(""I2.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I2.I1.M1.set""); } } } public interface I3 : I1 { " + implModifiers + @"int I1.M1 { get { System.Console.WriteLine(""I3.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I3.I1.M1.set""); } } } public interface I4 : I1 { " + implModifiers + @"int I1.M1 { get { System.Console.WriteLine(""I4.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I4.I1.M1.set""); } } } public interface I5 : I2, I3 { " + implModifiers + @"int I1.M1 { get { System.Console.WriteLine(""I5.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I5.I1.M1.set""); } } } public interface I6 : I1, I2, I3, I5 {} "; var source4 = @" class Test5 : I2 {} class Test6 : I1, I2, I3, I5 {} class Test7 : I6 { "; if (!isStatic) { source4 += @" static void Main() { I1 i5 = new Test5(); I1 i6 = new Test6(); I1 i7 = new Test7(); "; } else { source4 += @" static void Main() { Test<Test5, Test6, Test7>(); } static void Test<i5, i6, i7>() where i5 : I1 where i6 : I1 where i7 : I1 { "; } source4 += @" i5.M1 = i5.M1; i6.M1 = i6.M1; i7.M1 = i7.M1; } } "; var source5 = @" class Test8 : I2, I3 { " + implModifiers + @"int I1.M1 { get { System.Console.WriteLine(""Test8.I1.M1.get""); return 1; } set { System.Console.WriteLine(""Test8.I1.M1.set""); } } "; if (!isStatic) { source5 += @" static void Main() { I1 i8 = new Test8(); I1 i9 = new Test9(); I1 i10 = new Test10(); I1 i11 = new Test11(); I1 i12 = new Test12(); "; } else { source5 += @" static void Main() { Test<Test8, Test9, Test10, Test11, Test12>(); } static void Test<i8, i9, i10, i11, i12>() where i8 : I1 where i9 : I1 where i10 : I1 where i11 : I1 where i12 : I1 { "; } source5 += @" i8.M1 = i8.M1; i9.M1 = i9.M1; i10.M1 = i10.M1; i11.M1 = i11.M1; i12.M1 = i12.M1; } } class Test9 : I7 { " + implModifiers + @"int I1.M1 { get { System.Console.WriteLine(""Test9.I1.M1.get""); return 1; } set { System.Console.WriteLine(""Test9.I1.M1.set""); } } } class Test10 : I1, I2, I3, I4 { " + implModifiers + @"public int M1 { get { System.Console.WriteLine(""Test10.M1.get""); return 1; } set { System.Console.WriteLine(""Test10.M1.set""); } } } class Test11 : I1, I2, I3, I5, I4 { " + implModifiers + @"public int M1 { get { System.Console.WriteLine(""Test11.M1.get""); return 1; } set { System.Console.WriteLine(""Test11.M1.set""); } } } class Test12 : I8 { " + implModifiers + @"public " + (isStatic ? "" : "virtual") + @" int M1 { get { System.Console.WriteLine(""Test12.M1.get""); return 1; } set { System.Console.WriteLine(""Test12.M1.set""); } } } "; ValidatePropertyImplementationInDerived_12(source1, source4, source5, isStatic, new DiagnosticDescription[] { // (2,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(2, 15), // (5,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test2 : I7 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I7").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(5, 15), // (8,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test3 : I1, I2, I3, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(8, 15), // (11,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I5.I1.M1', nor 'I4.I1.M1' are most specific. // class Test4 : I1, I2, I3, I5, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.M1", "I5.I1.M1", "I4.I1.M1").WithLocation(11, 15), // (14,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I5.I1.M1', nor 'I4.I1.M1' are most specific. // class Test5 : I8 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I8").WithArguments("I1.M1", "I5.I1.M1", "I4.I1.M1").WithLocation(14, 15) } ); } private void ValidatePropertyImplementationInDerived_12(string source1, string source4, string source5, bool isStatic, DiagnosticDescription[] expected1, DiagnosticDescription[] expected2 = null) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = GetSingleProperty(i1); var i2 = FindType(m, "I2"); var i2m1 = GetSingleProperty(i2); var i5 = FindType(m, "I5"); var i5m1 = GetSingleProperty(i5); var i6 = FindType(m, "I6"); ValidateExplicitImplementation(i2m1, isStatic: isStatic); ValidateExplicitImplementation(i5m1, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(i1m1, i1, i1m1); VerifyFindImplementationForInterfaceMemberSame(i2m1, i2, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, i5, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, i6, i1m1); } CompileAndVerify(compilation1, verify: Verify(isStatic), symbolValidator: Validate1); var refs1 = new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }; var source2 = @" public interface I7 : I2, I3 {} public interface I8 : I1, I2, I3, I5, I4 {} "; var source3 = @" class Test1 : I2, I3 {} class Test2 : I7 {} class Test3 : I1, I2, I3, I4 {} class Test4 : I1, I2, I3, I5, I4 {} class Test5 : I8 {} "; foreach (var ref1 in refs1) { var compilation2 = CreateCompilation(source2, new[] { ref1 }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); // According to LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-06-14.md, // we do not require interfaces to have a most specific implementation of all members. Therefore, there are no // errors in this compilation. compilation2.VerifyDiagnostics(); Validate2(compilation2.SourceModule); void Validate2(ModuleSymbol m) { Validate1(m); var i1 = FindType(m, "I1"); var i1m1 = GetSingleProperty(i1); var i7 = FindType(m, "I7"); var i8 = FindType(m, "I8"); VerifyFindImplementationForInterfaceMemberSame(null, i7, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i8, i1m1); } CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: Validate2); compilation2 = CreateCompilation(source2, new[] { ref1 }, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); Validate2(compilation2.SourceModule); CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: Validate2); var refs2 = new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }; var compilation4 = CreateCompilation(source4, new[] { ref1 }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); Validate4(compilation4.SourceModule); void Validate4(ModuleSymbol m) { Validate1(m); var i1 = FindType(m, "I1"); var i1m1 = GetSingleProperty(i1); var i2 = FindType(m, "I2"); var i2m1 = GetSingleProperty(i2); var i5 = FindType(m, "I5"); var i5m1 = GetSingleProperty(i5); var test5 = FindType(m, "Test5"); var test6 = FindType(m, "Test6"); var test7 = FindType(m, "Test7"); VerifyFindImplementationForInterfaceMemberSame(i2m1, test5, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, test6, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, test7, i1m1); } CompileAndVerify(compilation4, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.I1.M1.get I2.I1.M1.set I5.I1.M1.get I5.I1.M1.set I5.I1.M1.get I5.I1.M1.set " , verify: Verify(isStatic), symbolValidator: Validate4); foreach (var ref2 in refs2) { var compilation3 = CreateCompilation(source3, new[] { ref1, ref2 }, options: TestOptions.DebugDll.WithConcurrentBuild(false), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(ref1 is CompilationReference ? expected1 : expected2 ?? expected1); Validate3(compilation3.SourceModule); void Validate3(ModuleSymbol m) { Validate1(m); Validate2(m); var i1 = FindType(m, "I1"); var i1m1 = GetSingleProperty(i1); var test1 = FindType(m, "Test1"); var test2 = FindType(m, "Test2"); var test3 = FindType(m, "Test3"); var test4 = FindType(m, "Test4"); var test5 = FindType(m, "Test5"); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test2, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test3, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test4, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test5, i1m1); } var compilation5 = CreateCompilation(source5, new[] { ref1, ref2 }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics(); Validate5(compilation5.SourceModule); void Validate5(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = GetSingleProperty(i1); var test8 = FindType(m, "Test8"); var test9 = FindType(m, "Test9"); var test10 = FindType(m, "Test10"); var test11 = FindType(m, "Test11"); var test12 = FindType(m, "Test12"); VerifyFindImplementationForInterfaceMemberSame(GetSingleProperty(test8), test8, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleProperty(test9), test9, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleProperty(test10), test10, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleProperty(test11), test11, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleProperty(test12), test12, i1m1); } CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"Test8.I1.M1.get Test8.I1.M1.set Test9.I1.M1.get Test9.I1.M1.set Test10.M1.get Test10.M1.set Test11.M1.get Test11.M1.set Test12.M1.get Test12.M1.set ", verify: Verify(isStatic), symbolValidator: Validate5); } } } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_13(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"int M1 {get;} } public interface I2 : I1 { " + implModifiers + @"int I1.M1 => throw null; } public interface I3 : I1 { " + implModifiers + @"int I1.M1 => throw null; } "; var source2 = @" class Test1 : I2, I3 { " + implModifiers + @"public long M1 => 1; } "; ValidatePropertyImplementationInDerived_13(source1, source2, new DiagnosticDescription[] { // (2,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1'. 'Test1.M1' cannot implement 'I1.M1' because it does not have the matching return type of 'int'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.M1", "Test1.M1", "int").WithLocation(2, 15) } ); } private void ValidatePropertyImplementationInDerived_13(string source1, string source2, DiagnosticDescription[] expected1, DiagnosticDescription[] expected2 = null) { var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(expected1); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics(expected2 ?? expected1); } [Theory] [CombinatorialData] [WorkItem(20084, "https://github.com/dotnet/roslyn/issues/20084")] public void PropertyImplementationInDerived_14(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1<T> { " + modifiers + @"int M1 { get { System.Console.WriteLine(""I1.M1.get""); return 1; } set => System.Console.WriteLine(""I1.M1.set""); } } public interface I2<T> : I1<T> { " + implModifiers + @"int I1<T>.M1 { get { System.Console.WriteLine(""I2.I1.M1.get""); return 1; } set => System.Console.WriteLine(""I2.I1.M1.set""); } } public interface I3<T> : I1<T> {} "; var source2 = @" class Test1 : I1<int> { "; if (!isStatic) { source2 += @" static void Main() { I1<int> i1Int = new Test1(); I1<long> i1Long = new Test2(); "; } else { source2 += @" static void Main() { Test<Test1, Test2>(); } static void Test<i1Int, i1Long>() where i1Int : I1<int> where i1Long : I1<long> { "; } source2 += @" i1Int.M1 = i1Int.M1; i1Long.M1 = i1Long.M1; } } class Test2 : I2<long> {} "; ValidatePropertyImplementationInDerived_14(source1, source2, isStatic); } private void ValidatePropertyImplementationInDerived_14(string source1, string source2, bool isStatic = false) { var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = GetSingleProperty(i1); var i2 = FindType(m, "I2"); var i2m1 = GetSingleProperty(i2); var i2i1 = i2.InterfacesNoUseSiteDiagnostics().Single(); var i2i1m1 = GetSingleProperty(i2i1); var i3 = FindType(m, "I3"); var i3i1 = i3.InterfacesNoUseSiteDiagnostics().Single(); var i3i1m1 = GetSingleProperty(i3i1); VerifyFindImplementationForInterfaceMemberSame(i1m1, i1, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i2, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i2, i3i1m1); VerifyFindImplementationForInterfaceMemberSame(i2m1, i2, i2i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i3, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i3, i2i1m1); VerifyFindImplementationForInterfaceMemberEqual(i3i1m1, i3, i3i1m1); ValidateExplicitImplementation(i2m1, isStatic: isStatic); var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var test1i1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32)); var test1i1m1 = GetSingleProperty(i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32))); var test2 = m.GlobalNamespace.GetTypeMember("Test2"); var test2i1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)); var test2i1m1 = GetSingleProperty(i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64))); var test2i2 = i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)); var test2i2m1 = GetSingleProperty(i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64))); Assert.NotSame(test1i1, test1i1m1.ContainingType); Assert.NotSame(test2i1, test2i1m1.ContainingType); Assert.NotSame(test2i2, test2i2m1.ContainingType); VerifyFindImplementationForInterfaceMemberSame(null, test1i1, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test1i1m1, test1i1, test1i1m1); VerifyFindImplementationForInterfaceMemberEqual(test2i1m1, test2i1, test2i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test2i2, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test2i2m1, test2i2, test2i1m1); ValidateExplicitImplementation(test2i2m1, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test1i1m1, test1, test1i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test2, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test2i2m1, test2, test2i1m1); } CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1.get I1.M1.set I2.I1.M1.get I2.I1.M1.set ", verify: Verify(isStatic), symbolValidator: Validate); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1.get I1.M1.set I2.I1.M1.get I2.I1.M1.set ", verify: Verify(isStatic), symbolValidator: Validate); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1.get I1.M1.set I2.I1.M1.get I2.I1.M1.set ", verify: Verify(isStatic), symbolValidator: Validate); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_15(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get => throw null; private set => throw null;} } public interface I4 { " + modifiers + @"int M1 {set => throw null; private get => throw null;} } public interface I5 : I4 { } public interface I1 : I2, I5 { " + implModifiers + @"int I2.M1 { get { System.Console.WriteLine(""I2.M1""); return 1; } } " + implModifiers + @"int I4.M1 { set => System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source2 = @" class Test1 : I1 { "; if (!isStatic) { source2 += @" static void Main() { I2 i2 = new Test1(); I4 i4 = new Test1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source2 += @" _ = i2.M1; i4.M1 = 0; } } "; ValidatePropertyImplementationInDerived_01(source1, source2, isStatic); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_16(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get; set;} } public interface I4 { " + modifiers + @"int M1 {get; set;} } public interface I1 : I2, I4 { " + implModifiers + @"int I2.M1 { protected get => throw null; set => throw null; } " + implModifiers + @"protected int I4.M1 { get => throw null; set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic, // (16,19): error CS0106: The modifier 'protected' is not valid for this item // protected get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("protected").WithLocation(16, 19), // (19,22): error CS0106: The modifier 'protected' is not valid for this item // protected int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected").WithLocation(19, 22 + implModifiers.Length) ); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_17(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get; set;} } public interface I4 { " + modifiers + @"int M1 {get; set;} } public interface I1 : I2, I4 { " + implModifiers + @"int I2.M1 { get => throw null; protected internal set => throw null; } " + implModifiers + @"protected internal int I4.M1 { get => throw null; set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic, // (17,28): error CS0106: The modifier 'protected internal' is not valid for this item // protected internal set => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected internal").WithLocation(17, 28), // (19,31): error CS0106: The modifier 'protected internal' is not valid for this item // protected internal int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected internal").WithLocation(19, 31 + implModifiers.Length) ); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_18(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"int M1 {get; set;} } public interface I4 { " + modifiers + @"int M1 {get; set;} } public interface I1 : I2, I4 { " + implModifiers + @"int I2.M1 { private protected get => throw null; set => throw null; } " + implModifiers + @"private protected int I4.M1 { get => throw null; set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic, // (16,27): error CS0106: The modifier 'private protected' is not valid for this item // private protected get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private protected").WithLocation(16, 27), // (19,30): error CS0106: The modifier 'private protected' is not valid for this item // private protected int I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private protected").WithLocation(19, 30 + implModifiers.Length) ); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_19(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" #nullable enable public interface I1<T> { " + modifiers + @"int M1 {get; set;} } public interface I2 : I1<string> { } public interface I3 : I2, I1<string?> { " + implModifiers + @"int I1<string>.M1 { get => throw null!; set => throw null!; } " + implModifiers + @"int I1<string?>.M1 { get => throw null!; set => throw null!; } } "; var source2 = @" #nullable enable class Test1 : I3 { } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (13,18): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'I3' with different nullability of reference types. // public interface I3 : I2, I1<string?> Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "I3").WithArguments("I1<string?>", "I3").WithLocation(13, 18), // (13,18): error CS8646: 'I1<string>.M1' is explicitly implemented more than once. // public interface I3 : I2, I1<string?> Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "I3").WithArguments("I1<string>.M1").WithLocation(13, 18), // (13,18): error CS8646: 'I1<string?>.M1' is explicitly implemented more than once. // public interface I3 : I2, I1<string?> Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "I3").WithArguments("I1<string?>.M1").WithLocation(13, 18), // (21,21): error CS0102: The type 'I3' already contains a definition for 'I1<System.String>.M1' // int I1<string?>.M1 Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "M1").WithArguments("I3", "I1<System.String>.M1").WithLocation(21, 21 + implModifiers.Length) ); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (4,7): warning CS8645: 'I1<string?>' is already listed in the interface list on type 'Test1' with different nullability of reference types. // class Test1 : I3 Diagnostic(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList, "Test1").WithArguments("I1<string?>", "Test1").WithLocation(4, 7), // (4,15): error CS0535: 'Test1' does not implement interface member 'I1<string>.M1' // class Test1 : I3 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test1", "I1<string>.M1").WithLocation(4, 15), // (4,15): error CS0535: 'Test1' does not implement interface member 'I1<string?>.M1' // class Test1 : I3 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test1", "I1<string?>.M1").WithLocation(4, 15) ); var test1 = compilation2.GetTypeByMetadataName("Test1"); Assert.Equal(new[] { "I3", "I2", "I1<System.String>", "I1<System.String?>" }, test1.AllInterfacesNoUseSiteDiagnostics.Select(i => i.ToTestDisplayString())); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[2].GetMember("M1"))); Assert.Null(test1.FindImplementationForInterfaceMember(test1.AllInterfacesNoUseSiteDiagnostics[3].GetMember("M1"))); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_20(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"protected int M1 {get;} "; if (!isStatic) { source1 += @" public static void Test(I2 i2) { "; } else { source1 += @" public static void Test<i2>() where i2 : I2 { "; } source1 += @" _ = i2.M1; } } public interface I4 { " + modifiers + @"int M1 {get; protected set;} "; if (!isStatic) { source1 += @" public static void Test(I4 i4) { "; } else { source1 += @" public static void Test<i4>() where i4 : I4 { "; } source1 += @" i4.M1 = i4.M1; } } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { I2.Test(i2); I4.Test(i4); "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { I2.Test<i2>(); I4.Test<i4>(); "; } source1 += @" } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"int I2.M1 => Getter(); " + implModifiers + @"private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } " + implModifiers + @"int I4.M1 { get { System.Console.WriteLine(""I4.M1""); return 1; } set => System.Console.WriteLine(""I4.M1.set""); } } public interface I3 : I1 { } "; ValidatePropertyImplementationInDerived_11(source1, source2, isStatic); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_21(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"protected internal int M1 {get;} "; if (!isStatic) { source1 += @" public static void Test(I2 i2) { "; } else { source1 += @" public static void Test<i2>() where i2 : I2 { "; } source1 += @" _ = i2.M1; } } public interface I4 { " + modifiers + @"int M1 {get; protected internal set;} "; if (!isStatic) { source1 += @" public static void Test(I4 i4) { "; } else { source1 += @" public static void Test<i4>() where i4 : I4 { "; } source1 += @" i4.M1 = i4.M1; } } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { I2.Test(i2); I4.Test(i4); "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { I2.Test<i2>(); I4.Test<i4>(); "; } source1 += @" } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"int I2.M1 => Getter(); " + implModifiers + @"private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } " + implModifiers + @"int I4.M1 { get { System.Console.WriteLine(""I4.M1""); return 1; } set => System.Console.WriteLine(""I4.M1.set""); } } public interface I3 : I1 { } "; ValidatePropertyImplementationInDerived_11(source1, source2, isStatic); } [Theory] [CombinatorialData] public void PropertyImplementationInDerived_22(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"private protected int M1 {get;} "; if (!isStatic) { source1 += @" public static void Test(I2 i2) { "; } else { source1 += @" public static void Test<i2>() where i2 : I2 { "; } source1 += @" _ = i2.M1; } } public interface I4 { " + modifiers + @"int M1 {get; private protected set;} "; if (!isStatic) { source1 += @" public static void Test(I4 i4) { "; } else { source1 += @" public static void Test<i4>() where i4 : I4 { "; } source1 += @" i4.M1 = i4.M1; } } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { I2.Test(i2); I4.Test(i4); "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { I2.Test<i2>(); I4.Test<i4>(); "; } source1 += @" } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"int I2.M1 => Getter(); " + implModifiers + @"private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } " + implModifiers + @"int I4.M1 { get { System.Console.WriteLine(""I4.M1""); return 1; } set => System.Console.WriteLine(""I4.M1.set""); } } public interface I3 : I1 { } "; ValidatePropertyImplementationInDerived_11(source1, source2, isStatic, // (4,12): error CS0122: 'I2.M1' is inaccessible due to its protection level // int I2.M1 => Getter(); Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1").WithLocation(4, 12 + implModifiers.Length), // (11,12): error CS0122: 'I4.M1.set' is inaccessible due to its protection level // int I4.M1 Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I4.M1.set").WithLocation(11, 12 + implModifiers.Length) ); } [Theory] [CombinatorialData] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void EventImplementationInDerived_01(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"event System.Action M1; } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I5 : I4 { } public interface I1 : I2, I5 { " + implModifiers + @"event System.Action I2.M1 { add { System.Console.WriteLine(""I2.M1.add""); } remove { System.Console.WriteLine(""I2.M1.remove""); } } " + implModifiers + @"event System.Action I4.M1 { add => System.Console.WriteLine(""I4.M1.add""); remove => System.Console.WriteLine(""I4.M1.remove""); } } public interface I3 : I1 { } "; var source2 = @" class Test1 : I1 { "; if (!isStatic) { source2 += @" static void Main() { I2 i2 = new Test1(); I4 i4 = new Test1(); "; } else { source2 += @" static void Main() { Test<Test1, Test1>(); } static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source2 += @" i2.M1 += null; i2.M1 -= null; i4.M1 += null; i4.M1 -= null; } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateEventImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); void validateEventImplementationInDerived_01(ModuleSymbol m) { ValidateEventImplementationInDerived_01(m, isStatic); } } private static void ValidateEventImplementationInDerived_01(ModuleSymbol m, bool isStatic) { ValidateEventImplementationInDerived_01(m, i4M1IsAbstract: false, isStatic); } private static void ValidateEventImplementationInDerived_01(ModuleSymbol m, bool i4M1IsAbstract, bool isStatic) { var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var i1 = test1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I1").Single(); var i1i2m1 = i1.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I2.")).Single(); var i1i4m1 = i1.GetMembers().OfType<EventSymbol>().Where(p => p.Name.StartsWith("I4.")).Single(); var i2 = i1.InterfacesNoUseSiteDiagnostics().Where(i => i.Name == "I2").Single(); var i2m1 = i2.GetMembers().OfType<EventSymbol>().Single(); var i4 = i1.AllInterfacesNoUseSiteDiagnostics.Where(i => i.Name == "I4").Single(); var i4m1 = i4.GetMembers().OfType<EventSymbol>().Single(); var i3 = i1.ContainingNamespace.GetTypeMember("I3"); Assert.True(i1.IsAbstract); Assert.True(i1.IsMetadataAbstract); ValidateExplicitImplementation(i1i2m1, isStatic: isStatic); ValidateExplicitImplementation(i1i4m1, i4M1IsAbstract, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1i2m1); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1i4m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, test1, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4M1IsAbstract ? null : i1i4m1, test1, i4m1); VerifyFindImplementationForInterfaceMemberSame(null, i1, i1i2m1); VerifyFindImplementationForInterfaceMemberSame(null, i1, i1i4m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, i1, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4M1IsAbstract ? null : i1i4m1, i1, i4m1); VerifyFindImplementationForInterfaceMemberSame(null, i2, i2m1); VerifyFindImplementationForInterfaceMemberSame(null, i4, i4m1); VerifyFindImplementationForInterfaceMemberSame(i1i2m1, i3, i2m1); VerifyFindImplementationForInterfaceMemberSame(i4M1IsAbstract ? null : i1i4m1, i3, i4m1); } private static void VerifyFindImplementationForInterfaceMemberSame(EventSymbol expected, NamedTypeSymbol implementingType, EventSymbol interfaceEvent) { Assert.Same(expected, implementingType.FindImplementationForInterfaceMember(interfaceEvent)); ValidateAccessor(expected?.AddMethod, interfaceEvent.AddMethod); ValidateAccessor(expected?.RemoveMethod, interfaceEvent.RemoveMethod); void ValidateAccessor(MethodSymbol accessor, MethodSymbol interfaceAccessor) { if ((object)interfaceAccessor != null) { Assert.Same(accessor, implementingType.FindImplementationForInterfaceMember(interfaceAccessor)); } else { Assert.Null(accessor); } } } private static void VerifyFindImplementationForInterfaceMemberEqual(EventSymbol expected, NamedTypeSymbol implementingType, EventSymbol interfaceEvent) { Assert.Equal(expected, implementingType.FindImplementationForInterfaceMember(interfaceEvent)); ValidateAccessor(expected?.AddMethod, interfaceEvent.AddMethod); ValidateAccessor(expected?.RemoveMethod, interfaceEvent.RemoveMethod); void ValidateAccessor(MethodSymbol accessor, MethodSymbol interfaceAccessor) { if ((object)interfaceAccessor != null) { Assert.Equal(accessor, implementingType.FindImplementationForInterfaceMember(interfaceAccessor)); } else { Assert.Null(accessor); } } } private static void ValidateExplicitImplementation(EventSymbol m1, bool isAbstract = false, bool isStatic = false) { Assert.Equal(isAbstract, m1.IsAbstract); Assert.False(m1.IsVirtual); Assert.Equal(isAbstract, m1.IsSealed); Assert.Equal(isStatic, m1.IsStatic); Assert.False(m1.IsExtern); Assert.False(m1.IsOverride); Assert.Equal(Accessibility.Private, m1.DeclaredAccessibility); ValidateAccessor(m1.AddMethod, isAbstract); ValidateAccessor(m1.RemoveMethod, isAbstract); void ValidateAccessor(MethodSymbol accessor, bool isAbstract) { if ((object)accessor != null) { ValidateExplicitImplementation(accessor, isAbstract, isStatic); } } } [Fact] public void EventImplementationInDerived_02() { var source1 = @" public interface I2 { event System.Action M1; } public interface I4 { event System.Action M1; } public interface I1 : I2, I4 { event System.Action I2.M1 { add => throw null; remove => throw null; } event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (16,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // add => throw null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(16, 9), // (17,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // remove => throw null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(17, 9), // (22,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // add => throw null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "add").WithArguments("default interface implementation", "8.0").WithLocation(22, 9), // (23,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // remove => throw null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "remove").WithArguments("default interface implementation", "8.0").WithLocation(23, 9) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, isStatic: false); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (6,15): error CS8506: 'I1.I2.M1.remove' cannot implement interface member 'I2.M1.remove' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.remove", "I2.M1.remove", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15), // (6,15): error CS8506: 'I1.I2.M1.add' cannot implement interface member 'I2.M1.add' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.add", "I2.M1.add", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15), // (6,15): error CS8506: 'I1.I4.M1.remove' cannot implement interface member 'I4.M1.remove' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.remove", "I4.M1.remove", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15), // (6,15): error CS8506: 'I1.I4.M1.add' cannot implement interface member 'I4.M1.add' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.add", "I4.M1.add", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15) ); ValidateEventImplementationInDerived_01(compilation2.SourceModule, isStatic: false); } [Fact] public void EventImplementationInDerived_Static_02() { var source1 = @" public interface I2 { static abstract event System.Action M1; } public interface I4 { static abstract event System.Action M1; } public interface I1 : I2, I4 { static event System.Action I2.M1 { add => throw null; remove => throw null; } static event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular10, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,41): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract event System.Action M1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(4, 41), // (9,41): error CS8703: The modifier 'abstract' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static abstract event System.Action M1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("abstract", "10.0", "11.0").WithLocation(9, 41), // (14,35): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static event System.Action I2.M1 Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(14, 35), // (20,35): error CS8703: The modifier 'static' is not valid for this item in C# 10.0. Please use language version '11.0' or greater. // static event System.Action I4.M1 Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "M1").WithArguments("static", "10.0", "11.0").WithLocation(20, 35) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, isStatic: true); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular10, targetFramework: TargetFramework.Net60); compilation2.VerifyDiagnostics( // (6,15): error CS8706: 'I1.I2.M1.add' cannot implement interface member 'I2.M1.add' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.add", "I2.M1.add", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15), // (6,15): error CS8706: 'I1.I2.M1.remove' cannot implement interface member 'I2.M1.remove' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.remove", "I2.M1.remove", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15), // (6,15): error CS8706: 'I1.I4.M1.add' cannot implement interface member 'I4.M1.add' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.add", "I4.M1.add", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15), // (6,15): error CS8706: 'I1.I4.M1.remove' cannot implement interface member 'I4.M1.remove' in type 'Test1' because feature 'static abstract members in interfaces' is not available in C# 10.0. Please use language version '11.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.remove", "I4.M1.remove", "Test1", "static abstract members in interfaces", "10.0", "11.0").WithLocation(6, 15) ); ValidateEventImplementationInDerived_01(compilation2.SourceModule, isStatic: true); } [Fact] public void EventImplementationInDerived_03() { var source1 = @" public interface I2 { event System.Action M1; } public interface I4 { event System.Action M1; } public interface I1 : I2, I4 { event System.Action I2.M1 { add => throw null; remove => throw null; } event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular, skipUsesIsNullable: true); Assert.False(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (16,9): error CS8501: Target runtime doesn't support default interface implementation. // add => throw null; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(16, 9), // (17,9): error CS8501: Target runtime doesn't support default interface implementation. // remove => throw null; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(17, 9), // (22,9): error CS8501: Target runtime doesn't support default interface implementation. // add => throw null; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "add").WithLocation(22, 9), // (23,9): error CS8501: Target runtime doesn't support default interface implementation. // remove => throw null; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "remove").WithLocation(23, 9) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, isStatic: false); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular); Assert.False(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (6,15): error CS8502: 'I1.I2.M1.remove' cannot implement interface member 'I2.M1.remove' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.remove", "I2.M1.remove", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I2.M1.add' cannot implement interface member 'I2.M1.add' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.M1.add", "I2.M1.add", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I4.M1.remove' cannot implement interface member 'I4.M1.remove' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.remove", "I4.M1.remove", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I4.M1.add' cannot implement interface member 'I4.M1.add' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I4.M1.add", "I4.M1.add", "Test1").WithLocation(6, 15) ); } [Fact] public void EventImplementationInDerived_Static_03() { var source1 = @" public interface I2 { static abstract event System.Action M1; } public interface I4 { static abstract event System.Action M1; } public interface I1 : I2, I4 { static event System.Action I2.M1 { add => throw null; remove => throw null; } static event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.RegularPreview, skipUsesIsNullable: true); compilation1.VerifyDiagnostics( // (4,41): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract event System.Action M1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(4, 41), // (9,41): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static abstract event System.Action M1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(9, 41), // (14,35): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static event System.Action I2.M1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(14, 35), // (20,35): error CS8919: Target runtime doesn't support static abstract members in interfaces. // static event System.Action I4.M1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfaces, "M1").WithLocation(20, 35) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, isStatic: true); var source2 = @" public interface I3 : I1 { } class Test1 : I1 {} "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, targetFramework: TargetFramework.Net50, parseOptions: TestOptions.RegularPreview); compilation2.VerifyDiagnostics( // (6,15): error CS8929: 'I1.I2.M1.add' cannot implement interface member 'I2.M1.add' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I2.M1.add", "I2.M1.add", "Test1").WithLocation(6, 15), // (6,15): error CS8929: 'I1.I2.M1.remove' cannot implement interface member 'I2.M1.remove' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I2.M1.remove", "I2.M1.remove", "Test1").WithLocation(6, 15), // (6,15): error CS8929: 'I1.I4.M1.add' cannot implement interface member 'I4.M1.add' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I4.M1.add", "I4.M1.add", "Test1").WithLocation(6, 15), // (6,15): error CS8929: 'I1.I4.M1.remove' cannot implement interface member 'I4.M1.remove' in type 'Test1' because the target runtime doesn't support static abstract members in interfaces. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportStaticAbstractMembersInInterfacesForMember, "I1").WithArguments("I1.I4.M1.remove", "I4.M1.remove", "Test1").WithLocation(6, 15) ); } [Theory] [CombinatorialData] public void EventImplementationInDerived_04(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"event System.Action M1; } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I1 : I2, I4 { " + implModifiers + @"event System.Action I2.M1 { add; remove; } " + implModifiers + @"event System.Action I4.M1 { add; remove {} } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (16,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(16, 12), // (17,15): error CS0073: An add or remove accessor must have a body // remove; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(17, 15), // (21,12): error CS0073: An add or remove accessor must have a body // add; Diagnostic(ErrorCode.ERR_AddRemoveMustHaveBody, ";").WithLocation(21, 12) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, isStatic); } [Theory] [CombinatorialData] public void EventImplementationInDerived_05(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"event System.Action M1; } public interface I1 { " + implModifiers + @"event System.Action I2.M1 { add => throw null; remove => throw null; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (9,25): error CS0540: 'I1.I2.M1': containing type does not implement interface 'I2' // event System.Action I2.M1 Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I2").WithArguments("I1.I2.M1", "I2").WithLocation(9, 25 + implModifiers.Length) ); } [Fact] public void EventImplementationInDerived_06() { var source1 = @" public interface I2 { event System.Action M1; } public interface I4 { event System.Action M1; } public interface I1 : I2, I4 { public static event System.Action I2.M1 { add => throw null; remove => throw null; } internal virtual event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,42): error CS0106: The modifier 'public' is not valid for this item // public static event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("public").WithLocation(14, 42), // (14,42): error CS0539: 'I1.M1' in explicit interface declaration is not found among members of the interface that can be implemented // public static event System.Action I2.M1 Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.M1").WithLocation(14, 42), // (19,45): error CS0106: The modifier 'internal' is not valid for this item // internal virtual event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("internal").WithLocation(19, 45), // (19,45): error CS0106: The modifier 'virtual' is not valid for this item // internal virtual event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("virtual").WithLocation(19, 45), // (30,15): error CS0535: 'Test1' does not implement interface member 'I2.M1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I2.M1").WithLocation(30, 15) ); } [Fact] public void EventImplementationInDerived_Static_06() { var source1 = @" public interface I2 { static abstract event System.Action M1; } public interface I4 { static abstract event System.Action M1; } public interface I1 : I2, I4 { public event System.Action I2.M1 { add => throw null; remove => throw null; } static internal virtual event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (14,35): error CS0106: The modifier 'public' is not valid for this item // public event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("public").WithLocation(14, 35), // (14,35): error CS0539: 'I1.M1' in explicit interface declaration is not found among members of the interface that can be implemented // public event System.Action I2.M1 Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "M1").WithArguments("I1.M1").WithLocation(14, 35), // (19,52): error CS0106: The modifier 'internal' is not valid for this item // static internal virtual event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("internal").WithLocation(19, 52), // (19,52): error CS0106: The modifier 'virtual' is not valid for this item // static internal virtual event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("virtual").WithLocation(19, 52), // (30,15): error CS0535: 'Test1' does not implement interface member 'I2.M1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I2.M1").WithLocation(30, 15) ); } [Theory] [CombinatorialData] public void EventImplementationInDerived_07(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"event System.Action M1; } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I1 : I2, I4 { " + implModifiers + @"private sealed event System.Action I2.M1 { add => throw null; remove => throw null; } " + implModifiers + @"protected abstract event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,43): error CS0106: The modifier 'sealed' is not valid for this item // private sealed event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("sealed").WithLocation(14, 43 + implModifiers.Length), // (14,43): error CS0106: The modifier 'private' is not valid for this item // private sealed event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private").WithLocation(14, 43 + implModifiers.Length), // (19,47): error CS0106: The modifier 'protected' is not valid for this item // protected abstract event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected").WithLocation(19, 47 + implModifiers.Length), // (20,5): error CS8712: 'I1.I4.M1': abstract event cannot use event accessor syntax // { Diagnostic(ErrorCode.ERR_AbstractEventHasAccessors, "{").WithArguments("I1.I4.M1").WithLocation(20, 5), // (30,15): error CS0535: 'Test1' does not implement interface member 'I4.M1' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I4.M1").WithLocation(30, 15) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, i4M1IsAbstract: true, isStatic); } [Theory] [CombinatorialData] public void EventImplementationInDerived_08(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"event System.Action M1; } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I1 : I2, I4 { " + implModifiers + @"private protected extern event System.Action I2.M1 { add => throw null; remove => throw null; } " + implModifiers + @"internal protected override event System.Action I4.M1 { add => throw null; remove => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (14,53): error CS0106: The modifier 'private protected' is not valid for this item // private protected extern event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("private protected").WithLocation(14, 53 + implModifiers.Length), // (14,53): error CS0106: The modifier 'extern' is not valid for this item // private protected extern event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("extern").WithLocation(14, 53 + implModifiers.Length), // (19,56): error CS0106: The modifier 'protected internal' is not valid for this item // internal protected override event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("protected internal").WithLocation(19, 56 + implModifiers.Length), // (19,56): error CS0106: The modifier 'override' is not valid for this item // internal protected override event System.Action I4.M1 Diagnostic(ErrorCode.ERR_BadMemberFlag, "M1").WithArguments("override").WithLocation(19, 56 + implModifiers.Length) ); ValidateEventImplementationInDerived_01(compilation1.SourceModule, isStatic); } [Theory] [CombinatorialData] public void EventImplementationInDerived_10(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"event System.Action M1; " + modifiers + @"event System.Action M2; } public interface I2 : I1 { " + implModifiers + @"event System.Action I1.M1 { add => throw null; } " + implModifiers + @"event System.Action I1.M2 { remove => throw null; } } class Test1 : I2 {} public interface I3 { " + modifiers + @"event System.Action M1; } public interface I4 : I3 { " + implModifiers + @"event System.Action I3.M1; } class Test2 : I4 {} public interface I5 : I3 { " + implModifiers + @"event System.Action I3.M1 } class Test3 : I5 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics( // (30,28): error CS0071: An explicit interface implementation of an event must use event accessor syntax // event System.Action I3.M1; Diagnostic(ErrorCode.ERR_ExplicitEventFieldImpl, "M1").WithLocation(30, 28 + implModifiers.Length), // (10,28): error CS0065: 'I2.I1.M1': event property must have both add and remove accessors // event System.Action I1.M1 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "M1").WithArguments("I2.I1.M1").WithLocation(10, 28 + implModifiers.Length), // (14,28): error CS0065: 'I2.I1.M2': event property must have both add and remove accessors // event System.Action I1.M2 Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "M2").WithArguments("I2.I1.M2").WithLocation(14, 28 + implModifiers.Length), // (33,15): error CS0535: 'Test2' does not implement interface member 'I3.M1' // class Test2 : I4 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I4").WithArguments("Test2", "I3.M1").WithLocation(33, 15), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M1' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.M1").WithLocation(20, 15), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.M2' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.M2").WithLocation(20, 15), // (38,27): error CS0071: An explicit interface implementation of an event must use event accessor syntax // event System.Action I3.M1 Diagnostic(ErrorCode.ERR_ExplicitEventFieldImpl, ".").WithLocation(38, 27 + implModifiers.Length), // (41,15): error CS0535: 'Test3' does not implement interface member 'I3.M1' // class Test3 : I5 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I5").WithArguments("Test3", "I3.M1").WithLocation(41, 15) ); } [Theory] [CombinatorialData] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void EventImplementationInDerived_11(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"internal event System.Action M1; } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { "; } source1 += @" i2.M1 += null; i2.M1 -= null; i4.M1 += null; i4.M1 -= null; } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"event System.Action I2.M1 { add { System.Console.WriteLine(""I2.M1.add""); } remove => System.Console.WriteLine(""I2.M1.remove""); } " + implModifiers + @"event System.Action I4.M1 { add { System.Console.WriteLine(""I4.M1.add""); } remove => System.Console.WriteLine(""I4.M1.remove""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { TestHelper.Test(new Test1(), new Test1()); "; } else { source3 += @" static void Main() { TestHelper.Test<Test1, Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateEventImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); var compilation2 = CreateCompilation(source3, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); var compilation3 = CreateCompilation(source3, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); var compilation5 = CreateCompilation(source2 + source3, new[] { compilation4.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics( // (4,28): error CS0122: 'I2.M1' is inaccessible due to its protection level // event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1").WithLocation(4, 28 + implModifiers.Length) ); var compilation6 = CreateCompilation(source2 + source3, new[] { compilation4.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation6.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation6.SourceModule); compilation6.VerifyDiagnostics( // (4,28): error CS0122: 'I2.M1' is inaccessible due to its protection level // event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1").WithLocation(4, 28 + implModifiers.Length) ); void validateEventImplementationInDerived_01(ModuleSymbol m) { ValidateEventImplementationInDerived_01(m, isStatic); } } [Theory] [CombinatorialData] [WorkItem(20083, "https://github.com/dotnet/roslyn/issues/20083")] public void EventImplementationInDerived_12(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"event System.Action M1 { add => throw null; remove => throw null;} } public interface I2 : I1 { " + implModifiers + @"event System.Action I1.M1 { add { System.Console.WriteLine(""I2.I1.M1.add""); } remove { System.Console.WriteLine(""I2.I1.M1.remove""); } } } public interface I3 : I1 { " + implModifiers + @"event System.Action I1.M1 { add { System.Console.WriteLine(""I3.I1.M1.add""); } remove { System.Console.WriteLine(""I3.I1.M1.remove""); } } } public interface I4 : I1 { " + implModifiers + @"event System.Action I1.M1 { add { System.Console.WriteLine(""I4.I1.M1.add""); } remove { System.Console.WriteLine(""I4.I1.M1.remove""); } } } public interface I5 : I2, I3 { " + implModifiers + @"event System.Action I1.M1 { add { System.Console.WriteLine(""I5.I1.M1.add""); } remove { System.Console.WriteLine(""I5.I1.M1.remove""); } } } public interface I6 : I1, I2, I3, I5 {} "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate1(compilation1.SourceModule); void Validate1(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = GetSingleEvent(i1); var i2 = FindType(m, "I2"); var i2m1 = GetSingleEvent(i2); var i5 = FindType(m, "I5"); var i5m1 = GetSingleEvent(i5); var i6 = FindType(m, "I6"); ValidateExplicitImplementation(i2m1, isStatic: isStatic); ValidateExplicitImplementation(i5m1, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(i1m1, i1, i1m1); VerifyFindImplementationForInterfaceMemberSame(i2m1, i2, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, i5, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, i6, i1m1); } CompileAndVerify(compilation1, verify: Verify(isStatic), symbolValidator: Validate1); var refs1 = new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }; var source2 = @" public interface I7 : I2, I3 {} public interface I8 : I1, I2, I3, I5, I4 {} "; var source3 = @" class Test1 : I2, I3 {} class Test2 : I7 {} class Test3 : I1, I2, I3, I4 {} class Test4 : I1, I2, I3, I5, I4 {} class Test5 : I8 {} "; var source4 = @" class Test5 : I2 {} class Test6 : I1, I2, I3, I5 {} class Test7 : I6 { "; if (!isStatic) { source4 += @" static void Main() { I1 i5 = new Test5(); I1 i6 = new Test6(); I1 i7 = new Test7(); "; } else { source4 += @" static void Main() { Test<Test5, Test6, Test7>(); } static void Test<i5, i6, i7>() where i5 : I1 where i6 : I1 where i7 : I1 { "; } source4 += @" i5.M1 += null; i5.M1 -= null; i6.M1 += null; i6.M1 -= null; i7.M1 += null; i7.M1 -= null; } } "; var source5 = @" class Test8 : I2, I3 { " + implModifiers + @"event System.Action I1.M1 { add { System.Console.WriteLine(""Test8.I1.M1.add""); } remove { System.Console.WriteLine(""Test8.I1.M1.remove""); } } "; if (!isStatic) { source5 += @" static void Main() { I1 i8 = new Test8(); I1 i9 = new Test9(); I1 i10 = new Test10(); I1 i11 = new Test11(); I1 i12 = new Test12(); "; } else { source5 += @" static void Main() { Test<Test8, Test9, Test10, Test11, Test12>(); } static void Test<i8, i9, i10, i11, i12>() where i8 : I1 where i9 : I1 where i10 : I1 where i11 : I1 where i12 : I1 { "; } source5 += @" i8.M1 += null; i8.M1 -= null; i9.M1 += null; i9.M1 -= null; i10.M1 += null; i10.M1 -= null; i11.M1 += null; i11.M1 -= null; i12.M1 += null; i12.M1 -= null; } } class Test9 : I7 { " + implModifiers + @"event System.Action I1.M1 { add { System.Console.WriteLine(""Test9.I1.M1.add""); } remove { System.Console.WriteLine(""Test9.I1.M1.remove""); } } } class Test10 : I1, I2, I3, I4 { " + implModifiers + @"public event System.Action M1 { add { System.Console.WriteLine(""Test10.M1.add""); } remove { System.Console.WriteLine(""Test10.M1.remove""); } } } class Test11 : I1, I2, I3, I5, I4 { " + implModifiers + @"public event System.Action M1 { add { System.Console.WriteLine(""Test11.M1.add""); } remove { System.Console.WriteLine(""Test11.M1.remove""); } } } class Test12 : I8 { " + implModifiers + @"public " + (isStatic ? "" : "virtual") + @" event System.Action M1 { add { System.Console.WriteLine(""Test12.M1.add""); } remove { System.Console.WriteLine(""Test12.M1.remove""); } } } "; foreach (var ref1 in refs1) { var compilation2 = CreateCompilation(source2, new[] { ref1 }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); // According to LDM decision captured at https://github.com/dotnet/csharplang/blob/main/meetings/2017/LDM-2017-06-14.md, // we do not require interfaces to have a most specific implementation of all members. Therefore, there are no // errors in this compilation. compilation2.VerifyDiagnostics(); Validate2(compilation2.SourceModule); void Validate2(ModuleSymbol m) { Validate1(m); var i1 = FindType(m, "I1"); var i1m1 = GetSingleEvent(i1); var i7 = FindType(m, "I7"); var i8 = FindType(m, "I8"); VerifyFindImplementationForInterfaceMemberSame(null, i7, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i8, i1m1); } CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: Validate2); compilation2 = CreateCompilation(source2, new[] { ref1 }, options: TestOptions.DebugDll, parseOptions: isStatic ? TestOptions.Regular10 : TestOptions.Regular7_3, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics(); Validate2(compilation2.SourceModule); CompileAndVerify(compilation2, verify: Verify(isStatic), symbolValidator: Validate2); var refs2 = new[] { compilation2.ToMetadataReference(), compilation2.EmitToImageReference() }; var compilation4 = CreateCompilation(source4, new[] { ref1 }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); Validate4(compilation4.SourceModule); void Validate4(ModuleSymbol m) { Validate1(m); var i1 = FindType(m, "I1"); var i1m1 = GetSingleEvent(i1); var i2 = FindType(m, "I2"); var i2m1 = GetSingleEvent(i2); var i5 = FindType(m, "I5"); var i5m1 = GetSingleEvent(i5); var test5 = FindType(m, "Test5"); var test6 = FindType(m, "Test6"); var test7 = FindType(m, "Test7"); VerifyFindImplementationForInterfaceMemberSame(i2m1, test5, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, test6, i1m1); VerifyFindImplementationForInterfaceMemberSame(i5m1, test7, i1m1); } CompileAndVerify(compilation4, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.I1.M1.add I2.I1.M1.remove I5.I1.M1.add I5.I1.M1.remove I5.I1.M1.add I5.I1.M1.remove " , verify: Verify(isStatic), symbolValidator: Validate4); foreach (var ref2 in refs2) { var compilation3 = CreateCompilation(source3, new[] { ref1, ref2 }, options: TestOptions.DebugDll.WithConcurrentBuild(false), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(2, 15), // (5,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test2 : I7 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I7").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(5, 15), // (8,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test3 : I1, I2, I3, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(8, 15), // (11,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I5.I1.M1', nor 'I4.I1.M1' are most specific. // class Test4 : I1, I2, I3, I5, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.M1", "I5.I1.M1", "I4.I1.M1").WithLocation(11, 15), // (14,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I5.I1.M1', nor 'I4.I1.M1' are most specific. // class Test5 : I8 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I8").WithArguments("I1.M1", "I5.I1.M1", "I4.I1.M1").WithLocation(14, 15) ); Validate3(compilation3.SourceModule); void Validate3(ModuleSymbol m) { Validate1(m); Validate2(m); var i1 = FindType(m, "I1"); var i1m1 = GetSingleEvent(i1); var test1 = FindType(m, "Test1"); var test2 = FindType(m, "Test2"); var test3 = FindType(m, "Test3"); var test4 = FindType(m, "Test4"); var test5 = FindType(m, "Test5"); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test2, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test3, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test4, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test5, i1m1); } var compilation5 = CreateCompilation(source5, new[] { ref1, ref2 }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation5.VerifyDiagnostics(); Validate5(compilation5.SourceModule); void Validate5(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = GetSingleEvent(i1); var test8 = FindType(m, "Test8"); var test9 = FindType(m, "Test9"); var test10 = FindType(m, "Test10"); var test11 = FindType(m, "Test11"); var test12 = FindType(m, "Test12"); VerifyFindImplementationForInterfaceMemberSame(GetSingleEvent(test8), test8, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleEvent(test9), test9, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleEvent(test10), test10, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleEvent(test11), test11, i1m1); VerifyFindImplementationForInterfaceMemberSame(GetSingleEvent(test12), test12, i1m1); } CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"Test8.I1.M1.add Test8.I1.M1.remove Test9.I1.M1.add Test9.I1.M1.remove Test10.M1.add Test10.M1.remove Test11.M1.add Test11.M1.remove Test12.M1.add Test12.M1.remove ", verify: Verify(isStatic), symbolValidator: Validate5); } } } [Theory] [CombinatorialData] public void EventImplementationInDerived_13(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1 { " + modifiers + @"event System.Action M1; } public interface I2 : I1 { " + implModifiers + @"event System.Action I1.M1 { add => throw null; remove => throw null;} } public interface I3 : I1 { " + implModifiers + @"event System.Action I1.M1 { add => throw null; remove => throw null;} } "; var source2 = @" class Test1 : I2, I3 { " + implModifiers + @"public event System.Action<object> M1 { add => throw null; remove => throw null;} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation2.VerifyDiagnostics( // (2,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1'. 'Test1.M1' cannot implement 'I1.M1' because it does not have the matching return type of 'Action'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.M1", "Test1.M1", "System.Action").WithLocation(2, 15) ); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation3.VerifyDiagnostics( // (2,15): error CS8505: Interface member 'I1.M1' does not have a most specific implementation. Neither 'I2.I1.M1', nor 'I3.I1.M1' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.M1", "I2.I1.M1", "I3.I1.M1").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.M1'. 'Test1.M1' cannot implement 'I1.M1' because it does not have the matching return type of 'Action'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.M1", "Test1.M1", "System.Action").WithLocation(2, 15) ); } [Theory] [CombinatorialData] [WorkItem(20084, "https://github.com/dotnet/roslyn/issues/20084")] public void EventImplementationInDerived_14(bool isStatic) { string modifiers = isStatic ? "static virtual " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I1<T> { " + modifiers + @"event System.Action M1 { add { System.Console.WriteLine(""I1.M1.add""); } remove => System.Console.WriteLine(""I1.M1.remove""); } } public interface I2<T> : I1<T> { " + implModifiers + @"event System.Action I1<T>.M1 { add { System.Console.WriteLine(""I2.I1.M1.add""); } remove => System.Console.WriteLine(""I2.I1.M1.remove""); } } public interface I3<T> : I1<T> {} "; var source2 = @" class Test1 : I1<int> { "; if (!isStatic) { source2 += @" static void Main() { I1<int> i1Int = new Test1(); I1<long> i1Long = new Test2(); "; } else { source2 += @" static void Main() { Test<Test1, Test2>(); } static void Test<i1Int, i1Long>() where i1Int : I1<int> where i1Long : I1<long> { "; } source2 += @" i1Int.M1 += null; i1Int.M1 -= null; i1Long.M1 += null; i1Long.M1 -= null; } } class Test2 : I2<long> {} "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); Validate(compilation1.SourceModule); void Validate(ModuleSymbol m) { var i1 = FindType(m, "I1"); var i1m1 = GetSingleEvent(i1); var i2 = FindType(m, "I2"); var i2m1 = GetSingleEvent(i2); var i2i1 = i2.InterfacesNoUseSiteDiagnostics().Single(); var i2i1m1 = GetSingleEvent(i2i1); var i3 = FindType(m, "I3"); var i3i1 = i3.InterfacesNoUseSiteDiagnostics().Single(); var i3i1m1 = GetSingleEvent(i3i1); VerifyFindImplementationForInterfaceMemberSame(i1m1, i1, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i2, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i2, i3i1m1); VerifyFindImplementationForInterfaceMemberSame(i2m1, i2, i2i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i3, i1m1); VerifyFindImplementationForInterfaceMemberSame(null, i3, i2i1m1); VerifyFindImplementationForInterfaceMemberEqual(i3i1m1, i3, i3i1m1); ValidateExplicitImplementation(i2m1, isStatic: isStatic); var test1 = m.GlobalNamespace.GetTypeMember("Test1"); var test1i1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32)); var test1i1m1 = GetSingleEvent(i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int32))); var test2 = m.GlobalNamespace.GetTypeMember("Test2"); var test2i1 = i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)); var test2i1m1 = GetSingleEvent(i1.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64))); var test2i2 = i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64)); var test2i2m1 = GetSingleEvent(i2.Construct(m.ContainingAssembly.GetSpecialType(SpecialType.System_Int64))); Assert.NotSame(test1i1, test1i1m1.ContainingType); Assert.NotSame(test2i1, test2i1m1.ContainingType); Assert.NotSame(test2i2, test2i2m1.ContainingType); VerifyFindImplementationForInterfaceMemberSame(null, test1i1, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test1i1m1, test1i1, test1i1m1); VerifyFindImplementationForInterfaceMemberEqual(test2i1m1, test2i1, test2i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test2i2, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test2i2m1, test2i2, test2i1m1); ValidateExplicitImplementation(test2i2m1, isStatic: isStatic); VerifyFindImplementationForInterfaceMemberSame(null, test1, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test1i1m1, test1, test1i1m1); VerifyFindImplementationForInterfaceMemberSame(null, test2, i1m1); VerifyFindImplementationForInterfaceMemberEqual(test2i2m1, test2, test2i1m1); } CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1.add I1.M1.remove I2.I1.M1.add I2.I1.M1.remove ", verify: Verify(isStatic), symbolValidator: Validate); var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1.add I1.M1.remove I2.I1.M1.add I2.I1.M1.remove ", verify: Verify(isStatic), symbolValidator: Validate); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation3.Assembly.RuntimeSupportsDefaultInterfaceImplementation); Validate(compilation3.SourceModule); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I1.M1.add I1.M1.remove I2.I1.M1.add I2.I1.M1.remove ", verify: Verify(isStatic), symbolValidator: Validate); } [Theory] [CombinatorialData] public void EventImplementationInDerived_15(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"protected event System.Action M1; "; if (!isStatic) { source1 += @" public static void Test(I2 i2) { "; } else { source1 += @" public static void Test<i2>() where i2 : I2 { "; } source1 += @" i2.M1 += null; i2.M1 -= null; } } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { I2.Test(i2); "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { I2.Test<i2>(); "; } source1 += @" i4.M1 += null; i4.M1 -= null; } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"event System.Action I2.M1 { add { System.Console.WriteLine(""I2.M1.add""); } remove => System.Console.WriteLine(""I2.M1.remove""); } " + implModifiers + @"event System.Action I4.M1 { add { System.Console.WriteLine(""I4.M1.add""); } remove => System.Console.WriteLine(""I4.M1.remove""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { TestHelper.Test(new Test1(), new Test1()); "; } else { source3 += @" static void Main() { TestHelper.Test<Test1, Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateEventImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics(); CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); } void validateEventImplementationInDerived_01(ModuleSymbol m) { ValidateEventImplementationInDerived_01(m, isStatic); } } [Theory] [CombinatorialData] public void EventImplementationInDerived_16(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"protected internal event System.Action M1; "; if (!isStatic) { source1 += @" public static void Test(I2 i2) { "; } else { source1 += @" public static void Test<i2>() where i2 : I2 { "; } source1 += @" i2.M1 += null; i2.M1 -= null; } } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { I2.Test(i2); "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { I2.Test<i2>(); "; } source1 += @" i4.M1 += null; i4.M1 -= null; } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"event System.Action I2.M1 { add { System.Console.WriteLine(""I2.M1.add""); } remove => System.Console.WriteLine(""I2.M1.remove""); } " + implModifiers + @"event System.Action I4.M1 { add { System.Console.WriteLine(""I4.M1.add""); } remove => System.Console.WriteLine(""I4.M1.remove""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { TestHelper.Test(new Test1(), new Test1()); "; } else { source3 += @" static void Main() { TestHelper.Test<Test1, Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateEventImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics(); CompileAndVerify(compilation5, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); } void validateEventImplementationInDerived_01(ModuleSymbol m) { ValidateEventImplementationInDerived_01(m, isStatic); } } [Theory] [CombinatorialData] public void EventImplementationInDerived_17(bool isStatic) { string modifiers = isStatic ? "static abstract " : ""; string implModifiers = isStatic ? "static " : ""; var source1 = @" public interface I2 { " + modifiers + @"private protected event System.Action M1; "; if (!isStatic) { source1 += @" public static void Test(I2 i2) { "; } else { source1 += @" public static void Test<i2>() where i2 : I2 { "; } source1 += @" i2.M1 += null; i2.M1 -= null; } } public interface I4 { " + modifiers + @"event System.Action M1; } public interface I5 : I4 { } public class TestHelper { "; if (!isStatic) { source1 += @" public static void Test(I2 i2, I4 i4) { I2.Test(i2); "; } else { source1 += @" public static void Test<i2, i4>() where i2 : I2 where i4 : I4 { I2.Test<i2>(); "; } source1 += @" i4.M1 += null; i4.M1 -= null; } } "; var source2 = @" public interface I1 : I2, I5 { " + implModifiers + @"event System.Action I2.M1 { add { System.Console.WriteLine(""I2.M1.add""); } remove => System.Console.WriteLine(""I2.M1.remove""); } " + implModifiers + @"event System.Action I4.M1 { add { System.Console.WriteLine(""I4.M1.add""); } remove => System.Console.WriteLine(""I4.M1.remove""); } } public interface I3 : I1 { } "; var source3 = @" class Test1 : I1 { "; if (!isStatic) { source3 += @" static void Main() { TestHelper.Test(new Test1(), new Test1()); "; } else { source3 += @" static void Main() { TestHelper.Test<Test1, Test1>(); "; } source3 += @" } } "; var compilation1 = CreateCompilation(source1 + source2 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); validateEventImplementationInDerived_01(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation2 = CreateCompilation(source3, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation2.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation2.SourceModule); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !Execute(isStatic, haveImplementationInDerivedInterface: true) ? null : @"I2.M1.add I2.M1.remove I4.M1.add I4.M1.remove ", verify: Verify(isStatic), symbolValidator: validateEventImplementationInDerived_01); } var compilation4 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics(); foreach (var reference in new[] { compilation4.ToMetadataReference(), compilation4.EmitToImageReference() }) { var compilation5 = CreateCompilation(source2 + source3, new[] { reference }, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); Assert.True(compilation5.Assembly.RuntimeSupportsDefaultInterfaceImplementation); validateEventImplementationInDerived_01(compilation5.SourceModule); compilation5.VerifyDiagnostics( // (4,28): error CS0122: 'I2.M1' is inaccessible due to its protection level // event System.Action I2.M1 Diagnostic(ErrorCode.ERR_BadAccess, "M1").WithArguments("I2.M1").WithLocation(4, 28 + implModifiers.Length) ); } void validateEventImplementationInDerived_01(ModuleSymbol m) { ValidateEventImplementationInDerived_01(m, isStatic); } } [Fact] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void IndexerImplementationInDerived_01() { var source1 = @" public interface I2 { int this[int x] {get;} } public interface I4 { int this[int x] {set;} } public interface I5 : I4 { } public interface I1 : I2, I5 { int I2.this[int x] { get { System.Console.WriteLine(""I2.M1""); return 1; } } int I4.this[int x] { set => System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source2 = @" class Test1 : I1 { static void Main() { I2 i2 = new Test1(); _ = i2[0]; I4 i4 = new Test1(); i4[0] = 0; } } "; ValidatePropertyImplementationInDerived_01(source1, source2); } [Fact] public void IndexerImplementationInDerived_02() { var source1 = @" public interface I2 { int this[int x] {get;} } public interface I4 { int this[int x] {set;} } public interface I1 : I2, I4 { int I2.this[int x] => Getter(); private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } int I4.this[int x] { set { System.Console.WriteLine(""I2.M1""); } } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_02(source1, isStatic: false, new DiagnosticDescription[] { // (16,17): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // private int Getter() Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "Getter").WithArguments("default interface implementation", "8.0").WithLocation(16, 17), // (14,27): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // int I2.this[int x] => Getter(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "Getter()").WithArguments("default interface implementation", "8.0").WithLocation(14, 27), // (24,9): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // set Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "set").WithArguments("default interface implementation", "8.0").WithLocation(24, 9) }, // (6,15): error CS8506: 'I1.I2.this[int].get' cannot implement interface member 'I2.this[int].get' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I2.this[int].get", "I2.this[int].get", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15), // (6,15): error CS8506: 'I1.I4.this[int].set' cannot implement interface member 'I4.this[int].set' in type 'Test1' because feature 'default interface implementation' is not available in C# 7.3. Please use language version '8.0' or greater. // class Test1 : I1 Diagnostic(ErrorCode.ERR_LanguageVersionDoesNotSupportInterfaceImplementationForMember, "I1").WithArguments("I1.I4.this[int].set", "I4.this[int].set", "Test1", "default interface implementation", "7.3", "8.0").WithLocation(6, 15) ); } [Fact] public void IndexerImplementationInDerived_03() { var source1 = @" public interface I2 { int this[int x] {get; set;} } public interface I4 { int this[int x] {set;} } public interface I1 : I2, I4 { int I2.this[int x] { get { System.Console.WriteLine(""I2.M1""); return 1; } set { System.Console.WriteLine(""I2.M1""); } } int I4.this[int x] { set { System.Console.WriteLine(""I2.M1""); } } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_03(source1, isStatic: false, new DiagnosticDescription[] { // (16,9): error CS8501: Target runtime doesn't support default interface implementation. // get Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(16, 9), // (21,9): error CS8501: Target runtime doesn't support default interface implementation. // set Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(21, 9), // (29,9): error CS8501: Target runtime doesn't support default interface implementation. // set Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "set").WithLocation(29, 9) }, // (6,15): error CS8502: 'I1.I2.this[int].set' cannot implement interface member 'I2.this[int].set' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.this[int].set", "I2.this[int].set", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I2.this[int].get' cannot implement interface member 'I2.this[int].get' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I2.this[int].get", "I2.this[int].get", "Test1").WithLocation(6, 15), // (6,15): error CS8502: 'I1.I4.this[int].set' cannot implement interface member 'I4.this[int].set' in type 'Test1' because the target runtime doesn't support default interface implementation. // class Test1 : I1 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementationForMember, "I1").WithArguments("I1.I4.this[int].set", "I4.this[int].set", "Test1").WithLocation(6, 15) ); } [Fact] public void IndexerImplementationInDerived_04() { var source1 = @" public interface I2 { int this[int x] {get;} } public interface I4 { int this[int x] {set;} } public interface I1 : I2, I4 { int I2.this[int x] {get;} int I4.this[int x] {set;} } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic: false, // (14,25): error CS0501: 'I1.I2.this[int].get' must declare a body because it is not marked abstract, extern, or partial // int I2.this[int x] {get;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.I2.this[int].get").WithLocation(14, 25), // (15,25): error CS0501: 'I1.I4.this[int].set' must declare a body because it is not marked abstract, extern, or partial // int I4.this[int x] {set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.I4.this[int].set").WithLocation(15, 25) ); } [Fact] public void IndexerImplementationInDerived_05() { var source1 = @" public interface I2 { int this[int x] {get;} } public interface I4 { int this[int x] {set;} } public interface I1 { int I2.this[int x] {get => throw null;} int I4.this[int x] {set => throw null;} } "; ValidatePropertyImplementationInDerived_05(source1, // (14,9): error CS0540: 'I1.I2.this[int]': containing type does not implement interface 'I2' // int I2.this[int x] {get => throw null;} Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I2").WithArguments("I1.I2.this[int]", "I2").WithLocation(14, 9), // (15,9): error CS0540: 'I1.I4.this[int]': containing type does not implement interface 'I4' // int I4.this[int x] {set => throw null;} Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I4").WithArguments("I1.I4.this[int]", "I4").WithLocation(15, 9) ); } [Fact] public void IndexerImplementationInDerived_06() { var source1 = @" public interface I2 { int this[int x] {get; set;} } public interface I4 { int this[int x] {get; set;} } public interface I1 : I2, I4 { public static int I2.this[int x] { internal get => throw null; set => throw null; } internal virtual int I4.this[int x] { public get => throw null; set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic: false, // (14,26): error CS0106: The modifier 'static' is not valid for this item // public static int I2.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(14, 26), // (14,26): error CS0106: The modifier 'public' is not valid for this item // public static int I2.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("public").WithLocation(14, 26), // (16,18): error CS0106: The modifier 'internal' is not valid for this item // internal get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("internal").WithLocation(16, 18), // (19,29): error CS0106: The modifier 'internal' is not valid for this item // internal virtual int I4.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("internal").WithLocation(19, 29), // (19,29): error CS0106: The modifier 'virtual' is not valid for this item // internal virtual int I4.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("virtual").WithLocation(19, 29), // (21,16): error CS0106: The modifier 'public' is not valid for this item // public get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("public").WithLocation(21, 16) ); } [Fact] public void IndexerImplementationInDerived_07() { var source1 = @" public interface I2 { int this[int x] {get; set;} } public interface I4 { int this[int x] {get; set;} } public interface I1 : I2, I4 { private sealed int I2.this[int x] { private get => throw null; set => throw null; } protected abstract int I4.this[int x] { get => throw null; protected set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, i4M1IsAbstract: true, isStatic: false, // (14,27): error CS0106: The modifier 'sealed' is not valid for this item // private sealed int I2.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("sealed").WithLocation(14, 27), // (14,27): error CS0106: The modifier 'private' is not valid for this item // private sealed int I2.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("private").WithLocation(14, 27), // (16,17): error CS0106: The modifier 'private' is not valid for this item // private get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private").WithLocation(16, 17), // (19,31): error CS0106: The modifier 'protected' is not valid for this item // protected abstract int I4.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected").WithLocation(19, 31), // (21,9): error CS0500: 'I1.I4.this[int].get' cannot declare a body because it is marked abstract // get => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "get").WithArguments("I1.I4.this[int].get").WithLocation(21, 9), // (22,19): error CS0106: The modifier 'protected' is not valid for this item // protected set => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected").WithLocation(22, 19), // (22,19): error CS0500: 'I1.I4.this[int].set' cannot declare a body because it is marked abstract // protected set => throw null; Diagnostic(ErrorCode.ERR_AbstractHasBody, "set").WithArguments("I1.I4.this[int].set").WithLocation(22, 19), // (30,15): error CS0535: 'Test1' does not implement interface member 'I4.this[int]' // class Test1 : I1 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Test1", "I4.this[int]").WithLocation(30, 15) ); } [Fact] public void IndexerImplementationInDerived_08() { var source1 = @" public interface I2 { int this[int x] {get; set;} } public interface I4 { int this[int x] {get; set;} } public interface I1 : I2, I4 { private protected int I2.this[int x] { private protected get => throw null; set => throw null; } internal protected override int I4.this[int x] { get => throw null; internal protected set => throw null; } } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_04(source1, isStatic: false, // (14,30): error CS0106: The modifier 'private protected' is not valid for this item // private protected int I2.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("private protected").WithLocation(14, 30), // (16,27): error CS0106: The modifier 'private protected' is not valid for this item // private protected get => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "get").WithArguments("private protected").WithLocation(16, 27), // (19,40): error CS0106: The modifier 'protected internal' is not valid for this item // internal protected override int I4.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal").WithLocation(19, 40), // (19,40): error CS0106: The modifier 'override' is not valid for this item // internal protected override int I4.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override").WithLocation(19, 40), // (22,28): error CS0106: The modifier 'protected internal' is not valid for this item // internal protected set => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "set").WithArguments("protected internal").WithLocation(22, 28) ); } [Fact] public void IndexerImplementationInDerived_09() { var source1 = @" public interface I2 { int this[int x] {get;} } public interface I1 : I2 { extern int I2.this[int x] {get;} } public interface I3 : I1 { } class Test1 : I1 {} "; var source2 = @" public interface I2 { int this[int x] {set;} } public interface I1 : I2 { extern int I2.this[int x] { set {}} } public interface I3 : I1 { } class Test1 : I1 {} "; ValidatePropertyImplementationInDerived_09(source1, source2, isStatic: false, new DiagnosticDescription[] { // (9,32): warning CS0626: Method, operator, or accessor 'I1.I2.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int I2.this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.this[int].get").WithLocation(9, 32) }, new DiagnosticDescription[] { // (9,32): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // extern int I2.this[int x] {get;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "get").WithArguments("default interface implementation", "8.0").WithLocation(9, 32), // (9,32): warning CS0626: Method, operator, or accessor 'I1.I2.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int I2.this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.this[int].get").WithLocation(9, 32) }, new DiagnosticDescription[] { // (9,32): error CS8501: Target runtime doesn't support default interface implementation. // extern int I2.this[int x] {get;} Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "get").WithLocation(9, 32), // (9,32): warning CS0626: Method, operator, or accessor 'I1.I2.this[int].get' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation. // extern int I2.this[int x] {get;} Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "get").WithArguments("I1.I2.this[int].get").WithLocation(9, 32) }, // (10,7): error CS0179: 'I1.I2.this[int].set' cannot be extern and declare a body // { set {}} Diagnostic(ErrorCode.ERR_ExternHasBody, "set").WithArguments("I1.I2.this[int].set").WithLocation(10, 7) ); } [Fact] public void IndexerImplementationInDerived_10() { var source1 = @" public interface I1 { int this[int x] {get;set;} int this[long x] {get;set;} } public interface I2 : I1 { int I1.this[int x] { get => throw null; } int I1.this[long x] { set => throw null; } } class Test1 : I2 {} public interface I3 { int this[int x] {get;} int this[long x] {set;} int this[byte x] {get;set;} int this[short x] {get;set;} } public interface I4 : I3 { int I3.this[int x] { get => throw null; set => throw null; } int I3.this[long x] { get => throw null; set => throw null; } int I3.this[byte x] {get; set;} int I3.this[short x] {get; set;} = 0; } class Test2 : I4 {} "; ValidatePropertyImplementationInDerived_05(source1, // (44,38): error CS1519: Invalid token '=' in class, record, struct, or interface member declaration // int I3.this[short x] {get; set;} = 0; Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "=").WithArguments("=").WithLocation(44, 38), // (10,12): error CS0551: Explicit interface implementation 'I2.I1.this[int]' is missing accessor 'I1.this[int].set' // int I1.this[int x] Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("I2.I1.this[int]", "I1.this[int].set").WithLocation(10, 12), // (14,12): error CS0551: Explicit interface implementation 'I2.I1.this[long]' is missing accessor 'I1.this[long].get' // int I1.this[long x] Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("I2.I1.this[long]", "I1.this[long].get").WithLocation(14, 12), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.this[long]' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.this[long]").WithLocation(20, 15), // (20,15): error CS0535: 'Test1' does not implement interface member 'I1.this[int]' // class Test1 : I2 Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Test1", "I1.this[int]").WithLocation(20, 15), // (36,9): error CS0550: 'I4.I3.this[int].set' adds an accessor not found in interface member 'I3.this[int]' // set => throw null; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("I4.I3.this[int].set", "I3.this[int]").WithLocation(36, 9), // (40,9): error CS0550: 'I4.I3.this[long].get' adds an accessor not found in interface member 'I3.this[long]' // get => throw null; Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("I4.I3.this[long].get", "I3.this[long]").WithLocation(40, 9), // (43,26): error CS0501: 'I4.I3.this[byte].get' must declare a body because it is not marked abstract, extern, or partial // int I3.this[byte x] {get; set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I4.I3.this[byte].get").WithLocation(43, 26), // (43,31): error CS0501: 'I4.I3.this[byte].set' must declare a body because it is not marked abstract, extern, or partial // int I3.this[byte x] {get; set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I4.I3.this[byte].set").WithLocation(43, 31), // (44,27): error CS0501: 'I4.I3.this[short].get' must declare a body because it is not marked abstract, extern, or partial // int I3.this[short x] {get; set;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I4.I3.this[short].get").WithLocation(44, 27), // (44,32): error CS0501: 'I4.I3.this[short].set' must declare a body because it is not marked abstract, extern, or partial // int I3.this[short x] {get; set;} = 0; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I4.I3.this[short].set").WithLocation(44, 32) ); } [Fact] [WorkItem(32540, "https://github.com/dotnet/roslyn/issues/32540")] public void IndexerImplementationInDerived_11() { var source1 = @" public interface I2 { internal int this[int x] {get;} } public interface I4 { int this[int x] {get; internal set;} } public interface I5 : I4 { } public class TestHelper { public static void Test(I2 i2, I4 i4) { _ = i2[0]; i4[0] = i4[0]; } } "; var source2 = @" public interface I1 : I2, I5 { int I2.this[int x] => Getter(); private int Getter() { System.Console.WriteLine(""I2.M1""); return 1; } int I4.this[int x] { get { System.Console.WriteLine(""I4.M1""); return 1; } set => System.Console.WriteLine(""I4.M1.set""); } } public interface I3 : I1 { } "; ValidatePropertyImplementationInDerived_11(source1, source2, isStatic: false, // (4,12): error CS0122: 'I2.this[int]' is inaccessible due to its protection level // int I2.this[int x] => Getter(); Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I2.this[int]").WithLocation(4, 12), // (11,12): error CS0122: 'I4.this[int].set' is inaccessible due to its protection level // int I4.this[int x] Diagnostic(ErrorCode.ERR_BadAccess, "this").WithArguments("I4.this[int].set").WithLocation(11, 12) ); } [Fact] [WorkItem(20083, "https://github.com/dotnet/roslyn/issues/20083")] public void IndexerImplementationInDerived_12() { var source1 = @" public interface I1 { int this[int x] { get => throw null; set => throw null;} } public interface I2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""I2.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I2.I1.M1.set""); } } } public interface I3 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""I3.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I3.I1.M1.set""); } } } public interface I4 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""I4.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I4.I1.M1.set""); } } } public interface I5 : I2, I3 { int I1.this[int x] { get { System.Console.WriteLine(""I5.I1.M1.get""); return 1; } set { System.Console.WriteLine(""I5.I1.M1.set""); } } } public interface I6 : I1, I2, I3, I5 {} "; var source4 = @" class Test5 : I2 {} class Test6 : I1, I2, I3, I5 {} class Test7 : I6 { static void Main() { I1 i1 = new Test5(); i1[0] = i1[0]; i1 = new Test6(); i1[0] = i1[0]; i1 = new Test7(); i1[0] = i1[0]; } } "; var source5 = @" class Test8 : I2, I3 { int I1.this[int x] { get { System.Console.WriteLine(""Test8.I1.M1.get""); return 1; } set { System.Console.WriteLine(""Test8.I1.M1.set""); } } static void Main() { I1 i1 = new Test8(); i1[0] = i1[0]; i1 = new Test9(); i1[0] = i1[0]; i1 = new Test10(); i1[0] = i1[0]; i1 = new Test11(); i1[0] = i1[0]; i1 = new Test12(); i1[0] = i1[0]; } } class Test9 : I7 { int I1.this[int x] { get { System.Console.WriteLine(""Test9.I1.M1.get""); return 1; } set { System.Console.WriteLine(""Test9.I1.M1.set""); } } } class Test10 : I1, I2, I3, I4 { public int this[int x] { get { System.Console.WriteLine(""Test10.M1.get""); return 1; } set { System.Console.WriteLine(""Test10.M1.set""); } } } class Test11 : I1, I2, I3, I5, I4 { public int this[int x] { get { System.Console.WriteLine(""Test11.M1.get""); return 1; } set { System.Console.WriteLine(""Test11.M1.set""); } } } class Test12 : I8 { public virtual int this[int x] { get { System.Console.WriteLine(""Test12.M1.get""); return 1; } set { System.Console.WriteLine(""Test12.M1.set""); } } } "; ValidatePropertyImplementationInDerived_12(source1, source4, source5, isStatic: false, new DiagnosticDescription[] { // (2,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.this[int]', nor 'I3.I1.this[int]' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.this[int]", "I2.I1.this[int]", "I3.I1.this[int]").WithLocation(2, 15), // (5,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.this[int]', nor 'I3.I1.this[int]' are most specific. // class Test2 : I7 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I7").WithArguments("I1.this[int]", "I2.I1.this[int]", "I3.I1.this[int]").WithLocation(5, 15), // (8,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.this[int]', nor 'I3.I1.this[int]' are most specific. // class Test3 : I1, I2, I3, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.this[int]", "I2.I1.this[int]", "I3.I1.this[int]").WithLocation(8, 15), // (11,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I5.I1.this[int]', nor 'I4.I1.this[int]' are most specific. // class Test4 : I1, I2, I3, I5, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.this[int]", "I5.I1.this[int]", "I4.I1.this[int]").WithLocation(11, 15), // (14,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I5.I1.this[int]', nor 'I4.I1.this[int]' are most specific. // class Test5 : I8 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I8").WithArguments("I1.this[int]", "I5.I1.this[int]", "I4.I1.this[int]").WithLocation(14, 15) }, new DiagnosticDescription[] { // (2,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.Item[int]', nor 'I3.I1.Item[int]' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.this[int]", "I2.I1.Item[int]", "I3.I1.Item[int]").WithLocation(2, 15), // (5,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.Item[int]', nor 'I3.I1.Item[int]' are most specific. // class Test2 : I7 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I7").WithArguments("I1.this[int]", "I2.I1.Item[int]", "I3.I1.Item[int]").WithLocation(5, 15), // (8,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.Item[int]', nor 'I3.I1.Item[int]' are most specific. // class Test3 : I1, I2, I3, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.this[int]", "I2.I1.Item[int]", "I3.I1.Item[int]").WithLocation(8, 15), // (11,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I5.I1.Item[int]', nor 'I4.I1.Item[int]' are most specific. // class Test4 : I1, I2, I3, I5, I4 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I1").WithArguments("I1.this[int]", "I5.I1.Item[int]", "I4.I1.Item[int]").WithLocation(11, 15), // (14,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I5.I1.Item[int]', nor 'I4.I1.Item[int]' are most specific. // class Test5 : I8 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I8").WithArguments("I1.this[int]", "I5.I1.Item[int]", "I4.I1.Item[int]").WithLocation(14, 15) } ); } [Fact] public void IndexerImplementationInDerived_13() { var source1 = @" public interface I1 { int this[int x] {get;} } public interface I2 : I1 { int I1.this[int x] => throw null; } public interface I3 : I1 { int I1.this[int x] => throw null; } "; var source2 = @" class Test1 : I2, I3 { public long this[int x] => 1; } "; ValidatePropertyImplementationInDerived_13(source1, source2, new DiagnosticDescription[] { // (2,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.this[int]', nor 'I3.I1.this[int]' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.this[int]", "I2.I1.this[int]", "I3.I1.this[int]").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.this[int]'. 'Test1.this[int]' cannot implement 'I1.this[int]' because it does not have the matching return type of 'int'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.this[int]", "Test1.this[int]", "int").WithLocation(2, 15) }, new DiagnosticDescription[] { // (2,15): error CS8505: Interface member 'I1.this[int]' does not have a most specific implementation. Neither 'I2.I1.Item[int]', nor 'I3.I1.Item[int]' are most specific. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_MostSpecificImplementationIsNotFound, "I2").WithArguments("I1.this[int]", "I2.I1.Item[int]", "I3.I1.Item[int]").WithLocation(2, 15), // (2,15): error CS0738: 'Test1' does not implement interface member 'I1.this[int]'. 'Test1.this[int]' cannot implement 'I1.this[int]' because it does not have the matching return type of 'int'. // class Test1 : I2, I3 Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I2").WithArguments("Test1", "I1.this[int]", "Test1.this[int]", "int").WithLocation(2, 15) } ); } [Fact] [WorkItem(20084, "https://github.com/dotnet/roslyn/issues/20084")] public void IndexerImplementationInDerived_14() { var source1 = @" public interface I1<T> { int this[int x] { get { System.Console.WriteLine(""I1.M1.get""); return 1; } set => System.Console.WriteLine(""I1.M1.set""); } } public interface I2<T> : I1<T> { int I1<T>.this[int x] { get { System.Console.WriteLine(""I2.I1.M1.get""); return 1; } set => System.Console.WriteLine(""I2.I1.M1.set""); } } public interface I3<T> : I1<T> {} "; var source2 = @" class Test1 : I1<int> { static void Main() { I1<int> i1Int = new Test1(); i1Int[0] = i1Int[0]; I1<long> i1Long = new Test2(); i1Long[0] = i1Long[0]; } } class Test2 : I2<long> {} "; ValidatePropertyImplementationInDerived_14(source1, source2); } [Fact] public void IndexerImplementationInDerived_15() { var source1 = @" public interface I2 { int this[int x] {get => throw null; private set => throw null;} } public interface I4 { int this[int x] {set => throw null; private get => throw null;} } public interface I5 : I4 { } public interface I1 : I2, I5 { int I2.this[int x] { get { System.Console.WriteLine(""I2.M1""); return 1; } } int I4.this[int x] { set => System.Console.WriteLine(""I4.M1""); } } public interface I3 : I1 { } "; var source2 = @" class Test1 : I1 { static void Main() { I2 i2 = new Test1(); _ = i2[0]; I4 i4 = new Test1(); i4[0] = 0; } } "; ValidatePropertyImplementationInDerived_01(source1, source2); } [Fact] public void IndexerImplementationInDerived_16() { var source1 = @" public interface I1 { static int this[int x] {get;} } public interface I2 : I1 { int I1.this[int x] { get { System.Console.WriteLine(""I2.M1""); return 1; } } } public interface I3 : I1 { abstract int I1.this[int x] {get;} } "; var compilation1 = CreateCompilation(source1, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,16): error CS0106: The modifier 'static' is not valid for this item // static int this[int x] {get;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(4, 16) ); } [Fact] public void IndexerImplementationInDerived_17() { var source1 = @" public interface I1 { static virtual int this[int x] {get => 0;} } public interface I2 : I1 { static int I1.this[int x] { get { System.Console.WriteLine(""I2.M1""); return 1; } } } public interface I3 : I1 { abstract static int I1.this[int x] {get;} } "; var compilation1 = CreateCompilation(source1, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (4,24): error CS0106: The modifier 'static' is not valid for this item // static virtual int this[int x] {get => 0;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(4, 24), // (9,19): error CS0106: The modifier 'static' is not valid for this item // static int I1.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(9, 19), // (21,28): error CS0106: The modifier 'static' is not valid for this item // abstract static int I1.this[int x] {get;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(21, 28) ); } [Fact] public void IndexerImplementationInDerived_18() { var source1 = @" public interface I1 { int this[int x] {get;} } public interface I2 : I1 { static int I1.this[int x] { get { System.Console.WriteLine(""I2.M1""); return 1; } } } public interface I3 : I1 { abstract static int I1.this[int x] {get;} } "; var compilation1 = CreateCompilation(source1, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Net60); compilation1.VerifyDiagnostics( // (9,19): error CS0106: The modifier 'static' is not valid for this item // static int I1.this[int x] Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(9, 19), // (21,28): error CS0106: The modifier 'static' is not valid for this item // abstract static int I1.this[int x] {get;} Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(21, 28) ); } [Theory] [CombinatorialData] public void Field_01(bool testCSharp14) { var source1 = @" public interface I1 { int F1; protected static int F2; protected internal static int F3; private protected static int F4; int F5 = 5; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: testCSharp14 ? TestOptions.Regular14 : TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation1.VerifyEmitDiagnostics( // (4,9): error CS0525: Interfaces cannot contain instance fields // int F1; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 9), // (5,26): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected static int F2; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "F2").WithLocation(5, 26), // (6,35): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal static int F3; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "F3").WithLocation(6, 35), // (7,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // private protected static int F4; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "F4").WithLocation(7, 34), // (8,9): error CS0525: Interfaces cannot contain instance fields // int F5 = 5; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F5").WithLocation(8, 9) ); validate(compilation1); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: testCSharp14 ? TestOptions.Regular14 : TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyEmitDiagnostics( // (4,9): error CS0525: Interfaces cannot contain instance fields // int F1; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F1").WithLocation(4, 9), // (8,9): error CS0525: Interfaces cannot contain instance fields // int F5 = 5; Diagnostic(ErrorCode.ERR_InterfacesCantContainFields, "F5").WithLocation(8, 9) ); validate(compilation2); static void validate(CSharpCompilation compilation) { var i1 = compilation.GetTypeByMetadataName("I1"); var f1 = i1.GetMember<FieldSymbol>("F1"); var f2 = i1.GetMember<FieldSymbol>("F2"); var f3 = i1.GetMember<FieldSymbol>("F3"); var f4 = i1.GetMember<FieldSymbol>("F4"); Assert.False(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Protected, f2.DeclaredAccessibility); Assert.Equal(Accessibility.ProtectedOrInternal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.ProtectedAndInternal, f4.DeclaredAccessibility); } } [Fact] public void Field_02() { var source1 = @" public interface I1 { static int F1; public static int F2; internal static int F3; private static int F4; public class TestHelper { public static int F4Proxy { get => I1.F4; set => I1.F4 = value; } } } class Test1 : I1 { static void Main() { I1.F1 = 1; I1.F2 = 2; I1.F3 = 3; I1.TestHelper.F4Proxy = 4; System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}{I1.TestHelper.F4Proxy}""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<FieldSymbol>("F1"); var f2 = i1.GetMember<FieldSymbol>("F2"); var f3 = i1.GetMember<FieldSymbol>("F3"); var f4 = i1.GetMember<FieldSymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Null(cctor); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { I1.F1 = 11; I1.F2 = 22; I1.TestHelper.F4Proxy = 44; System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.TestHelper.F4Proxy}""); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "112244"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "112244"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,16): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static int F1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F1").WithArguments("default interface implementation", "8.0").WithLocation(4, 16), // (5,23): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static int F2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F2").WithArguments("default interface implementation", "8.0").WithLocation(5, 23), // (6,25): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // internal static int F3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F3").WithArguments("default interface implementation", "8.0").WithLocation(6, 25), // (7,24): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // private static int F4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F4").WithArguments("default interface implementation", "8.0").WithLocation(7, 24), // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,16): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int F1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 16), // (5,23): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static int F2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F2").WithArguments("static members in interfaces", "15.0").WithLocation(5, 23), // (6,25): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int F3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F3").WithArguments("static members in interfaces", "15.0").WithLocation(6, 25), // (7,24): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static int F4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F4").WithArguments("static members in interfaces", "15.0").WithLocation(7, 24) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation2 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: "112244"); compilation3 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation3, expectedOutput: "112244"); } [Fact] public void Field_03() { var source1 = @" public interface I1 { static readonly int F1 = 1; public static readonly int F2 = 2; internal static readonly int F3 = 3; private static readonly int F4 = 4; public class TestHelper { public static int F4Proxy { get => I1.F4; } } } class Test1 : I1 { static void Main() { System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}{I1.TestHelper.F4Proxy}""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<FieldSymbol>("F1"); var f2 = i1.GetMember<FieldSymbol>("F2"); var f3 = i1.GetMember<FieldSymbol>("F3"); var f4 = i1.GetMember<FieldSymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.True(f1.IsReadOnly); Assert.True(f2.IsReadOnly); Assert.True(f3.IsReadOnly); Assert.True(f4.IsReadOnly); Assert.False(f1.IsConst); Assert.False(f2.IsConst); Assert.False(f3.IsConst); Assert.False(f4.IsConst); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Equal(MethodKind.StaticConstructor, cctor.MethodKind); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.TestHelper.F4Proxy}""); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "124"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "124"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,25): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static readonly int F1 = 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F1").WithArguments("default interface implementation", "8.0").WithLocation(4, 25), // (5,32): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static readonly int F2 = 2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F2").WithArguments("default interface implementation", "8.0").WithLocation(5, 32), // (6,34): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // internal static readonly int F3 = 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F3").WithArguments("default interface implementation", "8.0").WithLocation(6, 34), // (7,33): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // private static readonly int F4 = 4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F4").WithArguments("default interface implementation", "8.0").WithLocation(7, 33), // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,25): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static readonly int F1 = 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 25), // (5,32): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static readonly int F2 = 2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F2").WithArguments("static members in interfaces", "15.0").WithLocation(5, 32), // (6,34): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static readonly int F3 = 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F3").WithArguments("static members in interfaces", "15.0").WithLocation(6, 34), // (7,33): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static readonly int F4 = 4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F4").WithArguments("static members in interfaces", "15.0").WithLocation(7, 33) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation2 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: "124"); compilation3 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation3, expectedOutput: "124"); } [Fact] public void Field_04() { var source1 = @" public interface I1 { const int F1 = 1; public const int F2 = 2; internal const int F3 = 3; private const int F4 = 4; public class TestHelper { public static int F4Proxy { get => I1.F4; } } } class Test1 : I1 { static void Main() { System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}{I1.TestHelper.F4Proxy}""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<FieldSymbol>("F1"); var f2 = i1.GetMember<FieldSymbol>("F2"); var f3 = i1.GetMember<FieldSymbol>("F3"); var f4 = i1.GetMember<FieldSymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.True(f1.IsConst); Assert.True(f2.IsConst); Assert.True(f3.IsConst); Assert.True(f4.IsConst); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Null(cctor); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.TestHelper.F4Proxy}""); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "124"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "124"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,15): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // const int F1 = 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F1").WithArguments("default interface implementation", "8.0").WithLocation(4, 15), // (5,22): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public const int F2 = 2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F2").WithArguments("default interface implementation", "8.0").WithLocation(5, 22), // (6,24): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // internal const int F3 = 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F3").WithArguments("default interface implementation", "8.0").WithLocation(6, 24), // (7,23): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // private const int F4 = 4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F4").WithArguments("default interface implementation", "8.0").WithLocation(7, 23), // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,15): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // const int F1 = 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 15), // (5,22): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public const int F2 = 2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F2").WithArguments("static members in interfaces", "15.0").WithLocation(5, 22), // (6,24): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal const int F3 = 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F3").WithArguments("static members in interfaces", "15.0").WithLocation(6, 24), // (7,23): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private const int F4 = 4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F4").WithArguments("static members in interfaces", "15.0").WithLocation(7, 23) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation2 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: "124"); compilation3 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation3, expectedOutput: "124"); } [Fact] public void Field_05() { var source0 = @" public interface I1 { static protected int F1; static protected internal int F2; static private protected int F3; } "; var source1 = @" class Test1 : I1 { static void Main() { I1.F1 = 1; I1.F2 = 2; I1.F3 = 3; System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}""); Test2.Test(); } } class Test2 { public static void Test() { I1.F2 = -2; System.Console.WriteLine(I1.F2); } } "; var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); validate(compilation1.SourceModule); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"123 -2 ", verify: VerifyOnMonoOrCoreClr_FailsIlVerify, symbolValidator: validate); var source2 = @" class Test2 : I1 { static void Main() { I1.F1 = 11; I1.F2 = 22; System.Console.WriteLine($""{I1.F1}{I1.F2}""); } } "; var references = new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }; foreach (var reference in references) { var compilation2 = CreateCompilation(source2, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, expectedOutput: ExecutionConditionUtil.IsMonoOrCoreClr ? "1122" : null, verify: VerifyOnMonoOrCoreClr_FailsIlVerify); } var source3 = @" class Test1 { static void Main() { I1.F1 = 1; I1.F2 = 2; I1.F3 = 3; } } "; var compilation3 = CreateCompilation(source0 + source3, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics( // (13,12): error CS0122: 'I1.F1' is inaccessible due to its protection level // I1.F1 = 1; Diagnostic(ErrorCode.ERR_BadAccess, "F1").WithArguments("I1.F1").WithLocation(13, 12), // (15,12): error CS0122: 'I1.F3' is inaccessible due to its protection level // I1.F3 = 3; Diagnostic(ErrorCode.ERR_BadAccess, "F3").WithArguments("I1.F3").WithLocation(15, 12) ); var source4 = @" class Test2 : I1 { static void Test() { I1.F3 = -3; } } "; foreach (var reference in references) { var compilation2 = CreateCompilation(source3 + source4, new[] { reference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics( // (6,12): error CS0122: 'I1.F1' is inaccessible due to its protection level // I1.F1 = 1; Diagnostic(ErrorCode.ERR_BadAccess, "F1").WithArguments("I1.F1").WithLocation(6, 12), // (7,12): error CS0122: 'I1.F2' is inaccessible due to its protection level // I1.F2 = 2; Diagnostic(ErrorCode.ERR_BadAccess, "F2").WithArguments("I1.F2").WithLocation(7, 12), // (8,12): error CS0122: 'I1.F3' is inaccessible due to its protection level // I1.F3 = 3; Diagnostic(ErrorCode.ERR_BadAccess, "F3").WithArguments("I1.F3").WithLocation(8, 12), // (16,12): error CS0122: 'I1.F3' is inaccessible due to its protection level // I1.F3 = -3; Diagnostic(ErrorCode.ERR_BadAccess, "F3").WithArguments("I1.F3").WithLocation(16, 12) ); } var compilation4 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,26): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static protected int F1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F1").WithArguments("default interface implementation", "8.0").WithLocation(4, 26), // (5,35): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static protected internal int F2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F2").WithArguments("default interface implementation", "8.0").WithLocation(5, 35), // (6,34): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static private protected int F3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "F3").WithArguments("default interface implementation", "8.0").WithLocation(6, 34) ); validate(compilation4.SourceModule); void validate(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<FieldSymbol>("F1"); var f2 = i1.GetMember<FieldSymbol>("F2"); var f3 = i1.GetMember<FieldSymbol>("F3"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.Equal(Accessibility.Protected, f1.DeclaredAccessibility); Assert.Equal(Accessibility.ProtectedOrInternal, f2.DeclaredAccessibility); Assert.Equal(Accessibility.ProtectedAndInternal, f3.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Null(cctor); } } [Fact] public void Constructors_01() { var source1 = @" public interface I1 { I1(){} static I1() {} } interface I2 { I2(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,5): error CS0526: Interfaces cannot contain instance constructors // I1(){} Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I1").WithLocation(4, 5), // (10,5): error CS0501: 'I2.I2()' must declare a body because it is not marked abstract, extern, or partial // I2(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "I2").WithArguments("I2.I2()").WithLocation(10, 5), // (10,5): error CS0526: Interfaces cannot contain instance constructors // I2(); Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I2").WithLocation(10, 5) ); } [Fact] public void Constructors_02() { var source1 = @" interface I1 { static I1() {} } interface I2 { static I2() => throw null; } interface I3 { I3() {} } interface I4 { I4() => throw null; } interface I5 { I5(); } interface I6 { extern static I6(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,12): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static I1() {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "I1").WithArguments("default interface implementation", "8.0").WithLocation(4, 12), // (8,12): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // static I2() => throw null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "I2").WithArguments("default interface implementation", "8.0").WithLocation(8, 12), // (12,5): error CS0526: Interfaces cannot contain instance constructors // I3() {} Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I3").WithLocation(12, 5), // (16,5): error CS0526: Interfaces cannot contain instance constructors // I4() => throw null; Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I4").WithLocation(16, 5), // (20,5): error CS0501: 'I5.I5()' must declare a body because it is not marked abstract, extern, or partial // I5(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "I5").WithArguments("I5.I5()").WithLocation(20, 5), // (20,5): error CS0526: Interfaces cannot contain instance constructors // I5(); Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I5").WithLocation(20, 5), // (24,19): error CS8703: The modifier 'extern' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // extern static I6(); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "I6").WithArguments("extern", "7.3", "8.0").WithLocation(24, 19), // (24,19): warning CS0824: Constructor 'I6.I6()' is marked external // extern static I6(); Diagnostic(ErrorCode.WRN_ExternCtorNoImplementation, "I6").WithArguments("I6.I6()").WithLocation(24, 19) ); var compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics( // (4,12): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static I1() {} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "I1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 12), // (8,12): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static I2() => throw null; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "I2").WithArguments("static members in interfaces", "15.0").WithLocation(8, 12), // (12,5): error CS0526: Interfaces cannot contain instance constructors // I3() {} Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I3").WithLocation(12, 5), // (16,5): error CS0526: Interfaces cannot contain instance constructors // I4() => throw null; Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I4").WithLocation(16, 5), // (20,5): error CS0501: 'I5.I5()' must declare a body because it is not marked abstract, extern, or partial // I5(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "I5").WithArguments("I5.I5()").WithLocation(20, 5), // (20,5): error CS0526: Interfaces cannot contain instance constructors // I5(); Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I5").WithLocation(20, 5), // (24,19): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // extern static I6(); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "I6").WithArguments("static members in interfaces", "15.0").WithLocation(24, 19), // (24,19): warning CS0824: Constructor 'I6.I6()' is marked external // extern static I6(); Diagnostic(ErrorCode.WRN_ExternCtorNoImplementation, "I6").WithArguments("I6.I6()").WithLocation(24, 19) ); var expected = new[] { // (12,5): error CS0526: Interfaces cannot contain instance constructors // I3() {} Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I3").WithLocation(12, 5), // (16,5): error CS0526: Interfaces cannot contain instance constructors // I4() => throw null; Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I4").WithLocation(16, 5), // (20,5): error CS0501: 'I5.I5()' must declare a body because it is not marked abstract, extern, or partial // I5(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "I5").WithArguments("I5.I5()").WithLocation(20, 5), // (20,5): error CS0526: Interfaces cannot contain instance constructors // I5(); Diagnostic(ErrorCode.ERR_InterfacesCantContainConstructors, "I5").WithLocation(20, 5), // (24,19): warning CS0824: Constructor 'I6.I6()' is marked external // extern static I6(); Diagnostic(ErrorCode.WRN_ExternCtorNoImplementation, "I6").WithArguments("I6.I6()").WithLocation(24, 19) }; compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics(expected); compilation2 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation2.VerifyDiagnostics(expected); } [Fact] public void Constructors_03() { var source1 = @" interface I1 { static I1(int i) {} } interface I2 { static void I2() {} } interface I3 { void I3() {} } interface I4 { public static I4() {} } interface I5 { internal static I5() {} } interface I6 { private static I6() {} } interface I7 { static I7(); } interface I8 { static I8(){} static void M1() { I8(); } void M2() { I8.I8(); } } interface I9 { static I9() {} => throw null; } interface I10 { abstract static I10(); } interface I11 { virtual static I11(); } interface I12 { abstract static I12() {} } interface I13 { virtual static I13() => throw null; } interface I14 { partial static I14(); } interface I15 { static partial I15(); } interface I16 { partial static I16() {} } interface I17 { static partial I17() => throw null; } interface I18 { extern static I18() {} } interface I19 { static extern I19() => throw null; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,12): error CS0132: 'I1.I1(int)': a static constructor must be parameterless // static I1(int i) {} Diagnostic(ErrorCode.ERR_StaticConstParam, "I1").WithArguments("I1.I1(int)").WithLocation(4, 12), // (8,17): error CS0542: 'I2': member names cannot be the same as their enclosing type // static void I2() {} Diagnostic(ErrorCode.ERR_MemberNameSameAsType, "I2").WithArguments("I2").WithLocation(8, 17), // (16,19): error CS0515: 'I4.I4()': access modifiers are not allowed on static constructors // public static I4() {} Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "I4").WithArguments("I4.I4()").WithLocation(16, 19), // (20,21): error CS0515: 'I5.I5()': access modifiers are not allowed on static constructors // internal static I5() {} Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "I5").WithArguments("I5.I5()").WithLocation(20, 21), // (24,20): error CS0515: 'I6.I6()': access modifiers are not allowed on static constructors // private static I6() {} Diagnostic(ErrorCode.ERR_StaticConstructorWithAccessModifiers, "I6").WithArguments("I6.I6()").WithLocation(24, 20), // (28,12): error CS0501: 'I7.I7()' must declare a body because it is not marked abstract, extern, or partial // static I7(); Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "I7").WithArguments("I7.I7()").WithLocation(28, 12), // (36,9): error CS1955: Non-invocable member 'I8' cannot be used like a method. // I8(); Diagnostic(ErrorCode.ERR_NonInvocableMemberCalled, "I8").WithArguments("I8").WithLocation(36, 9), // (41,12): error CS0117: 'I8' does not contain a definition for 'I8' // I8.I8(); Diagnostic(ErrorCode.ERR_NoSuchMember, "I8").WithArguments("I8", "I8").WithLocation(41, 12), // (46,5): error CS8057: Block bodies and expression bodies cannot both be provided. // static I9() {} => throw null; Diagnostic(ErrorCode.ERR_BlockBodyAndExpressionBody, "static I9() {} => throw null;").WithLocation(46, 5), // (50,21): error CS0106: The modifier 'abstract' is not valid for this item // abstract static I10(); Diagnostic(ErrorCode.ERR_BadMemberFlag, "I10").WithArguments("abstract").WithLocation(50, 21), // (54,20): error CS0106: The modifier 'virtual' is not valid for this item // virtual static I11(); Diagnostic(ErrorCode.ERR_BadMemberFlag, "I11").WithArguments("virtual").WithLocation(54, 20), // (58,21): error CS0106: The modifier 'abstract' is not valid for this item // abstract static I12() {} Diagnostic(ErrorCode.ERR_BadMemberFlag, "I12").WithArguments("abstract").WithLocation(58, 21), // (62,20): error CS0106: The modifier 'virtual' is not valid for this item // virtual static I13() => throw null; Diagnostic(ErrorCode.ERR_BadMemberFlag, "I13").WithArguments("virtual").WithLocation(62, 20), // (66,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type. // partial static I14(); Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(66, 5), // (66,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type. // partial static I14(); Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(66, 5), // (70,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type. // static partial I15(); Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(70, 12), // (74,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type. // partial static I16() {} Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(74, 5), // (74,5): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type. // partial static I16() {} Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(74, 5), // (78,12): error CS0267: The 'partial' modifier can only appear immediately before 'class', 'record', 'struct', 'interface', 'event', an instance constructor name, or a method or property return type. // static partial I17() => throw null; Diagnostic(ErrorCode.ERR_PartialMisplaced, "partial").WithLocation(78, 12), // (82,19): error CS0179: 'I18.I18()' cannot be extern and declare a body // extern static I18() {} Diagnostic(ErrorCode.ERR_ExternHasBody, "I18").WithArguments("I18.I18()").WithLocation(82, 19), // (86,19): error CS0179: 'I19.I19()' cannot be extern and declare a body // static extern I19() => throw null; Diagnostic(ErrorCode.ERR_ExternHasBody, "I19").WithArguments("I19.I19()").WithLocation(86, 19) ); } [Fact] public void Constructors_04() { var source1 = @" interface I1 { static I1() { System.Console.WriteLine(""I1""); } static void Main() { System.Console.WriteLine(""Main""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview); compilation1.VerifyDiagnostics(); ValidateConstructor(compilation1.SourceModule); Assert.Empty(compilation1.GetTypeByMetadataName("I1").GetMembers("I1")); CompileAndVerify(compilation1, symbolValidator: ValidateConstructor, expectedOutput: @"I1 Main "); } private static void ValidateConstructor(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.False(cctor.IsAbstract); Assert.False(cctor.IsVirtual); Assert.False(cctor.IsMetadataVirtual()); Assert.False(cctor.IsSealed); Assert.True(cctor.IsStatic); Assert.False(cctor.IsExtern); Assert.False(cctor.IsAsync); Assert.False(cctor.IsOverride); Assert.Equal(Accessibility.Private, cctor.DeclaredAccessibility); Assert.Equal(MethodKind.StaticConstructor, cctor.MethodKind); } [Fact] public void Constructors_05() { var source1 = @" interface I1 { static string F = ""F""; static void Main() { System.Console.WriteLine(F); System.Console.WriteLine(""Main""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); ValidateConstructor(compilation1.SourceModule); CompileAndVerify(compilation1, symbolValidator: ValidateConstructor, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"F Main "); } [Fact] public void Constructors_06() { var source1 = @" interface I1 { static string F = ""F""; static I1() { System.Console.WriteLine(F); System.Console.WriteLine(""I1""); } static void Main() { System.Console.WriteLine(""Main""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); ValidateConstructor(compilation1.SourceModule); CompileAndVerify(compilation1, symbolValidator: ValidateConstructor, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"F I1 Main "); } [Fact] public void Constructors_07() { var source1 = @" interface I1 { extern static I1(); } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics( // (4,19): warning CS0824: Constructor 'I1.I1()' is marked external // extern static I1(); Diagnostic(ErrorCode.WRN_ExternCtorNoImplementation, "I1").WithArguments("I1.I1()").WithLocation(4, 19) ); var i1 = compilation1.SourceModule.GlobalNamespace.GetTypeMember("I1"); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.False(cctor.IsAbstract); Assert.False(cctor.IsVirtual); Assert.False(cctor.IsMetadataVirtual()); Assert.False(cctor.IsSealed); Assert.True(cctor.IsStatic); Assert.True(cctor.IsExtern); Assert.False(cctor.IsAsync); Assert.False(cctor.IsOverride); Assert.Equal(Accessibility.Private, cctor.DeclaredAccessibility); Assert.Equal(MethodKind.StaticConstructor, cctor.MethodKind); CompileAndVerify(compilation1, symbolValidator: ValidateConstructor, verify: Verification.Skipped); } [Fact] public void Constructors_08() { var source1 = @" interface I1 { void I1(); } class Test : I1 { void I1.I1() { System.Console.WriteLine(""Test.I1""); } static void Main() { I1 x = new Test(); x.I1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: "Test.I1"); } [Fact] public void Constructors_09() { var source1 = @" interface I1 { void I1(); static I1() { System.Console.WriteLine(""I1..cctor""); } static void M1() { System.Console.WriteLine(""I1.M1""); } } class Test : I1 { void I1.I1() { System.Console.WriteLine(""Test.I1""); } static void Main() { I1.M1(); I1 x = new Test(); x.I1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"I1..cctor I1.M1 Test.I1 "); } [Fact] public void Constructors_10() { var source1 = @" interface I1 { void I1() { System.Console.WriteLine(""I1.I1""); } static I1() { System.Console.WriteLine(""I1..cctor""); } static void M1() { System.Console.WriteLine(""I1.M1""); } } class Test : I1 { static void Main() { I1.M1(); I1 x = new Test(); x.I1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"I1..cctor I1.M1 I1.I1 ", verify: VerifyOnMonoOrCoreClr); } [Fact] public void Constructors_11() { var source1 = @" interface I1 { void I1() { System.Console.WriteLine(""I1.I1""); } } class Test : I1 { static void Main() { I1 x = new Test(); x.I1(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "I1.I1", verify: VerifyOnMonoOrCoreClr); } /// <summary> /// Make sure runtime handles cycles in static constructors. /// </summary> [Fact] public void Constructors_12() { var source0 = @" interface I1 { public static int F1; static I1() { F1 = I2.F2; } } interface I2 { public static int F2; static I2() { F2 = I1.F1 + 1; } } "; var source1 = @" class Test { static void Main() { System.Console.WriteLine(I1.F1 + I2.F2); } } "; var compilation1 = CreateCompilation(source0 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "2"); var source2 = @" class Test { static void Main() { System.Console.WriteLine(I2.F2 + I1.F1); } } "; var compilation2 = CreateCompilation(source0 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1"); } [Fact] public void AutoProperty_01() { var source1 = @" public interface I1 { private int F1 {get; set;} private int F5 {get;} = 5; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyEmitDiagnostics( // (4,21): error CS0501: 'I1.F1.get' must declare a body because it is not marked abstract, extern, or partial // private int F1 {get; set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.F1.get").WithLocation(4, 21), // (4,26): error CS0501: 'I1.F1.set' must declare a body because it is not marked abstract, extern, or partial // private int F1 {get; set;} Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "set").WithArguments("I1.F1.set").WithLocation(4, 26), // (5,17): error CS8053: Instance properties in interfaces cannot have initializers. // private int F5 {get;} = 5; Diagnostic(ErrorCode.ERR_InstancePropertyInitializerInInterface, "F5").WithLocation(5, 17), // (5,21): error CS0501: 'I1.F5.get' must declare a body because it is not marked abstract, extern, or partial // private int F5 {get;} = 5; Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("I1.F5.get").WithLocation(5, 21) ); } [Fact] public void AutoProperty_02() { var source1 = @" public interface I1 { static int F1 {get; set;} public static int F2 {get; set;} internal static int F3 {get; set;} private static int F4 {get; set;} public class TestHelper { public static int F4Proxy { get => I1.F4; set => I1.F4 = value; } } } class Test1 : I1 { static void Main() { I1.F1 = 1; I1.F2 = 2; I1.F3 = 3; I1.TestHelper.F4Proxy = 4; System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}{I1.TestHelper.F4Proxy}""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<PropertySymbol>("F1"); var f2 = i1.GetMember<PropertySymbol>("F2"); var f3 = i1.GetMember<PropertySymbol>("F3"); var f4 = i1.GetMember<PropertySymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Null(cctor); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { I1.F1 = 11; I1.F2 = 22; I1.TestHelper.F4Proxy = 44; System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.TestHelper.F4Proxy}""); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "112244"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "112244"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,16): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static int F1 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F1").WithArguments("static", "7.3", "8.0").WithLocation(4, 16), // (5,23): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("static", "7.3", "8.0").WithLocation(5, 23), // (5,23): error CS8703: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("public", "7.3", "8.0").WithLocation(5, 23), // (6,25): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("static", "7.3", "8.0").WithLocation(6, 25), // (6,25): error CS8703: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("internal", "7.3", "8.0").WithLocation(6, 25), // (7,24): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static int F4 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("static", "7.3", "8.0").WithLocation(7, 24), // (7,24): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static int F4 {get; set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("private", "7.3", "8.0").WithLocation(7, 24), // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); compilation5.VerifyDiagnostics( // (4,20): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int F1 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(4, 20), // (4,25): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int F1 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(4, 25), // (5,27): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static int F2 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(5, 27), // (5,32): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static int F2 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(5, 32), // (6,29): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int F3 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(6, 29), // (6,34): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int F3 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(6, 34), // (7,28): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static int F4 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(7, 28), // (7,33): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static int F4 {get; set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(7, 33) ); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); var compilation6 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation6, expectedOutput: "112244"); var compilation7 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation7, expectedOutput: "112244"); } [Fact] public void AutoProperty_03() { var source1 = @" public interface I1 { static int F1 {get;} = 1; public static int F2 {get;} = 2; internal static int F3 {get;} = 3; private static int F4 {get;} = 4; public class TestHelper { public static int F4Proxy { get => I1.F4; } } } class Test1 : I1 { static void Main() { System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}{I1.TestHelper.F4Proxy}""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<PropertySymbol>("F1"); var f2 = i1.GetMember<PropertySymbol>("F2"); var f3 = i1.GetMember<PropertySymbol>("F3"); var f4 = i1.GetMember<PropertySymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.True(f1.IsReadOnly); Assert.True(f2.IsReadOnly); Assert.True(f3.IsReadOnly); Assert.True(f4.IsReadOnly); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Equal(MethodKind.StaticConstructor, cctor.MethodKind); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.TestHelper.F4Proxy}""); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "124"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "124"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,16): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static int F1 {get;} = 1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F1").WithArguments("static", "7.3", "8.0").WithLocation(4, 16), // (5,23): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get;} = 2; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("static", "7.3", "8.0").WithLocation(5, 23), // (5,23): error CS8703: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get;} = 2; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("public", "7.3", "8.0").WithLocation(5, 23), // (6,25): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get;} = 3; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("static", "7.3", "8.0").WithLocation(6, 25), // (6,25): error CS8703: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get;} = 3; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("internal", "7.3", "8.0").WithLocation(6, 25), // (7,24): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static int F4 {get;} = 4; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("static", "7.3", "8.0").WithLocation(7, 24), // (7,24): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static int F4 {get;} = 4; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("private", "7.3", "8.0").WithLocation(7, 24), // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,20): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int F1 {get;} = 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(4, 20), // (5,27): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static int F2 {get;} = 2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(5, 27), // (6,29): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int F3 {get;} = 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(6, 29), // (7,28): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static int F4 {get;} = 4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(7, 28) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); var compilation6 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation6, expectedOutput: "124"); var compilation7 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation7, expectedOutput: "124"); } [Fact] public void AutoProperty_04() { var source1 = @" public interface I1 { static int F1 {get; private set;} public static int F2 {get; private set;} internal static int F3 {get; private set;} public class TestHelper { public static void F4Proxy(int f1, int f2, int f3) { F1 = f1; F2 = f2; F3 = f3; } } } class Test1 : I1 { static void Main() { I1.TestHelper.F4Proxy(1,2,3); System.Console.WriteLine($""{I1.F1}{I1.F2}{I1.F3}""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<PropertySymbol>("F1"); var f2 = i1.GetMember<PropertySymbol>("F2"); var f3 = i1.GetMember<PropertySymbol>("F3"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f1.SetMethod.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f2.SetMethod.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f3.SetMethod.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Null(cctor); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "123", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { I1.TestHelper.F4Proxy(11,22,3); System.Console.WriteLine($""{I1.F1}{I1.F2}""); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1122"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1122"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (4,16): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static int F1 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F1").WithArguments("static", "7.3", "8.0").WithLocation(4, 16), // (4,33): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static int F1 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("private", "7.3", "8.0").WithLocation(4, 33), // (5,23): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("static", "7.3", "8.0").WithLocation(5, 23), // (5,23): error CS8703: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("public", "7.3", "8.0").WithLocation(5, 23), // (5,40): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static int F2 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("private", "7.3", "8.0").WithLocation(5, 40), // (6,25): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("static", "7.3", "8.0").WithLocation(6, 25), // (6,25): error CS8703: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("internal", "7.3", "8.0").WithLocation(6, 25), // (6,42): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static int F3 {get; private set;} Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "set").WithArguments("private", "7.3", "8.0").WithLocation(6, 42), // (8,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(8, 18) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,20): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int F1 {get; private set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(4, 20), // (4,33): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static int F1 {get; private set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(4, 33), // (5,27): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static int F2 {get; private set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(5, 27), // (5,40): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static int F2 {get; private set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(5, 40), // (6,29): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int F3 {get; private set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "get").WithArguments("static members in interfaces", "15.0").WithLocation(6, 29), // (6,42): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static int F3 {get; private set;} Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "set").WithArguments("static members in interfaces", "15.0").WithLocation(6, 42) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "123", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "123", symbolValidator: Validate1); var compilation6 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation6, expectedOutput: "1122"); var compilation7 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation7, expectedOutput: "1122"); } [Fact] public void FieldLikeEvent_01() { var source1 = @" public interface I1 { private event System.Action F1; private event System.Action F5 = null; } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular); compilation1.VerifyEmitDiagnostics( // (4,33): error CS0065: 'I1.F1': event property must have both add and remove accessors // private event System.Action F1; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "F1").WithArguments("I1.F1").WithLocation(4, 33), // (5,33): error CS0068: 'I1.F5': instance event in interface cannot have initializer // private event System.Action F5 = null; Diagnostic(ErrorCode.ERR_InterfaceEventInitializer, "F5").WithArguments("I1.F5").WithLocation(5, 33), // (5,33): error CS0065: 'I1.F5': event property must have both add and remove accessors // private event System.Action F5 = null; Diagnostic(ErrorCode.ERR_EventNeedsBothAccessors, "F5").WithArguments("I1.F5").WithLocation(5, 33), // (5,33): warning CS0067: The event 'I1.F5' is never used // private event System.Action F5 = null; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "F5").WithArguments("I1.F5").WithLocation(5, 33), // (4,33): warning CS0067: The event 'I1.F1' is never used // private event System.Action F1; Diagnostic(ErrorCode.WRN_UnreferencedEvent, "F1").WithArguments("I1.F1").WithLocation(4, 33) ); } [Fact] public void FieldLikeEvent_02() { var source1 = @" public interface I1 { static event System.Action F1; public static event System.Action F2; internal static event System.Action F3; private static event System.Action F4; public class TestHelper { public static System.Action F4Proxy { set => I1.F4 += value; } public static void Raise() { F1(); F2(); F3?.Invoke(); F4(); } } } class Test1 : I1 { static void Main() { I1.F1 += () => System.Console.Write(1); I1.F2 += () => System.Console.Write(2); I1.F3 += () => System.Console.Write(3); I1.TestHelper.F4Proxy = () => System.Console.Write(4); I1.TestHelper.Raise(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<EventSymbol>("F1"); var f2 = i1.GetMember<EventSymbol>("F2"); var f3 = i1.GetMember<EventSymbol>("F3"); var f4 = i1.GetMember<EventSymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Null(cctor); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { I1.F1 += () => System.Console.Write(11); I1.F2 += () => System.Console.Write(22); I1.TestHelper.F4Proxy = () => System.Console.Write(44); I1.TestHelper.Raise(); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "112244"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "112244"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18), // (4,32): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static event System.Action F1; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F1").WithArguments("static", "7.3", "8.0").WithLocation(4, 32), // (5,39): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static event System.Action F2; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("static", "7.3", "8.0").WithLocation(5, 39), // (5,39): error CS8503: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static event System.Action F2; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("public", "7.3", "8.0").WithLocation(5, 39), // (6,41): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static event System.Action F3; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("static", "7.3", "8.0").WithLocation(6, 41), // (6,41): error CS8503: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static event System.Action F3; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("internal", "7.3", "8.0").WithLocation(6, 41), // (7,40): error CS8503: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static event System.Action F4; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("static", "7.3", "8.0").WithLocation(7, 40), // (7,40): error CS8503: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static event System.Action F4; Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("private", "7.3", "8.0").WithLocation(7, 40) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,32): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static event System.Action F1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 32), // (5,39): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static event System.Action F2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F2").WithArguments("static members in interfaces", "15.0").WithLocation(5, 39), // (6,41): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static event System.Action F3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F3").WithArguments("static members in interfaces", "15.0").WithLocation(6, 41), // (7,40): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static event System.Action F4; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F4").WithArguments("static members in interfaces", "15.0").WithLocation(7, 40) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation2 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: "112244"); compilation3 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation3, expectedOutput: "112244"); } [Fact] public void FieldLikeEvent_03() { var source1 = @" public interface I1 { static event System.Action F1 = () => System.Console.Write(1); public static event System.Action F2 = () => System.Console.Write(2); internal static event System.Action F3 = () => System.Console.Write(3); private static event System.Action F4 = () => System.Console.Write(4); public class TestHelper { public static void Raise() { F1(); F2(); F3(); F4(); } } } class Test1 : I1 { static void Main() { I1.TestHelper.Raise(); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); void Validate1(ModuleSymbol m) { var i1 = m.GlobalNamespace.GetTypeMember("I1"); var f1 = i1.GetMember<EventSymbol>("F1"); var f2 = i1.GetMember<EventSymbol>("F2"); var f3 = i1.GetMember<EventSymbol>("F3"); var f4 = i1.GetMember<EventSymbol>("F4"); Assert.True(f1.IsStatic); Assert.True(f2.IsStatic); Assert.True(f3.IsStatic); Assert.True(f4.IsStatic); Assert.Equal(Accessibility.Public, f1.DeclaredAccessibility); Assert.Equal(Accessibility.Public, f2.DeclaredAccessibility); Assert.Equal(Accessibility.Internal, f3.DeclaredAccessibility); Assert.Equal(Accessibility.Private, f4.DeclaredAccessibility); var cctor = i1.GetMember<MethodSymbol>(".cctor"); Assert.Equal(MethodKind.StaticConstructor, cctor.MethodKind); } Validate1(compilation1.SourceModule); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234", symbolValidator: Validate1); var source2 = @" class Test2 : I1 { static void Main() { I1.TestHelper.Raise(); } } "; var compilation2 = CreateCompilation(source2, new[] { compilation1.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234"); var compilation3 = CreateCompilation(source2, new[] { compilation1.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "1234"); var compilation4 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics( // (9,18): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public class TestHelper Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "TestHelper").WithArguments("default interface implementation", "8.0").WithLocation(9, 18), // (4,32): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // static event System.Action F1 = () => System.Console.Write(1); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F1").WithArguments("static", "7.3", "8.0").WithLocation(4, 32), // (5,39): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static event System.Action F2 = () => System.Console.Write(2); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("static", "7.3", "8.0").WithLocation(5, 39), // (5,39): error CS8703: The modifier 'public' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // public static event System.Action F2 = () => System.Console.Write(2); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F2").WithArguments("public", "7.3", "8.0").WithLocation(5, 39), // (6,41): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static event System.Action F3 = () => System.Console.Write(3); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("static", "7.3", "8.0").WithLocation(6, 41), // (6,41): error CS8703: The modifier 'internal' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // internal static event System.Action F3 = () => System.Console.Write(3); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F3").WithArguments("internal", "7.3", "8.0").WithLocation(6, 41), // (7,40): error CS8703: The modifier 'static' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static event System.Action F4 = () => System.Console.Write(4); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("static", "7.3", "8.0").WithLocation(7, 40), // (7,40): error CS8703: The modifier 'private' is not valid for this item in C# 7.3. Please use language version '8.0' or greater. // private static event System.Action F4 = () => System.Console.Write(4); Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "F4").WithArguments("private", "7.3", "8.0").WithLocation(7, 40) ); Validate1(compilation4.SourceModule); var compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular14, targetFramework: TargetFramework.Mscorlib461Extended); compilation5.VerifyDiagnostics( // (4,32): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // static event System.Action F1 = () => System.Console.Write(1); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F1").WithArguments("static members in interfaces", "15.0").WithLocation(4, 32), // (5,39): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static event System.Action F2 = () => System.Console.Write(2); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F2").WithArguments("static members in interfaces", "15.0").WithLocation(5, 39), // (6,41): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // internal static event System.Action F3 = () => System.Console.Write(3); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F3").WithArguments("static members in interfaces", "15.0").WithLocation(6, 41), // (7,40): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // private static event System.Action F4 = () => System.Console.Write(4); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "F4").WithArguments("static members in interfaces", "15.0").WithLocation(7, 40) ); Validate1(compilation5.SourceModule); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation5 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMetadataImportOptions(MetadataImportOptions.All), parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); Validate1(compilation5.SourceModule); CompileAndVerify(compilation5, expectedOutput: "1234", symbolValidator: Validate1); compilation2 = CreateCompilation(source2, new[] { compilation5.ToMetadataReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation2, expectedOutput: "1234"); compilation3 = CreateCompilation(source2, new[] { compilation5.EmitToImageReference() }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular15, targetFramework: TargetFramework.Mscorlib461Extended); CompileAndVerify(compilation3, expectedOutput: "1234"); } [Fact] public void UnsupportedMemberAccess_01() { var source0 = @" public delegate void D0(); public interface I0 { static readonly int F1 = 1; static int P2 {get {System.Console.WriteLine(""P2""); return 2;} set {System.Console.WriteLine(""set_P2"");}} static void M3() {System.Console.WriteLine(""M3"");} static event D0 E4 { add {System.Console.WriteLine(""add E4"");value();} remove {System.Console.WriteLine(""remove E4"");value();} } class C6 { public static void M() {System.Console.WriteLine(""C6.M"");} } } "; var source1 = @" public delegate void D1(); public interface I1 { int P20 {get {System.Console.WriteLine(""P20""); return 20;}} int this[int P50] {set {System.Console.WriteLine(""P50"");}} void M30() {System.Console.WriteLine(""M30"");} event D1 E40 { add {System.Console.WriteLine(""add E40"");value();} remove {System.Console.WriteLine(""remove E40"");value();} } sealed int P200 {get {System.Console.WriteLine(""P200""); return 200;}} sealed int this[string P500] {set {System.Console.WriteLine(""P500"");}} sealed void M300() {System.Console.WriteLine(""M300"");} sealed event D1 E400 { add {System.Console.WriteLine(""add E400"");value();} remove {System.Console.WriteLine(""remove E400"");value();} } } public class Test1 : I1 { } "; var compilation0 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation0.VerifyDiagnostics(); var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source2 = @" class Test2 { static void Main() { System.Console.WriteLine(I0.F1); System.Console.WriteLine(I0.P2); I0.M3(); I0.E4 += I0.M3; I0.E4 -= new D0(I0.M3); I0.P2 = 3; I0.C6.M(); } } "; var source3 = @" class Test3 { static void Main() { I1 i1 = new Test1(); System.Console.WriteLine(i1.P20); i1.M30(); i1.E40 += i1.M30; i1.E40 -= new D1(i1.M30); i1[50] = default; } } "; var source4 = @" class Test4 : Test1 { static void Main() { I1 i1 = new Test1(); System.Console.WriteLine(i1.P200); i1.M300(); i1.E400 += i1.M300; i1.E400 -= new D1(i1.M300); i1[""500""] = default; } } "; foreach (var refs in new[] { (comp0:compilation0.ToMetadataReference(), comp1:compilation1.ToMetadataReference()), (comp0:compilation0.EmitToImageReference(), comp1:compilation1.EmitToImageReference()) }) { var compilation2 = CreateCompilation(source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation2 = compilation2.AddReferences(refs.comp0); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"1 P2 2 M3 add E4 M3 remove E4 M3 set_P2 C6.M "); var compilation3 = CreateCompilation(source3, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.Net50); compilation3 = compilation3.AddReferences(refs.comp1); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @"P20 20 M30 add E40 M30 remove E40 M30 P50 "); var compilation4 = CreateCompilation(source4, options: TestOptions.DebugExe, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular); compilation4 = compilation4.AddReferences(refs.comp1); Assert.False(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics( // (7,34): error CS8501: Target runtime doesn't support default interface implementation. // System.Console.WriteLine(i1.P200); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.P200").WithLocation(7, 34), // (8,9): error CS8501: Target runtime doesn't support default interface implementation. // i1.M300(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.M300").WithLocation(8, 9), // (9,9): error CS8501: Target runtime doesn't support default interface implementation. // i1.E400 += i1.M300; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.E400 += i1.M300").WithLocation(9, 9), // (9,20): error CS8501: Target runtime doesn't support default interface implementation. // i1.E400 += i1.M300; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.M300").WithLocation(9, 20), // (10,9): error CS8501: Target runtime doesn't support default interface implementation. // i1.E400 -= new D1(i1.M300); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.E400 -= new D1(i1.M300)").WithLocation(10, 9), // (10,27): error CS8501: Target runtime doesn't support default interface implementation. // i1.E400 -= new D1(i1.M300); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.M300").WithLocation(10, 27), // (11,9): error CS8701: Target runtime doesn't support default interface implementation. // i1["500"] = default; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, @"i1[""500""]").WithLocation(11, 9) ); } } [Theory] [CombinatorialData] public void UnsupportedMemberAccess_02_01(bool testCSharp14) { var source0 = @" public delegate void D0(); public interface I0 { static protected readonly int F1 = 1; static protected internal int P2 {get {System.Console.WriteLine(""P2""); return 2;} set {System.Console.WriteLine(""set_P2"");}} static protected void M3() {System.Console.WriteLine(""M3"");} static protected internal event D0 E4 { add {System.Console.WriteLine(""add E4"");value();} remove {System.Console.WriteLine(""remove E4"");value();} } protected internal class C6 { public static void M() {System.Console.WriteLine(""C6.M"");} } protected class C7<T> { } static int P8 {protected internal get {System.Console.WriteLine(""P8""); return 8;} set {System.Console.WriteLine(""set_P8"");}} static int P9 {get {System.Console.WriteLine(""P9""); return 9;} protected set {System.Console.WriteLine(""set_P9"");}} #pragma warning disable CS0067 // The event is never used static protected event D0 E5; static protected internal event D0 E6; static private protected event D0 E7; static protected internal readonly int F2 = 1; static private protected readonly int F3 = 1; } public class Test1 : I0 { } "; var compilation0 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: testCSharp14 ? TestOptions.Regular14 : TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation0.VerifyDiagnostics(); var source2 = @" using static I0; class Test2 : Test1 { static void Main() { System.Console.WriteLine(I0.F1); System.Console.WriteLine(I0.P2); I0.M3(); I0.E4 += I0.M3; I0.E4 -= new D0(I0.M3); I0.P2 = 3; I0.C6.M(); _ = new C7<int>(); _ = I0.P8; _ = I0.P9; I0.P8 = 12; I0.P9 = 13; } } "; foreach (var reference in new[] { compilation0.ToMetadataReference(), compilation0.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, references: new[] { reference }, parseOptions: testCSharp14 ? TestOptions.Regular14 : TestOptions.RegularPreview); CompileAndVerify(compilation2, verify: Verification.Skipped, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" 1 P2 2 M3 add E4 M3 remove E4 M3 set_P2 C6.M P8 P9 set_P8 set_P9 "); } } [Fact] public void UnsupportedMemberAccess_02_02() { var source0 = @" public delegate void D0(); public interface I0 { #line 1100 static protected readonly int F1 = 1; #line 1200 static protected internal int P2 { #line 1300 get {System.Console.WriteLine(""P2""); return 2;} #line 1400 set {System.Console.WriteLine(""set_P2"");} } #line 1500 static protected void M3() {System.Console.WriteLine(""M3"");} #line 1600 static protected internal event D0 E4 { #line 1700 add {System.Console.WriteLine(""add E4"");value();} #line 1800 remove {System.Console.WriteLine(""remove E4"");value();} } #line 1900 protected internal class C6 { public static void M() {System.Console.WriteLine(""C6.M"");} } #line 2000 protected class C7<T> { } static int P8 { #line 2100 protected internal get {System.Console.WriteLine(""P8""); return 8;} #line 2200 set {System.Console.WriteLine(""set_P8"");} } static int P9 { #line 2300 get {System.Console.WriteLine(""P9""); return 9;} #line 2400 protected set {System.Console.WriteLine(""set_P9"");} } #pragma warning disable CS0067 // The event is never used #line 2500 static protected event D0 E5; #line 2600 static protected internal event D0 E6; #line 2700 static private protected event D0 E7; #line 2800 static protected internal readonly int F2 = 1; #line 2900 static private protected readonly int F3 = 1; } public class Test1 : I0 { } "; var compilation0 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.Mscorlib461Extended); compilation0.VerifyDiagnostics( // (1100,36): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static protected readonly int F1 = 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "F1").WithLocation(1100, 36), // (1300,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // get Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "get").WithLocation(1300, 9), // (1400,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // set Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(1400, 9), // (1500,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static protected void M3() Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "M3").WithLocation(1500, 27), // (1700,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // add Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "add").WithLocation(1700, 9), // (1800,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // remove Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "remove").WithLocation(1800, 9), // (1900,30): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal class C6 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "C6").WithLocation(1900, 30), // (2000,21): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected class C7<T> Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "C7").WithLocation(2000, 21), // (2100,28): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected internal get Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "get").WithLocation(2100, 28), // (2400,19): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // protected set Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "set").WithLocation(2400, 19), // (2500,31): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static protected event D0 E5; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "E5").WithLocation(2500, 31), // (2600,40): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static protected internal event D0 E6; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "E6").WithLocation(2600, 40), // (2700,39): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static private protected event D0 E7; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "E7").WithLocation(2700, 39), // (2800,44): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static protected internal readonly int F2 = 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "F2").WithLocation(2800, 44), // (2900,43): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static private protected readonly int F3 = 1; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "F3").WithLocation(2900, 43) ); compilation0 = CreateCompilation(source0, options: TestOptions.DebugDll, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation0.VerifyDiagnostics(); var source2 = @" using static I0; class Test2 : Test1 { static void Main() { System.Console.WriteLine(I0.F1); System.Console.WriteLine(I0.P2); I0.M3(); I0.E4 += I0.M3; I0.E4 -= new D0(I0.M3); I0.P2 = 3; I0.C6.M(); _ = new C7<int>(); _ = I0.P8; _ = I0.P9; I0.P8 = 12; I0.P9 = 13; } } "; foreach (var reference in new[] { compilation0.ToMetadataReference(), compilation0.EmitToImageReference() }) { var compilation2 = CreateCompilation(source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.Mscorlib461Extended, references: new[] { reference }, parseOptions: TestOptions.RegularPreview); compilation2.VerifyDiagnostics( // (9,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // System.Console.WriteLine(I0.F1); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.F1").WithLocation(9, 34), // (10,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // System.Console.WriteLine(I0.P2); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.P2").WithLocation(10, 34), // (11,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.M3(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.M3").WithLocation(11, 9), // (12,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.E4 += I0.M3; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.E4 += I0.M3").WithLocation(12, 9), // (12,18): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.E4 += I0.M3; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.M3").WithLocation(12, 18), // (13,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.E4 -= new D0(I0.M3); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.E4 -= new D0(I0.M3)").WithLocation(13, 9), // (13,25): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.E4 -= new D0(I0.M3); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.M3").WithLocation(13, 25), // (14,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.P2 = 3; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.P2").WithLocation(14, 9), // (15,12): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.C6.M(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "C6").WithLocation(15, 12), // (16,17): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // _ = new C7<int>(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "C7<int>").WithLocation(16, 17), // (17,13): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // _ = I0.P8; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.P8").WithLocation(17, 13), // (20,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // I0.P9 = 13; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I0.P9").WithLocation(20, 9) ); } } [Fact] public void UnsupportedMemberAccess_03() { var source1 = @" public delegate void D1(); public interface I1 { protected int P20 {get {System.Console.WriteLine(""P20""); return 20;}} protected internal int this[int P50] {set {System.Console.WriteLine(""P50"");}} protected void M30() {System.Console.WriteLine(""M30"");} protected internal event D1 E40 { add {System.Console.WriteLine(""add E40"");value();} remove {System.Console.WriteLine(""remove E40"");value();} } int P50 {protected get {System.Console.WriteLine(""P50""); return 50;} set {}} int P60 {get {System.Console.WriteLine(""P60""); return 60;} protected internal set {}} protected internal sealed int P200 {get {System.Console.WriteLine(""P200""); return 200;}} protected sealed int this[string P500] {set {System.Console.WriteLine(""P500"");}} protected internal sealed void M300() {System.Console.WriteLine(""M300"");} protected sealed event D1 E400 { add {System.Console.WriteLine(""add E400"");value();} remove {System.Console.WriteLine(""remove E400"");value();} } sealed int P500 {protected get {System.Console.WriteLine(""P500""); return 500;} set {}} sealed int P600 {get {System.Console.WriteLine(""P600""); return 600;} protected internal set {}} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source3 = @" interface Test3 : I1 { static void Main() { Test3 i1 = null; System.Console.WriteLine(i1.P20); i1.M30(); i1.E40 += i1.M30; i1.E40 -= new D1(i1.M30); i1[50] = default; _ = i1.P50; _ = i1.P60; i1.P50 = 12; i1.P60 = 13; } } "; var source4 = @" interface Test4 : I1 { static void Main() { Test4 i1 = null; System.Console.WriteLine(i1.P200); i1.M300(); i1.E400 += i1.M300; i1.E400 -= new D1(i1.M300); i1[""500""] = default; _ = i1.P500; _ = i1.P600; i1.P500 = 12; i1.P600 = 13; } } "; foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation3 = CreateCompilation(source3, options: TestOptions.DebugExe, targetFramework: TargetFramework.Mscorlib461Extended, references: new[] { reference }, parseOptions: TestOptions.RegularPreview); compilation3.VerifyDiagnostics( // (7,34): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // System.Console.WriteLine(i1.P20); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.P20").WithLocation(7, 34), // (8,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1.M30(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.M30").WithLocation(8, 9), // (9,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1.E40 += i1.M30; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.E40 += i1.M30").WithLocation(9, 9), // (9,19): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1.E40 += i1.M30; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.M30").WithLocation(9, 19), // (10,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1.E40 -= new D1(i1.M30); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.E40 -= new D1(i1.M30)").WithLocation(10, 9), // (10,26): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1.E40 -= new D1(i1.M30); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.M30").WithLocation(10, 26), // (11,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1[50] = default; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1[50]").WithLocation(11, 9), // (12,13): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // _ = i1.P50; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.P50").WithLocation(12, 13), // (15,9): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // i1.P60 = 13; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "i1.P60").WithLocation(15, 9) ); var compilation4 = CreateCompilation(source4, options: TestOptions.DebugExe, targetFramework: TargetFramework.Mscorlib461Extended, references: new[] { reference }, parseOptions: TestOptions.RegularPreview); Assert.False(compilation4.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation4.VerifyDiagnostics( // (7,34): error CS8701: Target runtime doesn't support default interface implementation. // System.Console.WriteLine(i1.P200); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.P200").WithLocation(7, 34), // (8,9): error CS8701: Target runtime doesn't support default interface implementation. // i1.M300(); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.M300").WithLocation(8, 9), // (9,9): error CS8701: Target runtime doesn't support default interface implementation. // i1.E400 += i1.M300; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.E400 += i1.M300").WithLocation(9, 9), // (9,20): error CS8701: Target runtime doesn't support default interface implementation. // i1.E400 += i1.M300; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.M300").WithLocation(9, 20), // (10,9): error CS8701: Target runtime doesn't support default interface implementation. // i1.E400 -= new D1(i1.M300); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.E400 -= new D1(i1.M300)").WithLocation(10, 9), // (10,27): error CS8701: Target runtime doesn't support default interface implementation. // i1.E400 -= new D1(i1.M300); Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.M300").WithLocation(10, 27), // (11,9): error CS8701: Target runtime doesn't support default interface implementation. // i1["500"] = default; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, @"i1[""500""]").WithLocation(11, 9), // (12,13): error CS8701: Target runtime doesn't support default interface implementation. // _ = i1.P500; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.P500").WithLocation(12, 13), // (13,13): error CS8701: Target runtime doesn't support default interface implementation. // _ = i1.P600; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.P600").WithLocation(13, 13), // (14,9): error CS8701: Target runtime doesn't support default interface implementation. // i1.P500 = 12; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.P500").WithLocation(14, 9), // (15,9): error CS8701: Target runtime doesn't support default interface implementation. // i1.P600 = 13; Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportDefaultInterfaceImplementation, "i1.P600").WithLocation(15, 9) ); } } [Fact] public void UnsupportedMemberAccess_04() { var source1 = @" public interface I1 { protected interface I2 {} protected internal interface I3 {} } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); Assert.True(compilation1.Assembly.RuntimeSupportsDefaultInterfaceImplementation); compilation1.VerifyDiagnostics(); var source3 = @" interface Test3 : I1 { class C { static void M1(I1.I2 x) { System.Console.WriteLine(""M1""); } static void M2(I1.I3 x) { System.Console.WriteLine(""M2""); } static void Main() { M1(null); M2(null); } } } "; var source4 = @" class Test4 : I1 { interface Test5 : I1.I2 { } interface Test6 : I1.I3 { } } "; foreach (var reference in new[] { compilation1.ToMetadataReference(), compilation1.EmitToImageReference() }) { var compilation3 = CreateCompilation(source3, options: TestOptions.DebugExe, targetFramework: TargetFramework.Mscorlib461Extended, references: new[] { reference }, parseOptions: TestOptions.Regular); compilation3.VerifyDiagnostics( // (6,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static void M1(I1.I2 x) Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I2").WithLocation(6, 27), // (11,27): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // static void M2(I1.I3 x) Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I3").WithLocation(11, 27) ); var compilation4 = CreateCompilation(source4, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, references: new[] { reference }, parseOptions: TestOptions.Regular); compilation4.VerifyDiagnostics( // (4,26): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // interface Test5 : I1.I2 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I2").WithLocation(4, 26), // (8,26): error CS8707: Target runtime doesn't support 'protected', 'protected internal', or 'private protected' accessibility for a member of an interface. // interface Test6 : I1.I3 Diagnostic(ErrorCode.ERR_RuntimeDoesNotSupportProtectedAccessForInterfaceMember, "I3").WithLocation(8, 26) ); } } [Fact] public void EntryPoint_01() { var source1 = @" public interface I1 { static void Main() { System.Console.WriteLine(""I1.Main""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "I1.Main"); } [Fact] public void EntryPoint_02() { var source1 = @" public interface I1 { static void Main() { System.Console.WriteLine(""I1.Main""); } } public interface I2 { static void Main() { System.Console.WriteLine(""I2.Main""); } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugExe.WithMainTypeName("I2"), parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : "I2.Main"); } [Fact] public void Operators_01() { var source1 = @" public interface I1 { public static I1 operator +(I1 x) { System.Console.WriteLine(""+""); return x; } public static I1 operator -(I1 x) { System.Console.WriteLine(""-""); return x; } public static I1 operator !(I1 x) { System.Console.WriteLine(""!""); return x; } public static I1 operator ~(I1 x) { System.Console.WriteLine(""~""); return x; } public static I1 operator ++(I1 x) { System.Console.WriteLine(""++""); return x; } public static I1 operator --(I1 x) { System.Console.WriteLine(""--""); return x; } public static bool operator true(I1 x) { System.Console.WriteLine(""true""); return true; } public static bool operator false(I1 x) { System.Console.WriteLine(""false""); return false; } public static I1 operator +(I1 x, I1 y) { System.Console.WriteLine(""+2""); return x; } public static I1 operator -(I1 x, I1 y) { System.Console.WriteLine(""-2""); return x; } public static I1 operator *(I1 x, I1 y) { System.Console.WriteLine(""*""); return x; } public static I1 operator /(I1 x, I1 y) { System.Console.WriteLine(""/""); return x; } public static I1 operator %(I1 x, I1 y) { System.Console.WriteLine(""%""); return x; } public static I1 operator &(I1 x, I1 y) { System.Console.WriteLine(""&""); return x; } public static I1 operator |(I1 x, I1 y) { System.Console.WriteLine(""|""); return x; } public static I1 operator ^(I1 x, I1 y) { System.Console.WriteLine(""^""); return x; } public static I1 operator <<(I1 x, int y) { System.Console.WriteLine(""<<""); return x; } public static I1 operator >>(I1 x, int y) { System.Console.WriteLine("">>""); return x; } public static I1 operator >(I1 x, I1 y) { System.Console.WriteLine("">""); return x; } public static I1 operator <(I1 x, I1 y) { System.Console.WriteLine(""<""); return x; } public static I1 operator >=(I1 x, I1 y) { System.Console.WriteLine("">=""); return x; } public static I1 operator <=(I1 x, I1 y) { System.Console.WriteLine(""<=""); return x; } public static I1 operator >>>(I1 x, int y) { System.Console.WriteLine("">>>""); return x; } } "; var source2 = @" class Test2 : I1 { static void Main() { I1 x = new Test2(); I1 y = new Test2(); x = +x; x = -x; x = !x; x = ~x; x = ++x; x = x--; x = x + y; x = x - y; x = x * y; x = x / y; x = x % y; if (x && y) { } x = x | y; x = x ^ y; x = x << 1; x = x >> 2; x = x > y; x = x < y; x = x >= y; x = x <= y; x = x >>> 3; } } "; var expectedOutput = @" + - ! ~ ++ -- +2 -2 * / % false & true | ^ << >> > < >= <= >>> "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.RegularPreview); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.RegularPreview); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); var compilation6 = CreateCompilation(source1 + source2, options: TestOptions.DebugDll, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular7_3); compilation6.VerifyDiagnostics( // (4,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator +(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "+").WithArguments("default interface implementation", "8.0").WithLocation(4, 31), // (10,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator -(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "-").WithArguments("default interface implementation", "8.0").WithLocation(10, 31), // (16,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator !(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "!").WithArguments("default interface implementation", "8.0").WithLocation(16, 31), // (22,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator ~(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "~").WithArguments("default interface implementation", "8.0").WithLocation(22, 31), // (28,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator ++(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "++").WithArguments("default interface implementation", "8.0").WithLocation(28, 31), // (34,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator --(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "--").WithArguments("default interface implementation", "8.0").WithLocation(34, 31), // (40,33): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static bool operator true(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "true").WithArguments("default interface implementation", "8.0").WithLocation(40, 33), // (46,33): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static bool operator false(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "false").WithArguments("default interface implementation", "8.0").WithLocation(46, 33), // (52,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator +(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "+").WithArguments("default interface implementation", "8.0").WithLocation(52, 31), // (58,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator -(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "-").WithArguments("default interface implementation", "8.0").WithLocation(58, 31), // (64,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator *(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "*").WithArguments("default interface implementation", "8.0").WithLocation(64, 31), // (70,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator /(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "/").WithArguments("default interface implementation", "8.0").WithLocation(70, 31), // (76,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator %(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "%").WithArguments("default interface implementation", "8.0").WithLocation(76, 31), // (82,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator &(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "&").WithArguments("default interface implementation", "8.0").WithLocation(82, 31), // (88,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator |(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "|").WithArguments("default interface implementation", "8.0").WithLocation(88, 31), // (94,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator ^(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "^").WithArguments("default interface implementation", "8.0").WithLocation(94, 31), // (100,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator <<(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "<<").WithArguments("default interface implementation", "8.0").WithLocation(100, 31), // (106,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator >>(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">>").WithArguments("default interface implementation", "8.0").WithLocation(106, 31), // (112,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator >(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">").WithArguments("default interface implementation", "8.0").WithLocation(112, 31), // (118,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator <(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "<").WithArguments("default interface implementation", "8.0").WithLocation(118, 31), // (124,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator >=(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">=").WithArguments("default interface implementation", "8.0").WithLocation(124, 31), // (130,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator <=(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "<=").WithArguments("default interface implementation", "8.0").WithLocation(130, 31), // (136,31): error CS8370: Feature 'unsigned right shift' is not available in C# 7.3. Please use language version 11.0 or greater. // public static I1 operator >>>(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">>>").WithArguments("unsigned right shift", "11.0").WithLocation(136, 31), // (136,31): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // public static I1 operator >>>(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, ">>>").WithArguments("default interface implementation", "8.0").WithLocation(136, 31) ); var compilation61 = CreateCompilation(source1 + source2, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular14); compilation61.VerifyDiagnostics( // (4,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator +(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "+").WithArguments("static members in interfaces", "15.0").WithLocation(4, 31), // (10,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator -(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "-").WithArguments("static members in interfaces", "15.0").WithLocation(10, 31), // (16,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator !(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "!").WithArguments("static members in interfaces", "15.0").WithLocation(16, 31), // (22,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator ~(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "~").WithArguments("static members in interfaces", "15.0").WithLocation(22, 31), // (28,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator ++(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "++").WithArguments("static members in interfaces", "15.0").WithLocation(28, 31), // (34,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator --(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "--").WithArguments("static members in interfaces", "15.0").WithLocation(34, 31), // (40,33): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static bool operator true(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "true").WithArguments("static members in interfaces", "15.0").WithLocation(40, 33), // (46,33): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static bool operator false(I1 x) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "false").WithArguments("static members in interfaces", "15.0").WithLocation(46, 33), // (52,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator +(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "+").WithArguments("static members in interfaces", "15.0").WithLocation(52, 31), // (58,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator -(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "-").WithArguments("static members in interfaces", "15.0").WithLocation(58, 31), // (64,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator *(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "*").WithArguments("static members in interfaces", "15.0").WithLocation(64, 31), // (70,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator /(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "/").WithArguments("static members in interfaces", "15.0").WithLocation(70, 31), // (76,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator %(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "%").WithArguments("static members in interfaces", "15.0").WithLocation(76, 31), // (82,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator &(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "&").WithArguments("static members in interfaces", "15.0").WithLocation(82, 31), // (88,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator |(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "|").WithArguments("static members in interfaces", "15.0").WithLocation(88, 31), // (94,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator ^(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "^").WithArguments("static members in interfaces", "15.0").WithLocation(94, 31), // (100,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator <<(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "<<").WithArguments("static members in interfaces", "15.0").WithLocation(100, 31), // (106,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator >>(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, ">>").WithArguments("static members in interfaces", "15.0").WithLocation(106, 31), // (112,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator >(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, ">").WithArguments("static members in interfaces", "15.0").WithLocation(112, 31), // (118,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator <(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "<").WithArguments("static members in interfaces", "15.0").WithLocation(118, 31), // (124,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator >=(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, ">=").WithArguments("static members in interfaces", "15.0").WithLocation(124, 31), // (130,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator <=(I1 x, I1 y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, "<=").WithArguments("static members in interfaces", "15.0").WithLocation(130, 31), // (136,31): error CS9327: Feature 'static members in interfaces' is not available in C# 14.0. Please use language version 15.0 or greater. // public static I1 operator >>>(I1 x, int y) Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion14, ">>>").WithArguments("static members in interfaces", "15.0").WithLocation(136, 31) ); var compilation62 = CreateCompilation(source1 + source2, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.RegularPreview); compilation62.VerifyDiagnostics(); compilation62 = CreateCompilation(source1 + source2, options: TestOptions.DebugDll, targetFramework: TargetFramework.Mscorlib461Extended, parseOptions: TestOptions.Regular15); compilation62.VerifyDiagnostics(); var compilation7 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular7_3); var expected7 = new DiagnosticDescription[] { // (9,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = +x; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "+x").WithArguments("default interface implementation", "8.0").WithLocation(9, 13), // (10,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = -x; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "-x").WithArguments("default interface implementation", "8.0").WithLocation(10, 13), // (11,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = !x; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "!x").WithArguments("default interface implementation", "8.0").WithLocation(11, 13), // (12,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = ~x; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "~x").WithArguments("default interface implementation", "8.0").WithLocation(12, 13), // (13,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = ++x; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "++x").WithArguments("default interface implementation", "8.0").WithLocation(13, 13), // (14,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x--; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x--").WithArguments("default interface implementation", "8.0").WithLocation(14, 13), // (16,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x + y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x + y").WithArguments("default interface implementation", "8.0").WithLocation(16, 13), // (17,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x - y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x - y").WithArguments("default interface implementation", "8.0").WithLocation(17, 13), // (18,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x * y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x * y").WithArguments("default interface implementation", "8.0").WithLocation(18, 13), // (19,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x / y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x / y").WithArguments("default interface implementation", "8.0").WithLocation(19, 13), // (20,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x % y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x % y").WithArguments("default interface implementation", "8.0").WithLocation(20, 13), // (21,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // if (x && y) { } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x && y").WithArguments("default interface implementation", "8.0").WithLocation(21, 13), // (21,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // if (x && y) { } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x && y").WithArguments("default interface implementation", "8.0").WithLocation(21, 13), // (22,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x | y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x | y").WithArguments("default interface implementation", "8.0").WithLocation(22, 13), // (23,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x ^ y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x ^ y").WithArguments("default interface implementation", "8.0").WithLocation(23, 13), // (24,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x << 1; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x << 1").WithArguments("default interface implementation", "8.0").WithLocation(24, 13), // (25,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x >> 2; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x >> 2").WithArguments("default interface implementation", "8.0").WithLocation(25, 13), // (26,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x > y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x > y").WithArguments("default interface implementation", "8.0").WithLocation(26, 13), // (27,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x < y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x < y").WithArguments("default interface implementation", "8.0").WithLocation(27, 13), // (28,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x >= y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x >= y").WithArguments("default interface implementation", "8.0").WithLocation(28, 13), // (29,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x <= y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x <= y").WithArguments("default interface implementation", "8.0").WithLocation(29, 13), // (31,13): error CS8370: Feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x >>> 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x >>> 3").WithArguments("default interface implementation", "8.0").WithLocation(31, 13), // (31,13): error CS8370: Feature 'unsigned right shift' is not available in C# 7.3. Please use language version 11.0 or greater. // x = x >>> 3; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x >>> 3").WithArguments("unsigned right shift", "11.0").WithLocation(31, 13) }; compilation7.VerifyDiagnostics(expected7); var compilation8 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular7_3); compilation8.VerifyDiagnostics(expected7); var source3 = @" class Test3 : I1 { static void Main() { I1 x = new Test3(); I1 y = new Test3(); if (x) { } x = x & y; } } "; var compilation9 = CreateCompilation(source3, new[] { compilationReference }, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular7_3); var expected9 = new DiagnosticDescription[] { // (8,13): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // if (x) { } Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x").WithArguments("default interface implementation", "8.0").WithLocation(8, 13), // (9,13): error CS8652: The feature 'default interface implementation' is not available in C# 7.3. Please use language version 8.0 or greater. // x = x & y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "x & y").WithArguments("default interface implementation", "8.0").WithLocation(9, 13) }; compilation9.VerifyDiagnostics(expected9); var compilation10 = CreateCompilation(source3, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3); compilation10.VerifyDiagnostics(expected9); } [Fact] public void Operators_02() { var source1 = @" public class C1 { public static int operator +(C1 x, I1 y) { System.Console.WriteLine(""C1.+""); return 0; } public static int operator -(I1 x, C1 y) { System.Console.WriteLine(""C1.-""); return 0; } } public class C2 : C1 {} class Test : I1 { static void Main() { I1 x = new Test(); C2 y = new C2(); var r = y + x; r = x - y; } } "; var source2 = @" public interface I1 { } "; var source3 = @" public interface I1 { public static int operator +(C2 x, I1 y) { System.Console.WriteLine(""I1.+""); return 0; } public static int operator -(I1 x, C2 y) { System.Console.WriteLine(""I1.-""); return 0; } } "; var expectedOutput = @" C1.+ C1.- "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp); CompileAndVerify(compilation1, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); var compilation2 = CreateCompilation(source1 + source3, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput, verify: VerifyOnMonoOrCoreClr); } [Fact] public void Operators_03() { var source1 = @" public interface I1 { public static I1 operator ==(I1 x, I1 y) { System.Console.WriteLine(""==""); return x; } public static I1 operator !=(I1 x, I1 y) { System.Console.WriteLine(""!=""); return x; } } "; var source2 = @" class Test2 : I1 { static void Main() { I1 x = new Test2(); I1 y = new Test2(); x = x == y; x = x != y; } } "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular9); compilation1.VerifyDiagnostics( // (4,31): error CS0567: Conversion, equality, or inequality operators declared in interfaces must be abstract or virtual // public static I1 operator ==(I1 x, I1 y) Diagnostic(ErrorCode.ERR_InterfacesCantContainConversionOrEqualityOperators, "==").WithLocation(4, 31), // (10,31): error CS0567: Conversion, equality, or inequality operators declared in interfaces must be abstract or virtual // public static I1 operator !=(I1 x, I1 y) Diagnostic(ErrorCode.ERR_InterfacesCantContainConversionOrEqualityOperators, "!=").WithLocation(10, 31), // (24,13): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // x = x == y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x == y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(24, 13), // (25,13): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // x = x != y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x != y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(25, 13) ); CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.RegularPreview).VerifyDiagnostics( // (4,31): error CS0567: Conversion, equality, or inequality operators declared in interfaces must be abstract or virtual // public static I1 operator ==(I1 x, I1 y) Diagnostic(ErrorCode.ERR_InterfacesCantContainConversionOrEqualityOperators, "==").WithLocation(4, 31), // (10,31): error CS0567: Conversion, equality, or inequality operators declared in interfaces must be abstract or virtual // public static I1 operator !=(I1 x, I1 y) Diagnostic(ErrorCode.ERR_InterfacesCantContainConversionOrEqualityOperators, "!=").WithLocation(10, 31) ); CompilationReference compilationReference = compilation1.ToMetadataReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9, targetFramework: TargetFramework.NetCoreApp).VerifyDiagnostics( // (9,13): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // x = x == y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x == y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(9, 13), // (10,13): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // x = x != y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x != y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(10, 13) ); var ilSource = @" .class interface public abstract auto ansi I1 { .method public hidebysig specialname static class I1 op_Equality(class I1 x, class I1 y) cil managed { // Code size 18 (0x12) .maxstack 1 .locals init (class I1 V_0) IL_0000: nop IL_0001: ldstr ""=="" IL_0006: call void [mscorlib]System.Console::WriteLine(string) IL_000b: nop IL_000c: ldarg.0 IL_000d: stloc.0 IL_000e: br.s IL_0010 IL_0010: ldloc.0 IL_0011: ret } // end of method I1::op_Equality .method public hidebysig specialname static class I1 op_Inequality(class I1 x, class I1 y) cil managed { // Code size 18 (0x12) .maxstack 1 .locals init (class I1 V_0) IL_0000: nop IL_0001: ldstr ""!="" IL_0006: call void [mscorlib]System.Console::WriteLine(string) IL_000b: nop IL_000c: ldarg.0 IL_000d: stloc.0 IL_000e: br.s IL_0010 IL_0010: ldloc.0 IL_0011: ret } // end of method I1::op_Inequality } // end of class I1 "; var compilation3 = CreateCompilationWithIL(source2, ilSource, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" == != ").VerifyDiagnostics(); CreateCompilationWithIL(source2, ilSource, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9).VerifyDiagnostics( // (9,13): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // x = x == y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x == y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(9, 13), // (10,13): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // x = x != y; Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x != y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(10, 13) ); var source3 = @" class Test2 : I1 { static void Main() { I1 x = new Test2(); I1 y = new Test2(); System.Console.WriteLine(x == y); System.Console.WriteLine(x != y); } } "; var compilation4 = CreateCompilationWithIL(source3, ilSource, options: TestOptions.DebugExe, parseOptions: TestOptions.RegularPreview); compilation4.VerifyDiagnostics(); CompileAndVerify(compilation4, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : @" == Test2 != Test2 "); CreateCompilationWithIL(source3, ilSource, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular9).VerifyDiagnostics( // (9,34): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // System.Console.WriteLine(x == y); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x == y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(9, 34), // (10,34): error CS8773: Feature 'static abstract members in interfaces' is not available in C# 9.0. Please use language version 11.0 or greater. // System.Console.WriteLine(x != y); Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion9, "x != y").WithArguments("static abstract members in interfaces", "11.0").WithLocation(10, 34) ); } [Fact] public void Operators_04() { var source1 = @" public interface I1 { public static implicit operator int(I1 x) { return 0; } public static explicit operator byte(I1 x) { return 0; } public static void Test(I1 x) { int y = x; y = (int)x; var z = (byte)x; z = x; } } "; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics( // (4,37): error CS0552: 'I1.implicit operator int(I1)': user-defined conversions to or from an interface are not allowed // public static implicit operator int(I1 x) Diagnostic(ErrorCode.ERR_ConversionWithInterface, "int").WithArguments("I1.implicit operator int(I1)").WithLocation(4, 37), // (4,37): error CS0567: Conversion, equality, or inequality operators declared in interfaces must be abstract or virtual // public static implicit operator int(I1 x) Diagnostic(ErrorCode.ERR_InterfacesCantContainConversionOrEqualityOperators, "int").WithLocation(4, 37), // (8,37): error CS0552: 'I1.explicit operator byte(I1)': user-defined conversions to or from an interface are not allowed // public static explicit operator byte(I1 x) Diagnostic(ErrorCode.ERR_ConversionWithInterface, "byte").WithArguments("I1.explicit operator byte(I1)").WithLocation(8, 37), // (8,37): error CS0567: Conversion, equality, or inequality operators declared in interfaces must be abstract or virtual // public static explicit operator byte(I1 x) Diagnostic(ErrorCode.ERR_InterfacesCantContainConversionOrEqualityOperators, "byte").WithLocation(8, 37), // (15,17): error CS0029: Cannot implicitly convert type 'I1' to 'int' // int y = x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("I1", "int").WithLocation(15, 17), // (16,13): error CS0030: Cannot convert type 'I1' to 'int' // y = (int)x; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(int)x").WithArguments("I1", "int").WithLocation(16, 13), // (17,17): error CS0030: Cannot convert type 'I1' to 'byte' // var z = (byte)x; Diagnostic(ErrorCode.ERR_NoExplicitConv, "(byte)x").WithArguments("I1", "byte").WithLocation(17, 17), // (18,13): error CS0029: Cannot implicitly convert type 'I1' to 'byte' // z = x; Diagnostic(ErrorCode.ERR_NoImplicitConv, "x").WithArguments("I1", "byte").WithLocation(18, 13) ); } [Fact] public void Operators_05() { var source1 = @" public interface I1 { public static I1 operator -(I1 x) { System.Console.WriteLine(""-""); return x; } } public interface I2 : I1 {} "; var source2 = @" class Test2 : I2 { static void Main() { I2 x = new Test2(); I1 y = -x; } } "; var expectedOutput = @" - "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, targetFramework: TargetFramework.NetCoreApp, parseOptions: TestOptions.Regular); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var source3 = @" class Test2 : I2 { static void Main() { Test2 x = new Test2(); I1 y = -x; } } "; var compilation9 = CreateCompilation(source3, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); var expected9 = new DiagnosticDescription[] { // (8,16): error CS0023: Operator '-' cannot be applied to operand of type 'Test2' // I1 y = -x; Diagnostic(ErrorCode.ERR_BadUnaryOp, "-x").WithArguments("-", "Test2").WithLocation(8, 16) }; compilation9.VerifyDiagnostics(expected9); var compilation10 = CreateCompilation(source3, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation10.VerifyDiagnostics(expected9); } [Fact] public void Operators_06() { var source1 = @" public interface I1 { public static I1 operator -(I1 x) { System.Console.WriteLine(""I1.-""); return x; } } public interface I2 : I1 { public static I2 operator -(I2 x) { System.Console.WriteLine(""I2.-""); return x; } } "; var source2 = @" class Test2 : I2 { static void Main() { I2 x = new Test2(); var y = -x; } } "; var expectedOutput = @" I2.- "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_07() { var source1 = @" public interface I1 { public static I1 operator -(I1 x) { System.Console.WriteLine(""I1.-""); return x; } } public interface I3 { public static I3 operator -(I3 x) { System.Console.WriteLine(""I3.-""); return x; } } public interface I4 : I1, I3 { public static I4 operator -(I4 x) { System.Console.WriteLine(""I4.-""); return x; } } public interface I2 : I4 { } "; var source2 = @" class Test2 : I2 { static void Main() { I2 x = new Test2(); var y = -x; } } "; var expectedOutput = @" I4.- "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_08() { var source1 = @" public interface I1 { public static I1 operator -(I1 x) { System.Console.WriteLine(""I1.-""); return x; } } public interface I3 { public static I3 operator -(I3 x) { System.Console.WriteLine(""I3.-""); return x; } } public interface I4 : I1, I3 { } public interface I2 : I4 { } "; var source2 = @" class Test2 : I2 { static void Main() { I2 x = new Test2(); var y = -x; } } "; var expected = new DiagnosticDescription[] { // (7,17): error CS9342: Operator resolution is ambiguous between the following members: 'I1.operator -(I1)' and 'I3.operator -(I3)' // var y = -x; Diagnostic(ErrorCode.ERR_AmbigOperator, "-").WithArguments("I1.operator -(I1)", "I3.operator -(I3)").WithLocation(7, 17) }; var compilation1 = CreateCompilation(source2 + source1, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(expected); CompilationReference compilationReference = compilation1.ToMetadataReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(expected); } [Fact] public void Operators_09() { var source1 = @" public interface I1 { public static I1 operator -(I1 x) { System.Console.WriteLine(""I1.-""); return x; } } "; var source2 = @" class Test1 : Test2, I1 {} class Test2 { static void Main() { Test(new Test1()); } static void Test<T>(T x) where T : Test2, I1 { var y = -x; } public static Test2 operator -(Test2 x) { System.Console.WriteLine(""Test2.-""); return x; } } "; var expectedOutput = @" Test2.- "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_10() { var source1 = @" public interface I1 { public static I1 operator -(I1 x) { System.Console.WriteLine(""I1.-""); return x; } } public interface I3 { public static I3 operator -(I3 x) { System.Console.WriteLine(""I3.-""); return x; } } public interface I4 : I1, I3 { public static I4 operator -(I4 x) { System.Console.WriteLine(""I4.-""); return x; } } public interface I2 : I4 { }"; var source2 = @" class Test1 : Test2, I2 {} class Test2 { static void Main() { Test(new Test1()); } static void Test<T>(T x) where T : Test2, I2 { var y = -x; } } "; var expectedOutput = @" I4.- "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_11() { var source0 = @" public interface I1 { } public interface I2 { } "; var source1 = @" public class C1 { public static C1 operator +(C1 x, I2 y) { System.Console.WriteLine(""C1.+1""); return x; } public static C1 operator +(C1 x, I1 y) { System.Console.WriteLine(""C1.+2""); return x; } } "; var source2 = @" public interface I3 : I1, I2 { } "; var source3 = @" class Test2 : I3 { static void Main() { I3 x = new Test2(); var y = new C1() + x; } } "; var expected = new DiagnosticDescription[] { // (7,26): error CS9342: Operator resolution is ambiguous between the following members: 'C1.operator +(C1, I2)' and 'C1.operator +(C1, I1)' // var y = new C1() + x; Diagnostic(ErrorCode.ERR_AmbigOperator, "+").WithArguments("C1.operator +(C1, I2)", "C1.operator +(C1, I1)").WithLocation(7, 26) }; var compilation0 = CreateCompilation(source0 + source1 + source2, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation0.VerifyDiagnostics(); CompilationReference compilationReference0 = compilation0.ToMetadataReference(); MetadataReference metadataReference0 = compilation0.EmitToImageReference(); var compilation1 = CreateCompilation(source3, new[] { compilationReference0 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(expected); var compilation2 = CreateCompilation(source3, new[] { metadataReference0 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(expected); var source4 = @" public interface I1 { public static C1 operator +(C1 x, I1 y) { System.Console.WriteLine(""I1.+""); return x; } } public interface I2 { } "; var compilation3 = CreateCompilation(source4 + source1 + source2, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompilationReference compilationReference3 = compilation3.ToMetadataReference(); MetadataReference metadataReference3 = compilation3.EmitToImageReference(); var compilation4 = CreateCompilation(source3, new[] { compilationReference3 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics(expected); var compilation5 = CreateCompilation(source3, new[] { metadataReference3 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics(expected); var source5 = @" public interface I3 : I1, I2 { public static C1 operator +(C1 x, I3 y) { System.Console.WriteLine(""I3.+""); return x; } } "; var compilation6 = CreateCompilation(source4 + source1 + source5, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation6.VerifyDiagnostics(); CompilationReference compilationReference6 = compilation6.ToMetadataReference(); MetadataReference metadataReference6 = compilation6.EmitToImageReference(); var compilation7 = CreateCompilation(source3, new[] { compilationReference6 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation7.VerifyDiagnostics(expected); var compilation8 = CreateCompilation(source3, new[] { metadataReference6 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation8.VerifyDiagnostics(expected); } [Fact] public void Operators_12() { var source0 = @" public interface I1 { } public interface I2 { } "; var source1 = @" public class C1 { public static C1 operator +(I2 x, C1 y) { System.Console.WriteLine(""C1.+1""); return y; } public static C1 operator +(I1 x, C1 y) { System.Console.WriteLine(""C1.+2""); return y; } } "; var source2 = @" public interface I3 : I1, I2 { } "; var source3 = @" class Test2 : I3 { static void Main() { I3 x = new Test2(); var y = x + new C1(); } } "; var expected = new DiagnosticDescription[] { // (7,19): error CS9342: Operator resolution is ambiguous between the following members: 'C1.operator +(I2, C1)' and 'C1.operator +(I1, C1)' // var y = x + new C1(); Diagnostic(ErrorCode.ERR_AmbigOperator, "+").WithArguments("C1.operator +(I2, C1)", "C1.operator +(I1, C1)").WithLocation(7, 19) }; var compilation0 = CreateCompilation(source0 + source1 + source2, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation0.VerifyDiagnostics(); CompilationReference compilationReference0 = compilation0.ToMetadataReference(); MetadataReference metadataReference0 = compilation0.EmitToImageReference(); var compilation1 = CreateCompilation(source3, new[] { compilationReference0 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(expected); var compilation2 = CreateCompilation(source3, new[] { metadataReference0 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(expected); var source4 = @" public interface I1 { public static C1 operator +(I1 x, C1 y) { System.Console.WriteLine(""I1.+""); return y; } } public interface I2 { } "; var compilation3 = CreateCompilation(source4 + source1 + source2, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompilationReference compilationReference3 = compilation3.ToMetadataReference(); MetadataReference metadataReference3 = compilation3.EmitToImageReference(); var compilation4 = CreateCompilation(source3, new[] { compilationReference3 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation4.VerifyDiagnostics(expected); var compilation5 = CreateCompilation(source3, new[] { metadataReference3 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation5.VerifyDiagnostics(expected); var source5 = @" public interface I3 : I1, I2 { public static C1 operator +(I3 x, C1 y) { System.Console.WriteLine(""I3.+""); return y; } } "; var compilation6 = CreateCompilation(source4 + source1 + source5, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation6.VerifyDiagnostics(); CompilationReference compilationReference6 = compilation6.ToMetadataReference(); MetadataReference metadataReference6 = compilation6.EmitToImageReference(); var compilation7 = CreateCompilation(source3, new[] { compilationReference6 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation7.VerifyDiagnostics(expected); var compilation8 = CreateCompilation(source3, new[] { metadataReference6 }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation8.VerifyDiagnostics(expected); } [Fact] public void Operators_13() { var source1 = @" public interface I1 { public static int operator +(I1 x, I2 y) { System.Console.WriteLine(""I1.+""); return 1; } } public interface I2 { public static int operator +(I1 x, I2 y) { System.Console.WriteLine(""I2.+""); return 2; } } "; var source2 = @" class Test2: I1, I2 { static void Main() { I1 x = new Test2(); I2 y = new Test2(); var z = x + y; z = y + x; } } "; var expected = new DiagnosticDescription[] { // (8,19): error CS9342: Operator resolution is ambiguous between the following members: 'I1.operator +(I1, I2)' and 'I2.operator +(I1, I2)' // var z = x + y; Diagnostic(ErrorCode.ERR_AmbigOperator, "+").WithArguments("I1.operator +(I1, I2)", "I2.operator +(I1, I2)").WithLocation(8, 19), // (9,13): error CS0019: Operator '+' cannot be applied to operands of type 'I2' and 'I1' // z = y + x; Diagnostic(ErrorCode.ERR_BadBinaryOps, "y + x").WithArguments("+", "I2", "I1").WithLocation(9, 13) }; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(expected); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(expected); } [Fact] public void Operators_14() { var source1 = @" public interface I1 { public static int operator +(I2 x, I1 y) { System.Console.WriteLine(""I1.+""); return 1; } } public interface I2 : I1 { public static int operator +(I2 x, I1 y) { System.Console.WriteLine(""I2.+""); return 2; } } "; var source2 = @" class Test2 : I2 { static void Main() { I1 x = new Test2(); I2 y = new Test2(); var z = y + x; z = x + y; } } "; var expected = new DiagnosticDescription[] { // (8,19): error CS9342: Operator resolution is ambiguous between the following members: 'I2.operator +(I2, I1)' and 'I1.operator +(I2, I1)' // var z = y + x; Diagnostic(ErrorCode.ERR_AmbigOperator, "+").WithArguments("I2.operator +(I2, I1)", "I1.operator +(I2, I1)").WithLocation(8, 19), // (9,13): error CS0019: Operator '+' cannot be applied to operands of type 'I1' and 'I2' // z = x + y; Diagnostic(ErrorCode.ERR_BadBinaryOps, "x + y").WithArguments("+", "I1", "I2").WithLocation(9, 13) }; var compilation1 = CreateCompilation(source1, options: TestOptions.DebugDll, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(expected); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(expected); } [Fact] public void Operators_15() { var source1 = @" public class I1 { public static int operator +(I1 x, C2 y) { System.Console.WriteLine(""I1.+1""); return 1; } public static int operator +(C2 x, I1 y) { System.Console.WriteLine(""I1.+2""); return 1; } } public class I2 : I1 { public static int operator +(I2 x, C1 y) { System.Console.WriteLine(""I2.+1""); return 1; } public static int operator +(C1 x, I2 y) { System.Console.WriteLine(""I2.+2""); return 1; } } public class C1 { } public class C2 : C1 { } "; var source2 = @" class Test2: I2 { static void Main() { I2 x = new Test2(); C2 y = new C2(); var z = x + y; z = y + x; } } "; var expectedOutput = @" I2.+1 I2.+2 "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_16() { var source1 = @" public interface I1<T> { public static int operator +(I1<T> x, I1<T> y) { System.Console.WriteLine(""I1.+""); return 1; } } "; var source2 = @" class Test2: I1<object> { static void Main() { I1<object> x = new Test2(); I1<dynamic> y = new Test2(); var z = x + y; z = y + x; } } "; var expectedOutput = @" I1.+ I1.+ "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_17() { var source1 = @" public interface I1 { public static I1 operator +(I1 x, C1 y) { System.Console.WriteLine(""I1.+1""); return x; } public static I1 operator +(C1 x, I1 y) { System.Console.WriteLine(""I1.+2""); return y; } } public interface I2 : I1 {} public class C1{} "; var source2 = @" class Test2 : I2 { static void Main() { I2 x = new Test2(); C1 y = new C1(); var z = x + y; z = y + x; } } "; var expectedOutput = @" I1.+1 I1.+2 "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var source3 = @" class Test2 : I2 { static void Main() { Test2 x = new Test2(); C1 y = new C1(); var z = x + y; z = y + x; } } "; var compilation9 = CreateCompilation(source3, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); var expected9 = new DiagnosticDescription[] { // (8,17): error CS0019: Operator '+' cannot be applied to operands of type 'Test2' and 'C1' // var z = x + y; Diagnostic(ErrorCode.ERR_BadBinaryOps, "x + y").WithArguments("+", "Test2", "C1").WithLocation(8, 17), // (9,13): error CS0019: Operator '+' cannot be applied to operands of type 'C1' and 'Test2' // z = y + x; Diagnostic(ErrorCode.ERR_BadBinaryOps, "y + x").WithArguments("+", "C1", "Test2").WithLocation(9, 13) }; compilation9.VerifyDiagnostics(expected9); var compilation10 = CreateCompilation(source3, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular7_3, targetFramework: TargetFramework.NetCoreApp); compilation10.VerifyDiagnostics(expected9); } [Fact] public void Operators_18() { var source1 = @" public interface I1 { public static int operator +(I1 x, I1 y) { System.Console.WriteLine(""I1.+""); return 1; } } public interface I2 : I1 {} "; var source2 = @" class Test2: I2 { static void Main() { I2 x = new Test2(); I1 y = new Test2(); var z = x + y; z = y + x; z = x + x; z = y + y; } } "; var expectedOutput = @" I1.+ I1.+ I1.+ I1.+ "; var compilation1 = CreateCompilation(source1 + source2, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation1.VerifyDiagnostics(); CompileAndVerify(compilation1, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); CompilationReference compilationReference = compilation1.ToMetadataReference(); MetadataReference metadataReference = compilation1.EmitToImageReference(); var compilation2 = CreateCompilation(source2, new[] { compilationReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation2.VerifyDiagnostics(); CompileAndVerify(compilation2, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); var compilation3 = CreateCompilation(source2, new[] { metadataReference }, options: TestOptions.DebugExe, parseOptions: TestOptions.Regular, targetFramework: TargetFramework.NetCoreApp); compilation3.VerifyDiagnostics(); CompileAndVerify(compilation3, verify: VerifyOnMonoOrCoreClr, expectedOutput: !ExecutionConditionUtil.IsMonoOrCoreClr ? null : expectedOutput); } [Fact] public void Operators_19() { var source1 = @" public interface I1<T> { public static int operator +(I1<T> x, I1<T> y) { System.Console.WriteLine(""I1.+""); return 1; } } public interface I2<T> : I1<T> {} "; var source2 = @" class Test2: I2<object> { static void Main() { I2<object> x = new