File: Semantics\InheritanceBindingTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Semantic\Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Semantic.UnitTests)
// 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.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    /// <summary>
    /// Areas: interface mapping, virtual/abstract/override methods,
    /// virtual properties, sealed members, new members, accessibility
    /// of inherited methods, etc.
    /// </summary>
    public class InheritanceBindingTests : CompilingTestBase
    {
        [Fact]
        public void TestModifiersOnExplicitImpl()
        {
            var text = @"
interface IGoo
{
    void Method1();
    void Method2();
    void Method3();
    void Method4();
    void Method5();
    void Method6();
    void Method7();
    void Method8();
    void Method9();
    void Method10();
    void Method11();
    void Method12();
    void Method13();
    void Method14();
}
 
abstract partial class AbstractGoo : IGoo
{
    abstract void IGoo.Method1() { }
    virtual void IGoo.Method2() { }
    override void IGoo.Method3() { }
 
    sealed void IGoo.Method4() { }
 
    new void IGoo.Method5() { }
 
    public void IGoo.Method6() { }
    protected void IGoo.Method7() { }
    internal void IGoo.Method8() { }
    protected internal void IGoo.Method9() { } //roslyn considers 'protected internal' one modifier (two in dev10)
    private void IGoo.Method10() { }
 
    extern void IGoo.Method11(); //not an error (in dev10 or roslyn)
    static void IGoo.Method12() { }
    partial void IGoo.Method13();
 
    private protected void IGoo.Method14() { }
}";
 
            CreateCompilation(text, parseOptions: TestOptions.Regular9).VerifyDiagnostics(
                // (22,24): error CS0106: The modifier 'abstract' is not valid for this item
                //     abstract void IGoo.Method1() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method1").WithArguments("abstract").WithLocation(22, 24),
                // (23,23): error CS0106: The modifier 'virtual' is not valid for this item
                //     virtual void IGoo.Method2() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method2").WithArguments("virtual").WithLocation(23, 23),
                // (24,24): error CS0106: The modifier 'override' is not valid for this item
                //     override void IGoo.Method3() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method3").WithArguments("override").WithLocation(24, 24),
                // (26,22): error CS0106: The modifier 'sealed' is not valid for this item
                //     sealed void IGoo.Method4() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method4").WithArguments("sealed").WithLocation(26, 22),
                // (28,19): error CS0106: The modifier 'new' is not valid for this item
                //     new void IGoo.Method5() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method5").WithArguments("new").WithLocation(28, 19),
                // (30,22): error CS0106: The modifier 'public' is not valid for this item
                //     public void IGoo.Method6() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method6").WithArguments("public").WithLocation(30, 22),
                // (31,25): error CS0106: The modifier 'protected' is not valid for this item
                //     protected void IGoo.Method7() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method7").WithArguments("protected").WithLocation(31, 25),
                // (32,24): error CS0106: The modifier 'internal' is not valid for this item
                //     internal void IGoo.Method8() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method8").WithArguments("internal").WithLocation(32, 24),
                // (33,34): error CS0106: The modifier 'protected internal' is not valid for this item
                //     protected internal void IGoo.Method9() { } //roslyn considers 'protected internal' one modifier (two in dev10)
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method9").WithArguments("protected internal").WithLocation(33, 34),
                // (34,23): error CS0106: The modifier 'private' is not valid for this item
                //     private void IGoo.Method10() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method10").WithArguments("private").WithLocation(34, 23),
                // (37,22): error CS8703: The modifier 'static' is not valid for this item in C# 9.0. Please use language version '11.0' or greater.
                //     static void IGoo.Method12() { }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "Method12").WithArguments("static", "9.0", "11.0").WithLocation(37, 22),
                // (40,33): error CS0106: The modifier 'private protected' is not valid for this item
                //     private protected void IGoo.Method14() { }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Method14").WithArguments("private protected").WithLocation(40, 33),
                // (37,22): error CS0539: 'AbstractGoo.Method12()' in explicit interface declaration is not found among members of the interface that can be implemented
                //     static void IGoo.Method12() { }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method12").WithArguments("AbstractGoo.Method12()").WithLocation(37, 22),
                // (38,23): error CS0754: A partial member may not explicitly implement an interface member
                //     partial void IGoo.Method13();
                Diagnostic(ErrorCode.ERR_PartialMemberNotExplicit, "Method13").WithLocation(38, 23),
                // (20,38): error CS0535: 'AbstractGoo' does not implement interface member 'IGoo.Method12()'
                // abstract partial class AbstractGoo : IGoo
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IGoo").WithArguments("AbstractGoo", "IGoo.Method12()").WithLocation(20, 38),
                // (36,22): warning CS0626: Method, operator, or accessor 'AbstractGoo.IGoo.Method11()' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
                //     extern void IGoo.Method11(); //not an error (in dev10 or roslyn)
                Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "Method11").WithArguments("AbstractGoo.IGoo.Method11()").WithLocation(36, 22)
                );
        }
 
        [Fact]
        public void TestModifiersOnExplicitPropertyImpl()
        {
            var text = @"
interface IGoo
{
    int Property1 { set; }
    int Property2 { set; }
    int Property3 { set; }
    int Property4 { set; }
    int Property5 { set; }
    int Property6 { set; }
    int Property7 { set; }
    int Property8 { set; }
    int Property9 { set; }
    int Property10 { set; }
    int Property11 { set; }
    int Property12 { set; }
}
 
abstract class AbstractGoo : IGoo
{
    abstract int IGoo.Property1 { set { } }
    virtual int IGoo.Property2 { set { } }
    override int IGoo.Property3 { set { } }
 
    sealed int IGoo.Property4 { set { } }
 
    new int IGoo.Property5 { set { } }
 
    public int IGoo.Property6 { set { } }
    protected int IGoo.Property7 { set { } }
    internal int IGoo.Property8 { set { } }
    protected internal int IGoo.Property9 { set { } } //roslyn considers 'protected internal' one modifier (two in dev10)
    private int IGoo.Property10 { set { } }
 
    extern int IGoo.Property11 { set; } //not an error (in dev10 or roslyn)
    static int IGoo.Property12 { set { } }
}";
 
            CreateCompilation(text, parseOptions: TestOptions.Regular9).VerifyDiagnostics(
                // (20,23): error CS0106: The modifier 'abstract' is not valid for this item
                //     abstract int IGoo.Property1 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property1").WithArguments("abstract").WithLocation(20, 23),
                // (21,22): error CS0106: The modifier 'virtual' is not valid for this item
                //     virtual int IGoo.Property2 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property2").WithArguments("virtual").WithLocation(21, 22),
                // (22,23): error CS0106: The modifier 'override' is not valid for this item
                //     override int IGoo.Property3 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property3").WithArguments("override").WithLocation(22, 23),
                // (24,21): error CS0106: The modifier 'sealed' is not valid for this item
                //     sealed int IGoo.Property4 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property4").WithArguments("sealed").WithLocation(24, 21),
                // (26,18): error CS0106: The modifier 'new' is not valid for this item
                //     new int IGoo.Property5 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property5").WithArguments("new").WithLocation(26, 18),
                // (28,21): error CS0106: The modifier 'public' is not valid for this item
                //     public int IGoo.Property6 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property6").WithArguments("public").WithLocation(28, 21),
                // (29,24): error CS0106: The modifier 'protected' is not valid for this item
                //     protected int IGoo.Property7 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property7").WithArguments("protected").WithLocation(29, 24),
                // (30,23): error CS0106: The modifier 'internal' is not valid for this item
                //     internal int IGoo.Property8 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property8").WithArguments("internal").WithLocation(30, 23),
                // (31,33): error CS0106: The modifier 'protected internal' is not valid for this item
                //     protected internal int IGoo.Property9 { set { } } //roslyn considers 'protected internal' one modifier (two in dev10)
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property9").WithArguments("protected internal").WithLocation(31, 33),
                // (32,22): error CS0106: The modifier 'private' is not valid for this item
                //     private int IGoo.Property10 { set { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Property10").WithArguments("private").WithLocation(32, 22),
                // (35,21): error CS8703: The modifier 'static' is not valid for this item in C# 9.0. Please use language version '11.0' or greater.
                //     static int IGoo.Property12 { set { } }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "Property12").WithArguments("static", "9.0", "11.0").WithLocation(35, 21),
                // (35,21): error CS0539: 'AbstractGoo.Property12' in explicit interface declaration is not found among members of the interface that can be implemented
                //     static int IGoo.Property12 { set { } }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property12").WithArguments("AbstractGoo.Property12").WithLocation(35, 21),
                // (18,30): error CS0535: 'AbstractGoo' does not implement interface member 'IGoo.Property12'
                // abstract class AbstractGoo : IGoo
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IGoo").WithArguments("AbstractGoo", "IGoo.Property12").WithLocation(18, 30),
                // (34,34): warning CS0626: Method, operator, or accessor 'AbstractGoo.IGoo.Property11.set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
                //     extern int IGoo.Property11 { set; } //not an error (in dev10 or roslyn)
                Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("AbstractGoo.IGoo.Property11.set").WithLocation(34, 34));
        }
 
        [Fact]
        public void TestModifiersOnExplicitIndexerImpl()
        {
            var text = @"
interface IGoo
{
    int this[int x1, int x2, int x3, int x4] { set; }
    int this[int x1, int x2, int x3, long x4] { set; }
    int this[int x1, int x2, long x3, int x4] { set; }
    int this[int x1, int x2, long x3, long x4] { set; }
    int this[int x1, long x2, int x3, int x4] { set; }
    int this[int x1, long x2, int x3, long x4] { set; }
    int this[int x1, long x2, long x3, int x4] { set; }
    int this[int x1, long x2, long x3, long x4] { set; }
    int this[long x1, int x2, int x3, int x4] { set; }
    int this[long x1, int x2, int x3, long x4] { set; }
    int this[long x1, int x2, long x3, int x4] { set; }
    int this[long x1, int x2, long x3, long x4] { set; }
}
 
abstract class AbstractGoo : IGoo
{
    abstract int IGoo.this[int x1, int x2, int x3, int x4] { set { } }
    virtual int IGoo.this[int x1, int x2, int x3, long x4] { set { } }
    override int IGoo.this[int x1, int x2, long x3, int x4] { set { } }
 
    sealed int IGoo.this[int x1, int x2, long x3, long x4] { set { } }
 
    new int IGoo.this[int x1, long x2, int x3, int x4] { set { } }
 
    public int IGoo.this[int x1, long x2, int x3, long x4] { set { } }
    protected int IGoo.this[int x1, long x2, long x3, int x4] { set { } }
    internal int IGoo.this[int x1, long x2, long x3, long x4] { set { } }
    protected internal int IGoo.this[long x1, int x2, int x3, int x4] { set { } } //roslyn considers 'protected internal' one modifier (two in dev10)
    private int IGoo.this[long x1, int x2, int x3, long x4] { set { } }
 
    extern int IGoo.this[long x1, int x2, long x3, int x4] { set; } //not an error (in dev10 or roslyn)
    static int IGoo.this[long x1, int x2, long x3, long x4] { set { } }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (20,23): error CS0106: The modifier 'abstract' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("abstract"),
                // (21,22): error CS0106: The modifier 'virtual' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("virtual"),
                // (22,23): error CS0106: The modifier 'override' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("override"),
                // (24,21): error CS0106: The modifier 'sealed' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("sealed"),
                // (26,18): error CS0106: The modifier 'new' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("new"),
                // (28,21): error CS0106: The modifier 'public' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("public"),
                // (29,24): error CS0106: The modifier 'protected' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected"),
                // (30,23): error CS0106: The modifier 'internal' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("internal"),
                // (31,33): error CS0106: The modifier 'protected internal' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("protected internal"),
                // (32,22): error CS0106: The modifier 'private' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("private"),
                // (35,21): error CS0106: The modifier 'static' is not valid for this item
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static"),
                // (34,62): warning CS0626: Method, operator, or accessor 'AbstractGoo.IGoo.this[long, int, long, int].set' is marked external and has no attributes on it. Consider adding a DllImport attribute to specify the external implementation.
                Diagnostic(ErrorCode.WRN_ExternMethodNoImplementation, "set").WithArguments("AbstractGoo.IGoo.this[long, int, long, int].set"));
        }
 
        [Fact, WorkItem(542158, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542158")]
        public void TestModifiersOnExplicitEventImpl()
        {
            var text = @"
interface IGoo
{
    event System.Action Event1;
    event System.Action Event2;
    event System.Action Event3;
    event System.Action Event4;
    event System.Action Event5;
    event System.Action Event6;
    event System.Action Event7;
    event System.Action Event8;
    event System.Action Event9;
    event System.Action Event10;
    event System.Action Event11;
    event System.Action Event12;
}
 
abstract class AbstractGoo : IGoo
{
    abstract event System.Action IGoo.Event1 { add { } remove { } }
    virtual event System.Action IGoo.Event2 { add { } remove { } }
    override event System.Action IGoo.Event3 { add { } remove { } }
 
    sealed event System.Action IGoo.Event4 { add { } remove { } }
 
    new event System.Action IGoo.Event5 { add { } remove { } }
 
    public event System.Action IGoo.Event6 { add { } remove { } }
    protected event System.Action IGoo.Event7 { add { } remove { } }
    internal event System.Action IGoo.Event8 { add { } remove { } }
    protected internal event System.Action IGoo.Event9 { add { } remove { } } //roslyn considers 'protected internal' one modifier (two in dev10)
    private event System.Action IGoo.Event10 { add { } remove { } }
 
    extern event System.Action IGoo.Event11 { add { } remove { } }
    static event System.Action IGoo.Event12 { add { } remove { } }
}";
            // It seems Dev11 doesn't report ERR_ExternHasBody errors for Event11 accessors
            // if there are other explicitly implemented members with erroneous modifiers other than extern and abstract.
            // If the other errors are fixed ERR_ExternHasBody is reported. 
            // We report all errors at once since they are unrelated, not cascading.
 
            CreateCompilation(text, parseOptions: TestOptions.Regular9).VerifyDiagnostics(
                // (20,39): error CS0106: The modifier 'abstract' is not valid for this item
                //     abstract event System.Action IGoo.Event1 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event1").WithArguments("abstract").WithLocation(20, 39),
                // (21,38): error CS0106: The modifier 'virtual' is not valid for this item
                //     virtual event System.Action IGoo.Event2 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event2").WithArguments("virtual").WithLocation(21, 38),
                // (22,39): error CS0106: The modifier 'override' is not valid for this item
                //     override event System.Action IGoo.Event3 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event3").WithArguments("override").WithLocation(22, 39),
                // (24,37): error CS0106: The modifier 'sealed' is not valid for this item
                //     sealed event System.Action IGoo.Event4 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event4").WithArguments("sealed").WithLocation(24, 37),
                // (26,34): error CS0106: The modifier 'new' is not valid for this item
                //     new event System.Action IGoo.Event5 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event5").WithArguments("new").WithLocation(26, 34),
                // (28,37): error CS0106: The modifier 'public' is not valid for this item
                //     public event System.Action IGoo.Event6 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event6").WithArguments("public").WithLocation(28, 37),
                // (29,40): error CS0106: The modifier 'protected' is not valid for this item
                //     protected event System.Action IGoo.Event7 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event7").WithArguments("protected").WithLocation(29, 40),
                // (30,39): error CS0106: The modifier 'internal' is not valid for this item
                //     internal event System.Action IGoo.Event8 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event8").WithArguments("internal").WithLocation(30, 39),
                // (31,49): error CS0106: The modifier 'protected internal' is not valid for this item
                //     protected internal event System.Action IGoo.Event9 { add { } remove { } } //roslyn considers 'protected internal' one modifier (two in dev10)
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event9").WithArguments("protected internal").WithLocation(31, 49),
                // (32,38): error CS0106: The modifier 'private' is not valid for this item
                //     private event System.Action IGoo.Event10 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_BadMemberFlag, "Event10").WithArguments("private").WithLocation(32, 38),
                // (34,47): error CS0179: 'AbstractGoo.IGoo.Event11.add' cannot be extern and declare a body
                //     extern event System.Action IGoo.Event11 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_ExternHasBody, "add").WithArguments("AbstractGoo.IGoo.Event11.add").WithLocation(34, 47),
                // (34,55): error CS0179: 'AbstractGoo.IGoo.Event11.remove' cannot be extern and declare a body
                //     extern event System.Action IGoo.Event11 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_ExternHasBody, "remove").WithArguments("AbstractGoo.IGoo.Event11.remove").WithLocation(34, 55),
                // (35,37): error CS8703: The modifier 'static' is not valid for this item in C# 9.0. Please use language version '11.0' or greater.
                //     static event System.Action IGoo.Event12 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_InvalidModifierForLanguageVersion, "Event12").WithArguments("static", "9.0", "11.0").WithLocation(35, 37),
                // (35,37): error CS0539: 'AbstractGoo.Event12' in explicit interface declaration is not found among members of the interface that can be implemented
                //     static event System.Action IGoo.Event12 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Event12").WithArguments("AbstractGoo.Event12").WithLocation(35, 37),
                // (18,30): error CS0535: 'AbstractGoo' does not implement interface member 'IGoo.Event12'
                // abstract class AbstractGoo : IGoo
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "IGoo").WithArguments("AbstractGoo", "IGoo.Event12").WithLocation(18, 30)
                );
        }
 
        [Fact] // can't bind to events
        public void TestInvokeExplicitMemberDirectly()
        {
            // Tests:
            // Sanity check – it should be an error to invoke a member by its fully qualified explicit implementation name
 
            var text = @"
interface Interface
{
    void Method<T>();
    void Method(int i, long j);
    long Property { set; }
    event System.Action Event;
}
class Class : Interface
{
    void Interface.Method(int i, long j)
    {
        Interface.Method(1, 2);
    }
 
    void Interface.Method<T>()
    {
        Interface.Method<T>();
    }
    
    long Interface.Property { set { } }
 
    event System.Action Interface.Event { add { } remove { } }
 
    void Test()
    {
        Interface.Property = 2;
        Interface.Event += null;
 
        Class c = new Class();
        c.Interface.Method(1, 2);
        c.Interface.Method<string>();
        c.Interface.Property = 2;
        c.Interface.Event += null;
    }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (13,9): error CS0120: An object reference is required for the non-static field, method, or property 'Interface.Method(int, long)'
                //         Interface.Method(1, 2);
                Diagnostic(ErrorCode.ERR_ObjectRequired, "Interface.Method").WithArguments("Interface.Method(int, long)").WithLocation(13, 9),
                // (18,9): error CS0120: An object reference is required for the non-static field, method, or property 'Interface.Method<T>()'
                //         Interface.Method<T>();
                Diagnostic(ErrorCode.ERR_ObjectRequired, "Interface.Method<T>").WithArguments("Interface.Method<T>()").WithLocation(18, 9),
                // (27,9): error CS0120: An object reference is required for the non-static field, method, or property 'Interface.Property'
                //         Interface.Property = 2;
                Diagnostic(ErrorCode.ERR_ObjectRequired, "Interface.Property").WithArguments("Interface.Property").WithLocation(27, 9),
                // (28,9): error CS0120: An object reference is required for the non-static field, method, or property 'Interface.Event'
                //         Interface.Event += null;
                Diagnostic(ErrorCode.ERR_ObjectRequired, "Interface.Event").WithArguments("Interface.Event").WithLocation(28, 9),
                // (31,11): error CS1061: 'Class' does not contain a definition for 'Interface' and no extension method 'Interface' accepting a first argument of type 'Class' could be found (are you missing a using directive or an assembly reference?)
                //         c.Interface.Method(1, 2);
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Interface").WithArguments("Class", "Interface").WithLocation(31, 11),
                // (32,11): error CS1061: 'Class' does not contain a definition for 'Interface' and no extension method 'Interface' accepting a first argument of type 'Class' could be found (are you missing a using directive or an assembly reference?)
                //         c.Interface.Method<string>();
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Interface").WithArguments("Class", "Interface").WithLocation(32, 11),
                // (33,11): error CS1061: 'Class' does not contain a definition for 'Interface' and no extension method 'Interface' accepting a first argument of type 'Class' could be found (are you missing a using directive or an assembly reference?)
                //         c.Interface.Property = 2;
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Interface").WithArguments("Class", "Interface").WithLocation(33, 11),
                // (34,11): error CS1061: 'Class' does not contain a definition for 'Interface' and no extension method 'Interface' accepting a first argument of type 'Class' could be found (are you missing a using directive or an assembly reference?)
                //         c.Interface.Event += null;
                Diagnostic(ErrorCode.ERR_NoSuchMemberOrExtension, "Interface").WithArguments("Class", "Interface").WithLocation(34, 11));
        }
 
        [Fact]
        public void TestHidesAbstractMethod()
        {
            var text = @"
abstract class AbstractGoo
{
    public abstract void Method1();
    public abstract void Method2();
    public abstract void Method3();
}
 
abstract class Goo : AbstractGoo
{
    public void Method1() { }
    public abstract void Method2();
    public virtual void Method3() { }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 11, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 11, Column = 17 },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 12, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 12, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 13, Column = 25, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 13, Column = 25 },
            });
        }
 
        [Fact]
        public void TestHidesAbstractProperty()
        {
            var text = @"
abstract class AbstractGoo
{
    public abstract long Property1 { set; }
    public abstract long Property2 { set; }
    public abstract long Property3 { set; }
}
 
abstract class Goo : AbstractGoo
{
    public long Property1 { set { } }
    public abstract long Property2 { set; }
    public virtual long Property3 { set { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 11, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 11, Column = 17 },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 12, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 12, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 13, Column = 25, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 13, Column = 25 },
            });
        }
 
        [Fact]
        public void TestHidesAbstractIndexer()
        {
            var text = @"
abstract class AbstractGoo
{
    public abstract long this[int x] { set; }
    public abstract long this[string x] { set; }
    public abstract long this[char x] { set; }
}
 
abstract class Goo : AbstractGoo
{
    public long this[int x] { set { } }
    public abstract long this[string x] { set; }
    public virtual long this[char x] { set { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 11, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 11, Column = 17 },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 12, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 12, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 13, Column = 25, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod,  Line = 13, Column = 25 },
            });
        }
 
        [Fact]
        public void TestHidesAbstractEvent()
        {
            var text = @"
abstract class AbstractGoo
{
    public abstract event System.Action Event1;
    public abstract event System.Action Event2;
    public abstract event System.Action Event3;
}
 
abstract class Goo : AbstractGoo
{
    public event System.Action Event1 { add { } remove { } }
    public abstract event System.Action Event2;
    public virtual event System.Action Event3 { add { } remove { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (11,32): error CS0533: 'Goo.Event1' hides inherited abstract member 'AbstractGoo.Event1'
                //     public event System.Action Event1 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Event1").WithArguments("Goo.Event1", "AbstractGoo.Event1"),
                // (11,32): warning CS0114: 'Goo.Event1' hides inherited member 'AbstractGoo.Event1'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public event System.Action Event1 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event1").WithArguments("Goo.Event1", "AbstractGoo.Event1"),
                // (12,41): error CS0533: 'Goo.Event2' hides inherited abstract member 'AbstractGoo.Event2'
                //     public abstract event System.Action Event2 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Event2").WithArguments("Goo.Event2", "AbstractGoo.Event2"),
                // (12,41): warning CS0114: 'Goo.Event2' hides inherited member 'AbstractGoo.Event2'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public abstract event System.Action Event2 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event2").WithArguments("Goo.Event2", "AbstractGoo.Event2"),
                // (13,40): error CS0533: 'Goo.Event3' hides inherited abstract member 'AbstractGoo.Event3'
                //     public virtual event System.Action Event3 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Event3").WithArguments("Goo.Event3", "AbstractGoo.Event3"),
                // (13,40): warning CS0114: 'Goo.Event3' hides inherited member 'AbstractGoo.Event3'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public virtual event System.Action Event3 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event3").WithArguments("Goo.Event3", "AbstractGoo.Event3"));
        }
 
        [Fact]
        public void TestNoMethodToOverride()
        {
            var text = @"
interface Interface
{
    void Method0();
}
 
class Base
{
    public virtual void Method1() { }
    private void Method2() { }
}
 
class Derived : Base, Interface
{
    public override void Method0() { }
    public override void Method1(int x) { }
    public override void Method2() { }
    public override void Method3() { }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 15, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 16, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 17, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 18, Column = 26 },
            });
        }
 
        [Fact]
        public void TestNoPropertyToOverride()
        {
            var text = @"
interface Interface
{
    int Property0 { get; set; }
}
 
class Base
{
    public virtual int Property1 { get; set; }
    private int Property2 { get; set; }
    public virtual int Property3 { get { return 0; } }
    public virtual int Property4 { get { return 0; } }
    public virtual int Property5 { set { } }
    public virtual int Property6 { set { } }
    public virtual int Property7 { get; set; }
    public virtual int Property8 { get; set; }
}
 
class Derived : Base, Interface
{
    public override int Property0 { get; set; } //iface
    public override double Property1 { get; set; } //wrong type
    public override int Property2 { get; set; } //inaccessible
    public override int Property3 { set { } } //wrong accessor(s)
    public override int Property4 { get; set; } //wrong accessor(s)
    public override int Property5 { get { return 0; } } //wrong accessor(s)
    public override int Property6 { get; set; } //wrong accessor(s)
    public override int Property7 { get { return 0; } } //wrong accessor(s)
    public override int Property8 { set { } } //wrong accessor(s)
    public override int Property9 { get; set; } //nothing to override
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 21, Column = 25 }, //0
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 22, Column = 28 }, //1
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 23, Column = 25 }, //2
                new ErrorDescription { Code = (int)ErrorCode.ERR_NoSetToOverride, Line = 24, Column = 37 }, //3.set
                new ErrorDescription { Code = (int)ErrorCode.ERR_NoSetToOverride, Line = 25, Column = 42 }, //4.set
                new ErrorDescription { Code = (int)ErrorCode.ERR_NoGetToOverride, Line = 26, Column = 37 }, //5.get
                new ErrorDescription { Code = (int)ErrorCode.ERR_NoGetToOverride, Line = 27, Column = 37 }, //6.get
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 30, Column = 25 }, //9
            });
        }
 
        [Fact]
        public void TestNoIndexerToOverride()
        {
            var text = @"
interface Interface
{
    int this[long w, long x, long y, long z] { get; set; }
}
 
class Base
{
    public virtual int this[long w, long x, long y, char z] { get { return 0; } set { } }
    private int this[long w, long x, char y, long z] { get { return 0; } set { } }
    public virtual int this[long w, long x, char y, char z] { get { return 0; } }
    public virtual int this[long w, char x, long y, long z] { get { return 0; } }
    public virtual int this[long w, char x, long y, char z] { set { } }
    public virtual int this[long w, char x, char y, long z] { set { } }
    public virtual int this[long w, char x, char y, char z] { get { return 0; } set { } }
    public virtual int this[char w, long x, long y, long z] { get { return 0; } set { } }
}
 
class Derived : Base, Interface
{
    public override int this[long w, long x, long y, long z] { get { return 0; } set { } } //iface
    public override double this[long w, long x, long y, char z] { get { return 0; } set { } } //wrong type
    public override int this[long w, long x, char y, long z] { get { return 0; } set { } } //inaccessible
    public override int this[long w, long x, char y, char z] { set { } } //wrong accessor(s)
    public override int this[long w, char x, long y, long z] { get { return 0; } set { } } //wrong accessor(s)
    public override int this[long w, char x, long y, char z] { get { return 0; } } //wrong accessor(s)
    public override int this[long w, char x, char y, long z] { get { return 0; } set { } } //wrong accessor(s)
    public override int this[long w, char x, char y, char z] { get { return 0; } } //wrong accessor(s)
    public override int this[char w, long x, long y, long z] { set { } } //wrong accessor(s)
    public override int this[string s] { get { return 0; } set { } } //nothing to override
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (21,25): error CS0115: 'Derived.this[long, long, long, long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[long, long, long, long]"),
                // (22,28): error CS1715: 'Derived.this[long, long, long, char]': type must be 'int' to match overridden member 'Base.this[long, long, long, char]'
                Diagnostic(ErrorCode.ERR_CantChangeTypeOnOverride, "this").WithArguments("Derived.this[long, long, long, char]", "Base.this[long, long, long, char]", "int"),
                // (23,25): error CS0115: 'Derived.this[long, long, char, long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[long, long, char, long]"),
                // (24,64): error CS0546: 'Derived.this[long, long, char, char].set': cannot override because 'Base.this[long, long, char, char]' does not have an overridable set accessor
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "set").WithArguments("Derived.this[long, long, char, char].set", "Base.this[long, long, char, char]"),
                // (25,82): error CS0546: 'Derived.this[long, char, long, long].set': cannot override because 'Base.this[long, char, long, long]' does not have an overridable set accessor
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "set").WithArguments("Derived.this[long, char, long, long].set", "Base.this[long, char, long, long]"),
                // (26,64): error CS0545: 'Derived.this[long, char, long, char].get': cannot override because 'Base.this[long, char, long, char]' does not have an overridable get accessor
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived.this[long, char, long, char].get", "Base.this[long, char, long, char]"),
                // (27,64): error CS0545: 'Derived.this[long, char, char, long].get': cannot override because 'Base.this[long, char, char, long]' does not have an overridable get accessor
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived.this[long, char, char, long].get", "Base.this[long, char, char, long]"),
                // (30,25): error CS0115: 'Derived.this[string]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[string]"));
        }
 
        [Fact]
        public void TestNoEventToOverride()
        {
            var text = @"
interface Interface
{
    event System.Action Event0;
}
 
class Base
{
    public virtual event System.Action Event1 { add { } remove { } }
    private event System.Action Event2 { add { } remove { } }
}
 
class Derived : Base, Interface
{
    public override event System.Action Event0 { add { } remove { } } //iface
    public override event System.Func<int> Event1 { add { } remove { } } //wrong type
    public override event System.Action Event2 { add { } remove { } } //inaccessible
    public override event System.Action Event3 { add { } remove { } } //nothing to override
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (15,41): error CS0115: 'Derived.Event0': no suitable method found to override
                //     public override event System.Action Event0 { add { } remove { } } //iface
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Event0").WithArguments("Derived.Event0"),
                // (16,44): error CS1715: 'Derived.Event1': type must be 'System.Action' to match overridden member 'Base.Event1'
                //     public override event System.Func<int> Event1 { add { } remove { } } //wrong type
                Diagnostic(ErrorCode.ERR_CantChangeTypeOnOverride, "Event1").WithArguments("Derived.Event1", "Base.Event1", "System.Action"),
                // (17,41): error CS0115: 'Derived.Event2': no suitable method found to override
                //     public override event System.Action Event2 { add { } remove { } } //inaccessible
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Event2").WithArguments("Derived.Event2"),
                // (18,41): error CS0115: 'Derived.Event3': no suitable method found to override
                //     public override event System.Action Event3 { add { } remove { } } //nothing to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Event3").WithArguments("Derived.Event3"));
        }
 
        [Fact]
        public void TestSuppressOverrideNotExpectedErrorWhenMethodParameterTypeNotFound()
        {
            var text = @"
class Base
{
}
 
class Derived : Base
{
    public override void Method0(String x) { }
    public override void Method1(string x, String y) { }
    public override void Method2(String[] x) { }
    public override void Method3(System.Func<String> x) { }
    public override void Method4((string a, String b) x) { }
    public override void Method5(System.Func<(string a, String[] b)> x) { }
    public override void Method6(Outer<String>.Inner<string> x) { }
    public override void Method7(Outer<string>.Inner<String> x) { }
    public override void Method8(Int? x) { }
}
 
class Outer<T>
{
    public class Inner<U>{}
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,34): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method0(String x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(8, 34),
                // (9,44): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method1(string x, String y) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(9, 44),
                // (10,34): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method2(String[] x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(10, 34),
                // (11,46): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method3(System.Func<String> x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(11, 46),
                // (12,45): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method4((string a, String b) x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(12, 45),
                // (13,57): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method5(System.Func<(string a, String[] b)> x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(13, 57),
                // (14,40): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method6(Outer<String>.Inner<string> x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(14, 40),
                // (15,54): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method7(Outer<string>.Inner<String> x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(15, 54),
                // (16,34): error CS0246: The type or namespace name 'Int' could not be found (are you missing a using directive or an assembly reference?)
                //     public override void Method8(Int? x) { }
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int").WithArguments("Int").WithLocation(16, 34));
        }
 
        [Fact]
        public void TestSuppressOverrideNotExpectedErrorWhenIndexerParameterTypeNotFound()
        {
            var text = @"
class Base
{
}
 
class Derived : Base
{
    public override int this[String x] => 0;
    public override int this[string x, String y] => 0;
    public override int this[String[] x] => 0;
    public override int this[System.Func<String> x] => 0;
    public override int this[(string a, String b) x] => 0;
    public override int this[System.Func<(string a, String[] b)> x] => 0;
    public override int this[Outer<String>.Inner<string> x] => 0;
    public override int this[Outer<string>.Inner<String> x] => 0;
    public override int this[Int? x] => 0;
}
 
class Outer<T>
{
    public class Inner<U>{}
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,30): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[String x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(8, 30),
                // (9,40): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[string x, String y] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(9, 40),
                // (10,30): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[String[] x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(10, 30),
                // (11,42): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[System.Func<String> x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(11, 42),
                // (12,41): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[(string a, String b) x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(12, 41),
                // (13,53): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[System.Func<(string a, String[] b)> x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(13, 53),
                // (14,36): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[Outer<String>.Inner<string> x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(14, 36),
                // (15,50): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[Outer<string>.Inner<String> x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(15, 50),
                // (16,30): error CS0246: The type or namespace name 'Int' could not be found (are you missing a using directive or an assembly reference?)
                //     public override int this[Int? x] => 0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int").WithArguments("Int").WithLocation(16, 30));
        }
 
        [Fact]
        public void TestSuppressCantChangeReturnTypeErrorWhenMethodReturnTypeNotFound()
        {
            var text = @"
abstract class Base
{
    public abstract void Method0();
    public abstract void Method1();
    public abstract void Method2();
    public abstract void Method3();
    public abstract void Method4();
    public abstract void Method5();
    public abstract void Method6();
    public abstract void Method7();
}
 
class Derived : Base
{
    public override String Method0() => null;
    public override String[] Method1() => null;
    public override System.Func<String> Method2() => null;
    public override (string a, String b) Method3() => (null, null);
    public override System.Func<(string a, String[] b)> Method4() => null;
    public override Outer<String>.Inner<string> Method5() => null;
    public override Outer<string>.Inner<String> Method6() => null;
    public override Int? Method7() => null;
}
 
class Outer<T>
{
    public class Inner<U> { }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (16,21): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override String Method0() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(16, 21),
                // (17,21): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override String[] Method1() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(17, 21),
                // (18,33): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override System.Func<String> Method2() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(18, 33),
                // (19,32): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override (string a, String b) Method3() => (null, null);
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(19, 32),
                // (20,44): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override System.Func<(string a, String[] b)> Method4() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(20, 44),
                // (21,27): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Outer<String>.Inner<string> Method5() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(21, 27),
                // (22,41): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Outer<string>.Inner<String> Method6() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(22, 41),
                // (23,21): error CS0246: The type or namespace name 'Int' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Int? Method7() => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int").WithArguments("Int").WithLocation(23, 21));
        }
 
        [Fact]
        public void TestSuppressCantChangeTypeErrorWhenPropertyTypeNotFound()
        {
            var text = @"
abstract class Base
{
    public abstract int Property0 { get; }
    public abstract int Property1 { get; }
    public abstract int Property2 { get; }
    public abstract int Property3 { get; }
    public abstract int Property4 { get; }
    public abstract int Property5 { get; }
    public abstract int Property6 { get; }
    public abstract int Property7 { get; }
}
 
class Derived : Base
{
    public override String Property0 => null;
    public override String[] Property1 => null;
    public override System.Func<String> Property2 => null;
    public override (string a, String b) Property3 => (null, null);
    public override System.Func<(string a, String[] b)> Property4 => null;
    public override Outer<String>.Inner<string> Property5 => null;
    public override Outer<string>.Inner<String> Property6 => null;
    public override Int? Property7 => null;
}
 
class Outer<T>
{
    public class Inner<U> { }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (16,21): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override String Property0 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(16, 21),
                // (17,21): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override String[] Property1 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(17, 21),
                // (18,33): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override System.Func<String> Property2 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(18, 33),
                // (19,32): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override (string a, String b) Property3 => (null, null);
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(19, 32),
                // (20,44): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override System.Func<(string a, String[] b)> Property4 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(20, 44),
                // (21,27): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Outer<String>.Inner<string> Property5 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(21, 27),
                // (22,41): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Outer<string>.Inner<String> Property6 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(22, 41),
                // (23,21): error CS0246: The type or namespace name 'Int' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Int? Property7 => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int").WithArguments("Int").WithLocation(23, 21));
        }
 
        [Fact]
        public void TestSuppressCantChangeTypeErrorWhenIndexerTypeNotFound()
        {
            var text = @"
abstract class Base
{
    public abstract int this[int index] { get; }
}
 
class Derived : Base
{
    public override String this[int index] => null;
    public override String[] this[int index] => null;
    public override System.Func<String> this[int index] => null;
    public override (string a, String b) this[int index] => (null, null);
    public override System.Func<(string a, String[] b)> this[int index] => null;
    public override Outer<String>.Inner<string> this[int index] => null;
    public override Outer<string>.Inner<String> this[int index] => null;
    public override Int? this[int index] => null;
}
 
class Outer<T>
{
    public class Inner<U> { }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (9,21): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override String this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(9, 21),
                // (10,21): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override String[] this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(10, 21),
                // (11,33): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override System.Func<String> this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(11, 33),
                // (12,32): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override (string a, String b) this[int index] => (null, null);
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(12, 32),
                // (13,44): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override System.Func<(string a, String[] b)> this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(13, 44),
                // (14,27): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Outer<String>.Inner<string> this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(14, 27),
                // (15,41): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Outer<string>.Inner<String> this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(15, 41),
                // (16,21): error CS0246: The type or namespace name 'Int' could not be found (are you missing a using directive or an assembly reference?)
                //     public override Int? this[int index] => null;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int").WithArguments("Int").WithLocation(16, 21),
                // (10,30): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override String[] this[int index] => null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(10, 30),
                // (11,41): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override System.Func<String> this[int index] => null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(11, 41),
                // (12,42): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override (string a, String b) this[int index] => (null, null);
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(12, 42),
                // (13,57): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override System.Func<(string a, String[] b)> this[int index] => null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(13, 57),
                // (14,49): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override Outer<String>.Inner<string> this[int index] => null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(14, 49),
                // (15,49): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override Outer<string>.Inner<String> this[int index] => null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(15, 49),
                // (16,26): error CS0111: Type 'Derived' already defines a member called 'this' with the same parameter types
                //     public override Int? this[int index] => null;
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "this").WithArguments("this", "Derived").WithLocation(16, 26));
        }
 
        [Fact]
        public void TestSuppressCantChangeTypeErrorWhenEventTypeNotFound()
        {
            var text = @"
abstract class Base
{
    public abstract event System.Action Event0;
    public abstract event System.Action Event1;
    public abstract event System.Action Event2;
    public abstract event System.Action Event3;
    public abstract event System.Action Event4;
    public abstract event System.Action Event5;
    public abstract event System.Action Event6;
    public abstract event System.Action Event7;
}
 
class Derived : Base
{
    public override event String Event0;
    public override event String[] Event1;
    public override event System.Func<String> Event2;
    public override event (string a, String b) Event3;
    public override event System.Func<(string a, String[] b)> Event4;
    public override event Outer<String>.Inner<string> Event5;
    public override event Outer<string>.Inner<String> Event6;
    public override event Int? Event7;
}
 
class Outer<T>
{
	public class Inner<U> { }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (16,27): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event String Event0;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(16, 27),
                // (17,27): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event String[] Event1;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(17, 27),
                // (18,39): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event System.Func<String> Event2;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(18, 39),
                // (19,38): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event (string a, String b) Event3;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(19, 38),
                // (20,50): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event System.Func<(string a, String[] b)> Event4;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(20, 50),
                // (21,33): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event Outer<String>.Inner<string> Event5;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(21, 33),
                // (22,47): error CS0246: The type or namespace name 'String' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event Outer<string>.Inner<String> Event6;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "String").WithArguments("String").WithLocation(22, 47),
                // (23,27): error CS0246: The type or namespace name 'Int' could not be found (are you missing a using directive or an assembly reference?)
                //     public override event Int? Event7;
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "Int").WithArguments("Int").WithLocation(23, 27),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event6.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event6.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event1.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event1.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event1.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event1.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event5.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event5.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event3.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event3.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event2.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event2.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event4.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event4.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event4.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event4.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event3.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event3.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event7.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event7.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event0.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event0.add").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event6.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event6.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event2.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event2.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event7.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event7.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event0.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event0.remove").WithLocation(14, 7),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event5.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event5.remove").WithLocation(14, 7),
                // (17,36): error CS0066: 'Derived.Event1': event must be of a delegate type
                //     public override event String[] Event1;
                Diagnostic(ErrorCode.ERR_EventNotDelegate, "Event1").WithArguments("Derived.Event1").WithLocation(17, 36),
                // (19,48): error CS0066: 'Derived.Event3': event must be of a delegate type
                //     public override event (string a, String b) Event3;
                Diagnostic(ErrorCode.ERR_EventNotDelegate, "Event3").WithArguments("Derived.Event3").WithLocation(19, 48),
                // (21,55): error CS0066: 'Derived.Event5': event must be of a delegate type
                //     public override event Outer<String>.Inner<string> Event5;
                Diagnostic(ErrorCode.ERR_EventNotDelegate, "Event5").WithArguments("Derived.Event5").WithLocation(21, 55),
                // (22,55): error CS0066: 'Derived.Event6': event must be of a delegate type
                //     public override event Outer<string>.Inner<String> Event6;
                Diagnostic(ErrorCode.ERR_EventNotDelegate, "Event6").WithArguments("Derived.Event6").WithLocation(22, 55),
                // (23,32): error CS0066: 'Derived.Event7': event must be of a delegate type
                //     public override event Int? Event7;
                Diagnostic(ErrorCode.ERR_EventNotDelegate, "Event7").WithArguments("Derived.Event7").WithLocation(23, 32),
                // (19,48): warning CS0067: The event 'Derived.Event3' is never used
                //     public override event (string a, String b) Event3;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event3").WithArguments("Derived.Event3").WithLocation(19, 48),
                // (23,32): warning CS0067: The event 'Derived.Event7' is never used
                //     public override event Int? Event7;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event7").WithArguments("Derived.Event7").WithLocation(23, 32),
                // (17,36): warning CS0067: The event 'Derived.Event1' is never used
                //     public override event String[] Event1;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event1").WithArguments("Derived.Event1").WithLocation(17, 36),
                // (22,55): warning CS0067: The event 'Derived.Event6' is never used
                //     public override event Outer<string>.Inner<String> Event6;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event6").WithArguments("Derived.Event6").WithLocation(22, 55),
                // (18,47): warning CS0067: The event 'Derived.Event2' is never used
                //     public override event System.Func<String> Event2;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event2").WithArguments("Derived.Event2").WithLocation(18, 47),
                // (21,55): warning CS0067: The event 'Derived.Event5' is never used
                //     public override event Outer<String>.Inner<string> Event5;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event5").WithArguments("Derived.Event5").WithLocation(21, 55),
                // (20,63): warning CS0067: The event 'Derived.Event4' is never used
                //     public override event System.Func<(string a, String[] b)> Event4;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event4").WithArguments("Derived.Event4").WithLocation(20, 63),
                // (16,34): warning CS0067: The event 'Derived.Event0' is never used
                //     public override event String Event0;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event0").WithArguments("Derived.Event0").WithLocation(16, 34));
        }
 
        [Fact]
        public void TestOverrideSealedMethod()
        {
            var text = @"
class Base
{
    public sealed override string ToString()
    {
        return ""Base"";
    }
}
 
class Derived : Base
{
    public override string ToString()
    {
        return ""Derived"";
    }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideSealed, Line = 12, Column = 28 },
            });
        }
 
        [Fact]
        public void TestOverrideSealedProperty()
        {
            var text = @"
class Base0
{
    public virtual int Property { get; set; }
}
 
class Base : Base0
{
    public sealed override int Property { get; set; }
}
 
class Derived : Base
{
    public override int Property { get; set; }
}
";
            // CONSIDER: Dev10 reports on both accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideSealed, Line = 14, Column = 25 }, //Derived.Property
            });
        }
 
        [Fact]
        public void TestOverrideSealedIndexer()
        {
            var text = @"
class Base0
{
    public virtual int this[int x] { get { return 0; } set { } }
}
 
class Base : Base0
{
    public sealed override int this[int x] { get { return 0; } set { } }
}
 
class Derived : Base
{
    public override int this[int x] { get { return 0; } set { } }
}
";
            // CONSIDER: Dev10 reports on both accessors, but not on the indexer itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideSealed, Line = 14, Column = 25 }, //Derived indexer
            });
        }
 
        [Fact]
        public void TestOverrideSealedEvents()
        {
            var text = @"
class Base0
{
    public virtual event System.Action Event { add { } remove { } }
}
 
class Base : Base0
{
    public sealed override event System.Action Event { add { } remove { } }
}
 
class Derived : Base
{
    public override event System.Action Event { add { } remove { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (14,41): error CS0239: 'Derived.Event': cannot override inherited member 'Base.Event' because it is sealed
                //     public override event System.Action Event { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideSealed, "Event").WithArguments("Derived.Event", "Base.Event"));
        }
 
        [Fact]
        public void TestOverrideSealedPropertyOmitAccessors()
        {
            var text = @"
class Base0
{
    public virtual int Property { get; set; }
}
 
class Base : Base0
{
    public sealed override int Property { set { } }
}
 
class Derived : Base
{
    public override int Property { get { return 0; } }
}
";
            // CONSIDER: Dev10 reports on accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideSealed, Line = 14, Column = 25 }, //Derived.Property
            });
        }
 
        [Fact]
        public void TestOverrideSealedIndexerOmitAccessors()
        {
            var text = @"
class Base0
{
    public virtual int this[int x] { get { return 0; } set { } }
}
 
class Base : Base0
{
    public sealed override int this[int x] { set { } }
}
 
class Derived : Base
{
    public override int this[int x] { get { return 0; } }
}
";
            // CONSIDER: Dev10 reports on accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideSealed, Line = 14, Column = 25 }, //Derived indexer
            });
        }
 
        [Fact]
        public void TestOverrideSameMemberMultipleTimes()
        {
            // Tests:
            // Override same virtual / abstract member more than once in different parts of a (partial) derived type
 
            var text = @"
using @str = System.String;
 
class Base
{
    public virtual string Method1() { return string.Empty; }
    public virtual string Method2() { return string.Empty; }
}
 
class Derived : Base
{
    public override System.String Method1() { return null; }
    public override string Method1() { return null; }
}
 
partial class Derived2 : Base
{
    public override string Method2() { return null; }
}
partial class Derived2
{
    public override string Method2() { return null; }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (13,28): error CS0111: Type 'Derived' already defines a member called 'Method1' with the same parameter types
                //     public override string Method1() { return null; }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method1").WithArguments("Method1", "Derived").WithLocation(13, 28),
                // (22,28): error CS0111: Type 'Derived2' already defines a member called 'Method2' with the same parameter types
                //     public override string Method2() { return null; }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method2").WithArguments("Method2", "Derived2").WithLocation(22, 28),
                // (2,1): hidden CS8019: Unnecessary using directive.
                // using @str = System.String;
                Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using @str = System.String;").WithLocation(2, 1));
        }
 
        [Fact]
        public void TestOverrideNonMethodWithMethod()
        {
            var text = @"
class Base
{
    public int field;
    public int Property { get { return 0; } }
    public interface Interface { }
    public class Class { }
    public struct Struct { }
    public enum Enum { Element }
    public delegate void Delegate();
    public event Delegate Event;
}
 
class Derived : Base
{
    public override int field() { return 1; }
    public override int Property() { return 1; }
    public override int Interface() { return 1; }
    public override int Class() { return 1; }
    public override int Struct() { return 1; }
    public override int Enum() { return 1; }
    public override int Delegate() { return 1; }
    public override int Event() { return 1; }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (16,25): error CS0505: 'Derived.field()': cannot override because 'Base.field' is not a function
                //     public override int field() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "field").WithArguments("Derived.field()", "Base.field"),
                // (17,25): error CS0505: 'Derived.Property()': cannot override because 'Base.Property' is not a function
                //     public override int Property() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Property").WithArguments("Derived.Property()", "Base.Property"),
                // (18,25): error CS0505: 'Derived.Interface()': cannot override because 'Base.Interface' is not a function
                //     public override int Interface() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Interface").WithArguments("Derived.Interface()", "Base.Interface"),
                // (19,25): error CS0505: 'Derived.Class()': cannot override because 'Base.Class' is not a function
                //     public override int Class() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Class").WithArguments("Derived.Class()", "Base.Class"),
                // (20,25): error CS0505: 'Derived.Struct()': cannot override because 'Base.Struct' is not a function
                //     public override int Struct() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Struct").WithArguments("Derived.Struct()", "Base.Struct"),
                // (21,25): error CS0505: 'Derived.Enum()': cannot override because 'Base.Enum' is not a function
                //     public override int Enum() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Enum").WithArguments("Derived.Enum()", "Base.Enum"),
                // (22,25): error CS0505: 'Derived.Delegate()': cannot override because 'Base.Delegate' is not a function
                //     public override int Delegate() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Delegate").WithArguments("Derived.Delegate()", "Base.Delegate"),
                // (23,25): error CS0505: 'Derived.Event()': cannot override because 'Base.Event' is not a function
                //     public override int Event() { return 1; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Event").WithArguments("Derived.Event()", "Base.Event"),
                // (4,16): warning CS0649: Field 'Base.field' is never assigned to, and will always have its default value 0
                //     public int field;
                Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("Base.field", "0"),
                // (11,27): warning CS0067: The event 'Base.Event' is never used
                //     public event Delegate Event;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("Base.Event")
                );
        }
 
        [Fact]
        public void TestOverrideNonPropertyWithProperty()
        {
            var text = @"
class Base
{
    public int field;
    public int Method() { return 0; }
    public interface Interface { }
    public class Class { }
    public struct Struct { }
    public enum Enum { Element }
    public delegate void Delegate();
    public event Delegate Event;
}
 
class Derived : Base
{
    public override int field { get; set; }
    public override int Method { get; set; }
    public override int Interface { get; set; }
    public override int Class { get; set; }
    public override int Struct { get; set; }
    public override int Enum { get; set; }
    public override int Delegate { get; set; }
    public override int Event { get; set; }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (16,25): error CS0544: 'Derived.field': cannot override because 'Base.field' is not a property
                //     public override int field { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "field").WithArguments("Derived.field", "Base.field"),
                // (17,25): error CS0544: 'Derived.Method': cannot override because 'Base.Method()' is not a property
                //     public override int Method { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Method").WithArguments("Derived.Method", "Base.Method()"),
                // (18,25): error CS0544: 'Derived.Interface': cannot override because 'Base.Interface' is not a property
                //     public override int Interface { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Interface").WithArguments("Derived.Interface", "Base.Interface"),
                // (19,25): error CS0544: 'Derived.Class': cannot override because 'Base.Class' is not a property
                //     public override int Class { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Class").WithArguments("Derived.Class", "Base.Class"),
                // (20,25): error CS0544: 'Derived.Struct': cannot override because 'Base.Struct' is not a property
                //     public override int Struct { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Struct").WithArguments("Derived.Struct", "Base.Struct"),
                // (21,25): error CS0544: 'Derived.Enum': cannot override because 'Base.Enum' is not a property
                //     public override int Enum { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Enum").WithArguments("Derived.Enum", "Base.Enum"),
                // (22,25): error CS0544: 'Derived.Delegate': cannot override because 'Base.Delegate' is not a property
                //     public override int Delegate { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Delegate").WithArguments("Derived.Delegate", "Base.Delegate"),
                // (23,25): error CS0544: 'Derived.Event': cannot override because 'Base.Event' is not a property
                //     public override int Event { get; set; }
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Event").WithArguments("Derived.Event", "Base.Event"),
                // (11,27): warning CS0067: The event 'Base.Event' is never used
                //     public event Delegate Event;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("Base.Event"),
                // (4,16): warning CS0649: Field 'Base.field' is never assigned to, and will always have its default value 0
                //     public int field;
                Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("Base.field", "0")
                );
        }
 
        [Fact]
        public void TestOverrideNonEventWithEvent()
        {
            var text = @"
class Base
{
    public int field;
    public int Property { get { return 0; } }
    public int Method() { return 0; }
    public interface Interface { }
    public class Class { }
    public struct Struct { }
    public enum Enum { Element }
    public delegate void Delegate();
}
 
class Derived : Base
{
    public override event System.Action field { add { } remove { } }
    public override event System.Action Property { add { } remove { } }
    public override event System.Action Method { add { } remove { } }
    public override event System.Action Interface { add { } remove { } }
    public override event System.Action Class { add { } remove { } }
    public override event System.Action Struct { add { } remove { } }
    public override event System.Action Enum { add { } remove { } }
    public override event System.Action Delegate { add { } remove { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (16,41): error CS0072: 'Derived.field': cannot override; 'Base.field' is not an event
                //     public override event System.Action field { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "field").WithArguments("Derived.field", "Base.field"),
                // (17,41): error CS0072: 'Derived.Property': cannot override; 'Base.Property' is not an event
                //     public override event System.Action Property { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Property").WithArguments("Derived.Property", "Base.Property"),
                // (18,41): error CS0072: 'Derived.Method': cannot override; 'Base.Method()' is not an event
                //     public override event System.Action Method { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Method").WithArguments("Derived.Method", "Base.Method()"),
                // (19,41): error CS0072: 'Derived.Interface': cannot override; 'Base.Interface' is not an event
                //     public override event System.Action Interface { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Interface").WithArguments("Derived.Interface", "Base.Interface"),
                // (20,41): error CS0072: 'Derived.Class': cannot override; 'Base.Class' is not an event
                //     public override event System.Action Class { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Class").WithArguments("Derived.Class", "Base.Class"),
                // (21,41): error CS0072: 'Derived.Struct': cannot override; 'Base.Struct' is not an event
                //     public override event System.Action Struct { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Struct").WithArguments("Derived.Struct", "Base.Struct"),
                // (22,41): error CS0072: 'Derived.Enum': cannot override; 'Base.Enum' is not an event
                //     public override event System.Action Enum { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Enum").WithArguments("Derived.Enum", "Base.Enum"),
                // (23,41): error CS0072: 'Derived.Delegate': cannot override; 'Base.Delegate' is not an event
                //     public override event System.Action Delegate { add { } remove { } }
                Diagnostic(ErrorCode.ERR_CantOverrideNonEvent, "Delegate").WithArguments("Derived.Delegate", "Base.Delegate"),
                // (4,16): warning CS0649: Field 'Base.field' is never assigned to, and will always have its default value 0
                //     public int field;
                Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("Base.field", "0")
                );
        }
 
        [Fact]
        public void TestOverrideNonVirtualMethod()
        {
            var text = @"
class Base
{
    public virtual void Method1() { }
}
 
class Derived : Base
{
    public new void Method1() { }
    public void Method2() { }
}
 
class Derived2 : Derived
{
    public override void Method1() { }
    public override void Method2() { }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 15, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 16, Column = 26 },
            });
        }
 
        [Fact]
        public void TestOverrideNonVirtualProperty()
        {
            var text = @"
class Base
{
    public virtual long Property1 { get; set; }
}
 
class Derived : Base
{
    public new long Property1 { get; set; }
    public long Property2 { get; set; }
}
 
class Derived2 : Derived
{
    public override long Property1 { get; set; }
    public override long Property2 { get; set; }
}
";
            // CONSIDER: Dev10 reports on both accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 15, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 16, Column = 26 },
            });
        }
 
        [Fact]
        public void TestOverrideNonVirtualIndexer()
        {
            var text = @"
class Base
{
    public virtual long this[int x] { get { return 0; } set { } }
}
 
class Derived : Base
{
    public new long this[int x] { get { return 0; } set { } }
    public long this[string x] { get { return 0; } set { } }
}
 
class Derived2 : Derived
{
    public override long this[int x] { get { return 0; } set { } }
    public override long this[string x] { get { return 0; } set { } }
}
";
            // CONSIDER: Dev10 reports on both accessors, but not on the indexer itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 15, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 16, Column = 26 },
            });
        }
 
        [Fact]
        public void TestOverrideNonVirtualPropertyOmitAccessors()
        {
            var text = @"
class Base
{
    public virtual long Property1 { get; set; }
}
 
class Derived : Base
{
    public new long Property1 { get { return 0; } }
    public long Property2 { get; set; }
}
 
class Derived2 : Derived
{
    public override long Property1 { set { } }
    public override long Property2 { get { return 0;  } }
}
";
            // CONSIDER: Dev10 reports on accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 15, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 16, Column = 26 },
            });
        }
 
        [Fact]
        public void TestOverrideNonVirtualIndexerOmitAccessors()
        {
            var text = @"
class Base
{
    public virtual long this[int x] { get { return 0; } set { } }
}
 
class Derived : Base
{
    public new long this[int x] { get { return 0; } }
    public long this[string x] { get { return 0; } set { } }
}
 
class Derived2 : Derived
{
    public override long this[int x] { set { } }
    public override long this[string x] { get { return 0;  } }
}
";
            // CONSIDER: Dev10 reports on accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 15, Column = 26 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 16, Column = 26 },
            });
        }
 
        [Fact]
        public void TestOverrideNonVirtualEvent()
        {
            var text = @"
class Base
{
    public virtual event System.Action Event1 { add { } remove { } }
}
 
class Derived : Base
{
    public new event System.Action Event1 { add { } remove { } }
    public event System.Action Event2 { add { } remove { } }
}
 
class Derived2 : Derived
{
    public override event System.Action Event1 { add { } remove { } }
    public override event System.Action Event2 { add { } remove { } }
}
";
            // CONSIDER: Dev10 reports on both accessors, but not on the property itself
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 15, Column = 41 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantOverrideNonVirtual, Line = 16, Column = 41 },
            });
        }
 
        [Fact]
        public void TestChangeMethodReturnType()
        {
            var text = @"
using @str = System.String;
 
class Base
{
    public virtual string Method1() { return string.Empty; }
    public virtual string Method2() { return string.Empty; }
    public virtual string Method3() { return string.Empty; }
    public virtual string Method4() { return string.Empty; }
    public virtual string Method5() { return string.Empty; }
}
 
class Derived : Base
{
    public override System.String Method1() { return null; }
    public override str Method2() { return null; }
    public override object Method3() { return null; }
    public override int Method4() { return 0; }
    public override void Method5() { }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeReturnTypeOnOverride, Line = 17, Column = 28 }, //3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeReturnTypeOnOverride, Line = 18, Column = 25 }, //4
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeReturnTypeOnOverride, Line = 19, Column = 26 }, //5
            });
        }
 
        [Fact]
        public void TestChangeMethodRefReturn()
        {
            var text = @"
class Base
{
    public virtual int Method1() { return 0; }
    public virtual ref int Method2(ref int i) { return ref i; }
    public virtual ref int Method3(ref int i) { return ref i; }
}
 
class Derived : Base
{
    int field = 0;
 
    public override ref int Method1() { return ref field; }
    public override int Method2(ref int i) { return i; }
    public override ref int Method3(ref int i) { return ref i; }
}
";
 
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (13,29): error CS8148: 'Derived.Method1()' must match by reference return of overridden member 'Base.Method1()'
                //     public override ref int Method1() { return ref field; }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Method1").WithArguments("Derived.Method1()", "Base.Method1()").WithLocation(13, 29),
                // (14,25): error CS8148: 'Derived.Method2(ref int)' must match by reference return of overridden member 'Base.Method2(ref int)'
                //     public override int Method2(ref int i) { return i; }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Method2").WithArguments("Derived.Method2(ref int)", "Base.Method2(ref int)").WithLocation(14, 25));
        }
 
        [Fact]
        public void TestChangeMethodParameters()
        {
            // Tests:
            // Change parameter count / types of overridden member
            // Omit / toggle ref / out in overridden member
            // Override base member with a signature that only differs by optional parameters
            // Override base member with a signature that only differs by params
            // Change default value of optional argument in overridden member
 
            var text = @"
using @str = System.String;
using @integer = System.Int32;
abstract class Base
{
    public virtual string Method1(int i) { return string.Empty; }
    public virtual string Method2(long j) { return string.Empty; }
    public virtual string Method2(short j) { return string.Empty; }
    public virtual string Method3(System.Exception x, System.ArgumentException y) { return string.Empty; }
    public virtual string Method3(System.ArgumentException x, System.Exception y) { return string.Empty; }
    public abstract string Method4(str[] x, str[][] y);
    public abstract string Method5(System.Collections.Generic.List<str> x, System.Collections.Generic.Dictionary<int, long> y);
    public virtual string Method6(int i, params long[] j) { return string.Empty; }
    public virtual string Method7(int i, short j = 1) { return string.Empty; }
    public virtual string Method8(ref long j) { return string.Empty; }
    public abstract string Method9(out int j);
}
abstract class Derived : Base
{
    public override str Method1(int i, long j = 1) { return string.Empty; }
    public override str Method1(int i, params int[] j) { return string.Empty; }
    public override str Method1(double i) { return string.Empty; }
    public override str Method2(int j) { return string.Empty; }
    public override str Method3(System.Exception x, System.ArgumentException y, System.Exception z) { return string.Empty; }
    public override str Method3(System.ArgumentException x, System.ArgumentException y) { return string.Empty; }
    public override str Method3() { return string.Empty; }
    public override str Method3(System.Exception x) { return string.Empty; }
    public override str Method4(str[] x, str[] y) { return string.Empty; }
    public override str Method4(str[][] y, str[] x) { return string.Empty; }
    public override str Method4(str[] x) { return string.Empty; }
    public override str Method5(System.Collections.Generic.List<int> x, System.Collections.Generic.Dictionary<str, long> y) { return string.Empty; }
    public override str Method5(System.Collections.Generic.Dictionary<int, long> x, System.Collections.Generic.List<string> y) { return string.Empty; }
    public override str Method5(System.Collections.Generic.List<string> y, System.Collections.Generic.Dictionary<integer, long> x) { return string.Empty; } // Not an error
    public override str Method6(int i, long j = 1) { return string.Empty; }
    public override str Method6(int i) { return string.Empty; }
    public override str Method7(int i, params short[] j) { return string.Empty; }
    public override str Method7(int i) { return string.Empty; }
    public override str Method7(int i, short j = 1, short k = 1) { return string.Empty; }
    public override str Method8(out long j) { j = 1; return string.Empty; }
    public override str Method8(long j) { return string.Empty; }
    public override str Method9(ref int j) { return string.Empty; }
    public override str Method9(int j) { return string.Empty; }
    public override str Method1(ref int i) { return string.Empty; }
    public override str Method2(out long j) { j = 2; return string.Empty; }
    public override str Method7(int i, short j = short.MaxValue) { return string.Empty; } // Not an error
}
";
 
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 20, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 21, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 22, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 23, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 24, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 25, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 26, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 27, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 28, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 29, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 30, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 31, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 32, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 34, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 35, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 36, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 37, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 38, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 39, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 41, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 42, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 43, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 44, Column = 25 }
            });
        }
 
        [Fact]
        public void TestChangePropertyType()
        {
            var text = @"
using @str = System.String;
 
class Base
{
    public virtual string Property1 { get; set; }
    public virtual string Property2 { get; set; }
    public virtual string Property3 { get; set; }
    public virtual string Property4 { get; set; }
}
 
class Derived : Base
{
    public override System.String Property1 { get; set; }
    public override str Property2 { get; set; }
    public override object Property3 { get; set; }
    public override int Property4 { get; set; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 16, Column = 28 }, //3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 17, Column = 25 }, //4
            });
        }
 
        [Fact]
        public void TestChangePropertyRefReturn()
        {
            var text = @"
class Base
{
    int field = 0;
 
    public virtual int Proprty1 { get { return 0; } }
    public virtual ref int Property2 { get { return ref @field; } }
    public virtual ref int Property3 { get { return ref @field; } }
}
 
class Derived : Base
{
    int field = 0;
 
    public override ref int Proprty1 { get { return ref @field; } }
    public override int Property2 { get { return 0; } }
    public override ref int Property3 { get { return ref @field; } }
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (15,29): error CS8148: 'Derived.Proprty1' must match by reference return of overridden member 'Base.Proprty1'
                //     public override ref int Proprty1 { get { return ref @field; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Proprty1").WithArguments("Derived.Proprty1", "Base.Proprty1").WithLocation(15, 29),
                // (16,25): error CS8148: 'Derived.Property2' must match by reference return of overridden member 'Base.Property2'
                //     public override int Property2 { get { return 0; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Property2").WithArguments("Derived.Property2", "Base.Property2").WithLocation(16, 25));
        }
 
        [Fact]
        public void TestChangeIndexerType()
        {
            var text = @"
using @str = System.String;
 
class Base
{
    public virtual string this[int x, int y] { get { return null; } set { } }
    public virtual string this[int x, string y] { get { return null; } set { } }
    public virtual string this[string x, int y] { get { return null; } set { } }
    public virtual string this[string x, string y] { get { return null; } set { } }
}
 
class Derived : Base
{
    public override System.String this[int x, int y] { get { return null; } set { } }
    public override str this[int x, string y] { get { return null; } set { } }
    public override object this[string x, int y] { get { return null; } set { } }
    public override int this[string x, string y] { get { return 0; } set { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 16, Column = 28 }, //3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 17, Column = 25 }, //4
            });
        }
 
        [Fact]
        public void TestChangeIndexerRefReturn()
        {
            var text = @"
class Base
{
    int field = 0;
 
    public virtual int this[int x, int y] { get { return field; } }
    public virtual ref int this[int x, string y] { get { return ref field; } }
    public virtual ref int this[string x, int y] { get { return ref field; } }
}
 
class Derived : Base
{
    int field = 0;
 
    public override ref int this[int x, int y] { get { return ref field; } }
    public override int this[int x, string y] { get { return field; } }
    public override ref int this[string x, int y] { get { return ref field; } }
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (15,29): error CS8148: 'Derived.this[int, int]' must match by reference return of overridden member 'Base.this[int, int]'
                //     public override ref int this[int x, int y] { get { return ref field; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "this").WithArguments("Derived.this[int, int]", "Base.this[int, int]").WithLocation(15, 29),
                // (16,25): error CS8148: 'Derived.this[int, string]' must match by reference return of overridden member 'Base.this[int, string]'
                //     public override int this[int x, string y] { get { return field; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "this").WithArguments("Derived.this[int, string]", "Base.this[int, string]").WithLocation(16, 25));
        }
 
        /// <summary>
        /// Based on Method1 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters1()
        {
            var text = @"
abstract class Base
{
    public virtual string this[int i] { set { } }
}
abstract class Derived : Base
{
    public override string this[int i, long j = 1] { set { } }
    public override string this[int i, params int[] j] { set { } }
    public override string this[double i] { set { } }
    public override string this[ref int i] { set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (11,33): error CS0631: ref and out are not valid in this context
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref"),
                // (8,28): error CS0115: 'Derived.this[int, long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int, long]"),
                // (9,28): error CS0115: 'Derived.this[int, params int[]]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int, params int[]]"),
                // (10,28): error CS0115: 'Derived.this[double]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[double]"),
                // (11,28): error CS0115: 'Derived.this[ref int]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[ref int]"));
        }
 
        /// <summary>
        /// Based on Method2 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters2()
        {
            var text = @"
abstract class Base
{
    public virtual string this[long j] { set { } }
    public virtual string this[short j] { set { } }
}
abstract class Derived : Base
{
    public override string this[int j] { set { } }
    public override string this[out long j] { set { j = 2; } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (10,33): error CS0631: ref and out are not valid in this context
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "out"),
                // (9,28): error CS0115: 'Derived.this[int]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int]"),
                // (10,28): error CS0115: 'Derived.this[out long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[out long]"));
        }
 
        /// <summary>
        /// Based on Method3 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters3()
        {
            var text = @"
abstract class Base
{
    public virtual string this[System.Exception x, System.ArgumentException y] { set { } }
    public virtual string this[System.ArgumentException x, System.Exception y] { set { } }
}
abstract class Derived : Base
{
    public override string this[System.Exception x, System.ArgumentException y, System.Exception z] { set { } }
    public override string this[System.ArgumentException x, System.ArgumentException y] { set { } }
    public override string this[] { set { } }
    public override string this[System.Exception x] { set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (11,33): error CS1551: Indexers must have at least one parameter
                Diagnostic(ErrorCode.ERR_IndexerNeedsParam, "]"),
                // (9,28): error CS0115: 'Derived.this[System.Exception, System.ArgumentException, System.Exception]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[System.Exception, System.ArgumentException, System.Exception]"),
                // (10,28): error CS0115: 'Derived.this[System.ArgumentException, System.ArgumentException]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[System.ArgumentException, System.ArgumentException]"),
                // (11,28): error CS0115: 'Derived.this': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this"),
                // (12,28): error CS0115: 'Derived.this[System.Exception]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[System.Exception]"));
        }
 
        /// <summary>
        /// Based on Method4 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters4()
        {
            var text = @"
abstract class Base
{
    public abstract string this[string[] x, string[][] y] { set; }
}
abstract class Derived : Base
{
    public override string this[string[] x, string[] y] { set { } }
    public override string this[string[][] y, string[] x] { set { } }
    public override string this[string[] x] { set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (8,28): error CS0115: 'Derived.this[string[], string[]]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[string[], string[]]"),
                // (9,28): error CS0115: 'Derived.this[string[][], string[]]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[string[][], string[]]"),
                // (10,28): error CS0115: 'Derived.this[string[]]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[string[]]"));
        }
 
        /// <summary>
        /// Based on Method5 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters5()
        {
            var text = @"
abstract class Base
{
    public abstract string this[System.Collections.Generic.List<string> x, System.Collections.Generic.Dictionary<int, long> y] { set; }
}
abstract class Derived : Base
{
    public override string this[System.Collections.Generic.List<int> x, System.Collections.Generic.Dictionary<string, long> y] { set { } }
    public override string this[System.Collections.Generic.Dictionary<int, long> x, System.Collections.Generic.List<string> y] { set { } }
    public override string this[System.Collections.Generic.List<string> y, System.Collections.Generic.Dictionary<int, long> x] { set { } } // Not an error
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (8,28): error CS0115: 'Derived.this[System.Collections.Generic.List<int>, System.Collections.Generic.Dictionary<string, long>]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[System.Collections.Generic.List<int>, System.Collections.Generic.Dictionary<string, long>]"),
                // (9,28): error CS0115: 'Derived.this[System.Collections.Generic.Dictionary<int, long>, System.Collections.Generic.List<string>]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[System.Collections.Generic.Dictionary<int, long>, System.Collections.Generic.List<string>]"));
        }
 
        /// <summary>
        /// Based on Method6 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters6()
        {
            var text = @"
abstract class Base
{
    public virtual string this[int i, params long[] j] { set { } }
}
abstract class Derived : Base
{
    public override string this[int i, long j = 1] { set { } }
    public override string this[int i] { set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (8,28): error CS0115: 'Derived.this[int, long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int, long]"),
                // (9,28): error CS0115: 'Derived.this[int]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int]"));
        }
 
        /// <summary>
        /// Based on Method7 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters7()
        {
            var text = @"
abstract class Base
{
    public virtual string this[int i, short j = 1] { set { } }
}
abstract class Derived : Base
{
    public override string this[int i, params short[] j] { set { } }
    public override string this[int i] { set { } }
    public override string this[int i, short j = 1, short k = 1] { set { } }
    public override string this[int i, short j = short.MaxValue] { set { } } // Not an error
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (8,28): error CS0115: 'Derived.this[int, params short[]]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int, params short[]]"),
                // (9,28): error CS0115: 'Derived.this[int]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int]"),
                // (10,28): error CS0115: 'Derived.this[int, short, short]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int, short, short]"));
        }
 
        /// <summary>
        /// Based on Method8 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters8()
        {
            var text = @"
abstract class Base
{
    public virtual string this[ref long j] { set { } }
}
abstract class Derived : Base
{
    public override string this[out long j] { set { j = 1; } }
    public override string this[long j] { set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (4,32): error CS0631: ref and out are not valid in this context
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref"),
                // (8,33): error CS0631: ref and out are not valid in this context
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "out"),
                // (8,28): error CS0115: 'Derived.this[out long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[out long]"),
                // (9,28): error CS0115: 'Derived.this[long]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[long]"));
        }
 
        /// <summary>
        /// Based on Method9 in TestChangeMethodParameters.
        /// </summary>
        [Fact]
        public void TestChangeIndexerParameters9()
        {
            var text = @"
abstract class Base
{
    public abstract string this[out int j] { set; }
}
abstract class Derived : Base
{
    public override string this[ref int j] { set { } }
    public override string this[int j] { set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (4,33): error CS0631: ref and out are not valid in this context
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "out"),
                // (8,33): error CS0631: ref and out are not valid in this context
                Diagnostic(ErrorCode.ERR_IllegalRefParam, "ref"),
                // (8,28): error CS0115: 'Derived.this[ref int]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[ref int]"),
                // (9,28): error CS0115: 'Derived.this[int]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[int]"));
        }
 
        [Fact]
        public void TestChangeEventType()
        {
            var text = @"
using @str = System.String;
 
class Base
{
    public virtual event System.Action<string> Event1 { add { } remove { } }
    public virtual event System.Action<string> Event2 { add { } remove { } }
    public virtual event System.Action<string> Event3 { add { } remove { } }
    public virtual event System.Action<string> Event4 { add { } remove { } }
}
 
class Derived : Base
{
    public override event System.Action<System.String> Event1 { add { } remove { } }
    public override event System.Action<str> Event2 { add { } remove { } }
    public override event System.Action<object> Event3 { add { } remove { } }
    public override event System.Action<int> Event4 { add { } remove { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 16, Column = 49 }, //3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 17, Column = 46 }, //4
            });
        }
 
        [Fact]
        public void TestChangeGenericMethodReturnType()
        {
            var text = @"
class Base<T>
{
    public virtual T Method1(T t) { return t; }
    public virtual U Method2<U>(U u) { return u; }
}
 
class Derived : Base<string>
{
    public override object Method1(string t) { return null; }
    public override object Method2<U>(U u) { return null; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeReturnTypeOnOverride, Line = 10, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeReturnTypeOnOverride, Line = 11, Column = 28 },
            });
        }
 
        [Fact]
        public void TestChangeGenericMethodParameters()
        {
            // Tests:
            // Change number / order / types of method parameters in overridden method
 
            var text = @"
using System.Collections.Generic;
abstract class Base<T, U>
{
    protected virtual void Method(T x) { }
    protected virtual void Method(List<T> x) { }
    protected virtual void Method<V>(V x, T y) { }
    protected virtual void Method<V>(List<V> x, List<U> y) { }
}
 
class Derived<A, B> : Base<A, B>
{
    protected override void Method(B x) { }
    protected override void Method(List<B> x) { }
    protected override void Method<V>(A x, V y) { }
    protected override void Method<V>(List<V> x, List<A> y) { }
    protected override void Method<V, U>(List<V> x, List<U> y) { }
}
 
class Derived : Base<long, int>
{
    protected override void Method(int x) { }
    protected override void Method(List<int> x) { }
    protected override void Method<V>(int x, long y) { }
    protected override void Method<V>(List<V> x, List<long> y) { }
    protected override void Method<V>(List<long> x, List<int> y) { }
}
 
class Derived<A, B, C> : Base<A, B>
{
    protected override void Method() { }
    protected override void Method(List<A> x, List<B> y) { }
    protected override void Method<V>(V x, A y, C z) { }
    protected override void Method<V>(List<V> x, ref List<B> y) { }
    protected override void Method<V>(List<V> x, List<B> y = null) { } // Not an error
    protected override void Method<V>(List<V> x, List<B>[] y) { }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B>.Method(B)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B>.Method(System.Collections.Generic.List<B>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B>.Method<V>(A, V)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B>.Method<V>(System.Collections.Generic.List<V>, System.Collections.Generic.List<A>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B>.Method<V, U>(System.Collections.Generic.List<V>, System.Collections.Generic.List<U>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method(int)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method(System.Collections.Generic.List<int>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V>(int, long)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V>(System.Collections.Generic.List<V>, System.Collections.Generic.List<long>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V>(System.Collections.Generic.List<long>, System.Collections.Generic.List<int>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B, C>.Method()"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B, C>.Method(System.Collections.Generic.List<A>, System.Collections.Generic.List<B>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B, C>.Method<V>(V, A, C)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B, C>.Method<V>(System.Collections.Generic.List<V>, ref System.Collections.Generic.List<B>)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived<A, B, C>.Method<V>(System.Collections.Generic.List<V>, System.Collections.Generic.List<B>[])"));
        }
 
        [Fact]
        public void TestChangeGenericMethodTypeParameters()
        {
            // Tests:
            // Change number / order of generic method type parameters in overridden method
 
            var text = @"
using System.Collections.Generic;
class Base<T, U>
{
    protected virtual void Method<V>() { }
    protected virtual void Method<V>(V x, T y) { }
    protected virtual void Method<V, W>(T x, U y) { }
    protected virtual void Method<V, W>(List<V> x, List<W> y) { }
}
class Derived : Base<int, int>
{
    protected override void Method() { }
    protected override void Method<V, U>() { }
    protected override void Method<V>(int x, V y) { }
    protected override void Method<V, U>(V x, int y) { }
    protected override void Method(int x, int y) { }
    protected override void Method<V>(int x, int y) { }
    protected override void Method<V, U, W>(int x, int y) { }
    protected override void Method<V, W>(List<W> x, List<V> y) { }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method()"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V, U>()"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V>(int, V)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V, U>(V, int)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method(int, int)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V>(int, int)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V, U, W>(int, int)"),
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Derived.Method<V, W>(System.Collections.Generic.List<W>, System.Collections.Generic.List<V>)"));
        }
 
        [Fact]
        public void TestChangeGenericPropertyType()
        {
            var text = @"
class Base<T>
{
    public virtual T Property1 { get; set; }
    public virtual T Property2 { get; set; }
}
 
class Derived : Base<string>
{
    public override string Property1 { get; set; }
    public override object Property2 { get; set; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 11, Column = 28 }, //2
            });
        }
 
        [Fact]
        public void TestChangeGenericIndexerType()
        {
            var text = @"
class Base<T>
{
    public virtual T this[int x] { get { return default(T); } set { } }
    public virtual T this[string x] { get { return default(T); } set { } }
}
 
class Derived : Base<string>
{
    public override string this[int x] { get { return null; } set { } }
    public override object this[string x] { get { return null; } set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (11,28): error CS1715: 'Derived.this[string]': type must be 'string' to match overridden member 'Base<string>.this[string]'
                Diagnostic(ErrorCode.ERR_CantChangeTypeOnOverride, "this").WithArguments("Derived.this[string]", "Base<string>.this[string]", "string"));
        }
 
        [Fact]
        public void TestChangeGenericIndexerParameters()
        {
            var text = @"
class Base<T>
{
    public virtual int this[string x, T y] { get { return 0; } set { } }
    public virtual int this[object x, T y] { get { return 0; } set { } }
}
 
class Derived : Base<string>
{
    public override int this[string x, string y] { get { return 0; } set { } }
    public override int this[object x, object y] { get { return 0; } set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (11,25): error CS0115: 'Derived.this[object, object]': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "this").WithArguments("Derived.this[object, object]"));
        }
 
        [Fact]
        public void TestChangeGenericEventType()
        {
            var text = @"
class Base<T>
{
    public virtual event System.Action<T> Event1 { add { } remove { } }
    public virtual event System.Action<T> Event2 { add { } remove { } }
}
 
class Derived : Base<string>
{
    public override event System.Action<string> Event1 { add { } remove { } }
    public override event System.Action<object> Event2 { add { } remove { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeTypeOnOverride, Line = 11, Column = 49 }, //2
            });
        }
 
        [Fact]
        public void TestDoNotChangeGenericMethodReturnType()
        {
            var text = @"
interface IGoo<A>
{
}
 
class Base
{
    public virtual T Method1<T>(T t) { return t; }
    public virtual IGoo<U> Method2<U>(U u) { return null; }
}
 
class Derived : Base
{
    public override M Method1<M>(M t) { return t; }
    public override IGoo<X> Method2<X>(X u) { return null; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
            });
        }
 
        [Fact]
        public void TestClassTypeParameterReturnType()
        {
            var text = @"
class Base<T>
{
    public virtual T Property { get; set; }
    public virtual T Method(T t) { return t; }
}
 
class Derived<S> : Base<S>
{
    public override S Property { get; set; }
    public override S Method(S s) { return s; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
            });
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractMethod()
        {
            var text = @"
abstract class Base
{
    public abstract object Method1();
    public abstract object Method2();
    public abstract object Method3();
    public abstract object Method4(int i);
    public abstract ref object Method5(ref object o);
    public abstract object Method6(ref object o);
}
 
class Derived : Base
{
    //missed Method1 entirely
    public object Method2() { return null; } //missed override keyword
    public int Method3() { return 0; } //wrong return type
    public object Method4(long l) { return 0; } //wrong signature
    public override object Method5(ref object o) { return null; } //wrong by-value return
    public override ref object Method6(ref object o) { return ref o; } //wrong by-ref return
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (16,16): warning CS0114: 'Derived.Method3()' hides inherited member 'Base.Method3()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public int Method3() { return 0; } //wrong return type
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Method3").WithArguments("Derived.Method3()", "Base.Method3()").WithLocation(16, 16),
                // (18,28): error CS8148: 'Derived.Method5(ref object)' must match by reference return of overridden member 'Base.Method5(ref object)'
                //     public override object Method5(ref object o) { return null; } //wrong by-value return
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Method5").WithArguments("Derived.Method5(ref object)", "Base.Method5(ref object)").WithLocation(18, 28),
                // (19,32): error CS8148: 'Derived.Method6(ref object)' must match by reference return of overridden member 'Base.Method6(ref object)'
                //     public override ref object Method6(ref object o) { return ref o; } //wrong by-ref return
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Method6").WithArguments("Derived.Method6(ref object)", "Base.Method6(ref object)").WithLocation(19, 32),
                // (15,19): warning CS0114: 'Derived.Method2()' hides inherited member 'Base.Method2()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public object Method2() { return null; } //missed override keyword
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Method2").WithArguments("Derived.Method2()", "Base.Method2()").WithLocation(15, 19),
                // (12,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Method2()'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Method2()").WithLocation(12, 7),
                // (12,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Method4(int)'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Method4(int)").WithLocation(12, 7),
                // (12,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Method3()'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Method3()").WithLocation(12, 7),
                // (12,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Method1()'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Method1()").WithLocation(12, 7));
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractProperty()
        {
            var text = @"
abstract class Base
{
    public abstract object Property1 { get; set; }
    public abstract object Property2 { get; set; }
    public abstract object Property3 { get; set; }
 
    public abstract object Property4 { get; set; }
    public abstract object Property5 { get; set; }
    public abstract object Property6 { get; }
    public abstract object Property7 { get; }
    public abstract object Property8 { set; }
    public abstract object Property9 { set; }
 
    public abstract object Property10 { get; }
    public abstract ref object Property11 { get; }
}
 
class Derived : Base
{
    //missed Property1 entirely
    public object Property2 { get; set; } //missed override keyword
    public override int Property3 { get; set; } //wrong type
 
    //wrong accessors
    public override object Property4 { get { return null; } }
    public override object Property5 { set { } }
    public override object Property6 { get; set; }
    public override object Property7 { set { } }
    public override object Property8 { get; set; }
    public override object Property9 { get { return null; } }
 
    //wrong by-{value,ref} return
    object o = null;
    public override ref object Property10 { get { return ref o; } }
    public override object Property11 { get { return null; } }
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (23,25): error CS1715: 'Derived.Property3': type must be 'object' to match overridden member 'Base.Property3'
                //     public override int Property3 { get; set; } //wrong type
                Diagnostic(ErrorCode.ERR_CantChangeTypeOnOverride, "Property3").WithArguments("Derived.Property3", "Base.Property3", "object").WithLocation(23, 25),
                // (28,45): error CS0546: 'Derived.Property6.set': cannot override because 'Base.Property6' does not have an overridable set accessor
                //     public override object Property6 { get; set; }
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "set").WithArguments("Derived.Property6.set", "Base.Property6").WithLocation(28, 45),
                // (29,40): error CS0546: 'Derived.Property7.set': cannot override because 'Base.Property7' does not have an overridable set accessor
                //     public override object Property7 { set { } }
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "set").WithArguments("Derived.Property7.set", "Base.Property7").WithLocation(29, 40),
                // (30,40): error CS0545: 'Derived.Property8.get': cannot override because 'Base.Property8' does not have an overridable get accessor
                //     public override object Property8 { get; set; }
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived.Property8.get", "Base.Property8").WithLocation(30, 40),
                // (31,40): error CS0545: 'Derived.Property9.get': cannot override because 'Base.Property9' does not have an overridable get accessor
                //     public override object Property9 { get { return null; } }
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived.Property9.get", "Base.Property9").WithLocation(31, 40),
                // (35,32): error CS8148: 'Derived.Property10' must match by reference return of overridden member 'Base.Property10'
                //     public override ref object Property10 { get { return ref o; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Property10").WithArguments("Derived.Property10", "Base.Property10").WithLocation(35, 32),
                // (36,28): error CS8148: 'Derived.Property11' must match by reference return of overridden member 'Base.Property11'
                //     public override object Property11 { get { return null; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "Property11").WithArguments("Derived.Property11", "Base.Property11").WithLocation(36, 28),
                // (22,19): warning CS0114: 'Derived.Property2' hides inherited member 'Base.Property2'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public object Property2 { get; set; } //missed override keyword
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Property2").WithArguments("Derived.Property2", "Base.Property2").WithLocation(22, 19),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property2.get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property2.get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property1.get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property1.get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property5.get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property5.get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property9.set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property9.set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property1.set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property1.set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property7.get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property7.get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property3.set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property3.set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property2.set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property2.set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Property4.set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Property4.set").WithLocation(19, 7));
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractIndexer()
        {
            var text = @"
abstract class Base
{
    public abstract object this[int w, int x, int y , int z] { get; set; }
    public abstract object this[int w, int x, int y , string z] { get; set; }
    public abstract object this[int w, int x, string y , int z] { get; set; }
 
    public abstract object this[int w, int x, string y , string z] { get; set; }
    public abstract object this[int w, string x, int y , int z] { get; set; }
    public abstract object this[int w, string x, int y , string z] { get; }
    public abstract object this[int w, string x, string y , int z] { get; }
    public abstract object this[int w, string x, string y , string z] { set; }
    public abstract object this[string w, int x, int y , int z] { set; }
 
    public abstract object this[string w, int x, int y, string z] { get; }
    public abstract ref object this[string w, int x, string y, int z] { get; }
}
 
class Derived : Base
{
    //missed first indexer entirely
    public object this[int w, int x, int y , string z] { get { return 0; } set { } } //missed override keyword
    public override int this[int w, int x, string y , int z] { get { return 0; } set { } } //wrong type
 
    //wrong accessors
    public override object this[int w, int x, string y , string z] { get { return null; } }
    public override object this[int w, string x, int y , int z] { set { } }
    public override object this[int w, string x, int y , string z] { get { return 0; } set { } }
    public override object this[int w, string x, string y , int z] { set { } }
    public override object this[int w, string x, string y , string z] { get { return 0; } set { } }
    public override object this[string w, int x, int y , int z] { get { return null; } }
 
    //wrong by-{value,ref} return
    object o = null;
    public override ref object this[string w, int x, int y, string z] { get { return ref o; } }
    public override object this[string w, int x, string y, int z] { get; }
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (36,69): error CS0501: 'Derived.this[string, int, string, int].get' must declare a body because it is not marked abstract, extern, or partial
                //     public override object this[string w, int x, string y, int z] { get; }
                Diagnostic(ErrorCode.ERR_ConcreteMissingBody, "get").WithArguments("Derived.this[string, int, string, int].get").WithLocation(36, 69),
                // (23,25): error CS1715: 'Derived.this[int, int, string, int]': type must be 'object' to match overridden member 'Base.this[int, int, string, int]'
                //     public override int this[int w, int x, string y , int z] { get { return 0; } set { } } //wrong type
                Diagnostic(ErrorCode.ERR_CantChangeTypeOnOverride, "this").WithArguments("Derived.this[int, int, string, int]", "Base.this[int, int, string, int]", "object").WithLocation(23, 25),
                // (28,88): error CS0546: 'Derived.this[int, string, int, string].set': cannot override because 'Base.this[int, string, int, string]' does not have an overridable set accessor
                //     public override object this[int w, string x, int y , string z] { get { return 0; } set { } }
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "set").WithArguments("Derived.this[int, string, int, string].set", "Base.this[int, string, int, string]").WithLocation(28, 88),
                // (29,70): error CS0546: 'Derived.this[int, string, string, int].set': cannot override because 'Base.this[int, string, string, int]' does not have an overridable set accessor
                //     public override object this[int w, string x, string y , int z] { set { } }
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "set").WithArguments("Derived.this[int, string, string, int].set", "Base.this[int, string, string, int]").WithLocation(29, 70),
                // (30,73): error CS0545: 'Derived.this[int, string, string, string].get': cannot override because 'Base.this[int, string, string, string]' does not have an overridable get accessor
                //     public override object this[int w, string x, string y , string z] { get { return 0; } set { } }
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived.this[int, string, string, string].get", "Base.this[int, string, string, string]").WithLocation(30, 73),
                // (31,67): error CS0545: 'Derived.this[string, int, int, int].get': cannot override because 'Base.this[string, int, int, int]' does not have an overridable get accessor
                //     public override object this[string w, int x, int y , int z] { get { return null; } }
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived.this[string, int, int, int].get", "Base.this[string, int, int, int]").WithLocation(31, 67),
                // (35,32): error CS8148: 'Derived.this[string, int, int, string]' must match by reference return of overridden member 'Base.this[string, int, int, string]'
                //     public override ref object this[string w, int x, int y, string z] { get { return ref o; } }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "this").WithArguments("Derived.this[string, int, int, string]", "Base.this[string, int, int, string]").WithLocation(35, 32),
                // (36,28): error CS8148: 'Derived.this[string, int, string, int]' must match by reference return of overridden member 'Base.this[string, int, string, int]'
                //     public override object this[string w, int x, string y, int z] { get; }
                Diagnostic(ErrorCode.ERR_CantChangeRefReturnOnOverride, "this").WithArguments("Derived.this[string, int, string, int]", "Base.this[string, int, string, int]").WithLocation(36, 28),
                // (22,19): warning CS0114: 'Derived.this[int, int, int, string]' hides inherited member 'Base.this[int, int, int, string]'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public object this[int w, int x, int y , string z] { get { return 0; } set { } } //missed override keyword
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "this").WithArguments("Derived.this[int, int, int, string]", "Base.this[int, int, int, string]").WithLocation(22, 19),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, int, string, int].set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, int, string, int].set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, int, string, string].set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, int, string, string].set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, int, int, int].set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, int, int, int].set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, int, int, int].get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, int, int, int].get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, string, int, int].get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, string, int, int].get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, int, int, string].set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, int, int, string].set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, int, int, string].get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, int, int, string].get").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[string, int, int, int].set'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[string, int, int, int].set").WithLocation(19, 7),
                // (19,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.this[int, string, string, int].get'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.this[int, string, string, int].get").WithLocation(19, 7));
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractEvent()
        {
            var text = @"
abstract class Base
{
    public abstract event System.Action Event1;
    public abstract event System.Action Event2;
    public abstract event System.Action Event3;
}
 
class Derived : Base
{
    //missed Method1 Event1
    public event System.Action Event2 { add { } remove { } } //missed override keyword
    public override event System.Action<int> Event3 { add { } remove { } } //wrong type
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (12,32): warning CS0114: 'Derived.Event2' hides inherited member 'Base.Event2'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public event System.Action Event2 { add { } remove { } } //missed override keyword
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event2").WithArguments("Derived.Event2", "Base.Event2"),
                // (13,46): error CS1715: 'Derived.Event3': type must be 'System.Action' to match overridden member 'Base.Event3'
                //     public override event System.Action<int> Event3 { add { } remove { } } //wrong type
                Diagnostic(ErrorCode.ERR_CantChangeTypeOnOverride, "Event3").WithArguments("Derived.Event3", "Base.Event3", "System.Action"),
                // (9,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event2.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event2.add"),
                // (9,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event2.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event2.remove"),
                // (9,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event1.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event1.add"),
                // (9,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event1.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event1.remove"),
                // (9,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event3.add'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event3.add"),
                // (9,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base.Event3.remove'
                // class Derived : Base
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base.Event3.remove"));
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractMethodFromGrandparent()
        {
            var text = @"
abstract class Abstract1
{
    public abstract void Method1();
    public abstract void Method2();
    public abstract void Method3();
}
 
abstract class Abstract2 : Abstract1
{
    public override void Method1() { }
 
    public abstract void Method4();
    public abstract void Method5();
}
 
class Concrete : Abstract2
{
    public override void Method3() { }
    public override void Method5() { }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //Method2
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //Method4
            });
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractPropertyFromGrandparent()
        {
            var text = @"
abstract class Abstract1
{
    public abstract long Property1 { get; set; }
    public abstract long Property2 { get; set; }
    public abstract long Property3 { get; set; }
}
 
abstract class Abstract2 : Abstract1
{
    public override long Property1 { get; set; }
 
    public abstract long Property4 { get; set; }
    public abstract long Property5 { get; set; }
}
 
class Concrete : Abstract2
{
    public override long Property3 { get; set; }
    public override long Property5 { get; set; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //2.get
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //2.set
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //4.get
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //4.set
            });
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractIndexerFromGrandparent()
        {
            var text = @"
abstract class Abstract1
{
    public abstract long this[int x, int y, string z] { get; set; }
    public abstract long this[int x, string y, int z] { get; set; }
    public abstract long this[int x, string y, string z] { get; set; }
}
 
abstract class Abstract2 : Abstract1
{
    public override long this[int x, int y, string z] { get { return 0; } set { } }
 
    public abstract long this[string x, int y, int z] { get; set; }
    public abstract long this[string x, int y, string z] { get; set; }
}
 
class Concrete : Abstract2
{
    public override long this[int x, string y, string z] { get { return 0; } set { } }
    public override long this[string x, int y, string z] { get { return 0; } set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (17,7): error CS0534: 'Concrete' does not implement inherited abstract member 'Abstract1.this[int, string, int].get'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Concrete").WithArguments("Concrete", "Abstract1.this[int, string, int].get"),
                // (17,7): error CS0534: 'Concrete' does not implement inherited abstract member 'Abstract1.this[int, string, int].set'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Concrete").WithArguments("Concrete", "Abstract1.this[int, string, int].set"),
                // (17,7): error CS0534: 'Concrete' does not implement inherited abstract member 'Abstract2.this[string, int, int].get'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Concrete").WithArguments("Concrete", "Abstract2.this[string, int, int].get"),
                // (17,7): error CS0534: 'Concrete' does not implement inherited abstract member 'Abstract2.this[string, int, int].set'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Concrete").WithArguments("Concrete", "Abstract2.this[string, int, int].set"));
        }
 
        [Fact]
        public void TestNoImplementationOfAbstractEventFromGrandparent()
        {
            var text = @"
abstract class Abstract1
{
    public abstract event System.Action Event1;
    public abstract event System.Action Event2;
    public abstract event System.Action Event3;
}
 
abstract class Abstract2 : Abstract1
{
    public override event System.Action Event1 { add { } remove { } }
 
    public abstract event System.Action Event4;
    public abstract event System.Action Event5;
}
 
class Concrete : Abstract2
{
    public override event System.Action Event3 { add { } remove { } }
    public override event System.Action Event5 { add { } remove { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //2.add
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //2.remove
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //4.add
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedAbstractMethod, Line = 17, Column = 7 }, //4.remove
            });
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceMethod_01()
        {
            var text = @"
interface Interface
{
    object Method1();
    object Method2(int i);
    ref object Method3(ref object o);
    object Method4(ref object o);
}
 
class Class : Interface
{
    //missed Method1 entirely
    public object Method2(long l) { return 0; } //wrong signature
    public object Method3(ref object o) { return null; } //wrong by-value return
    public ref object Method4(ref object o) { return ref o; } //wrong by-ref return
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (10,15): error CS8152: 'Class' does not implement interface member 'Interface.Method4(ref object)'. 'Class.Method4(ref object)' cannot implement 'Interface.Method4(ref object)' because it does not have matching return by reference.
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "Interface").WithArguments("Class", "Interface.Method4(ref object)", "Class.Method4(ref object)").WithLocation(10, 15),
                // (10,15): error CS0535: 'Class' does not implement interface member 'Interface.Method2(int)'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Method2(int)").WithLocation(10, 15),
                // (10,15): error CS8152: 'Class' does not implement interface member 'Interface.Method3(ref object)'. 'Class.Method3(ref object)' cannot implement 'Interface.Method3(ref object)' because it does not have matching return by reference.
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "Interface").WithArguments("Class", "Interface.Method3(ref object)", "Class.Method3(ref object)").WithLocation(10, 15),
                // (10,15): error CS0535: 'Class' does not implement interface member 'Interface.Method1()'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Method1()").WithLocation(10, 15));
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceMethod_02()
        {
            var source1 =
@"
public class C1 {}
";
 
            var comp11 = CreateCompilation(new AssemblyIdentity("lib1", new Version("4.2.1.0"), publicKeyOrToken: SigningTestHelpers.PublicKey, hasPublicKey: true),
                                           new[] { source1 }, TargetFrameworkUtil.GetReferences(TargetFramework.Standard, null).ToArray(), TestOptions.DebugDll.WithPublicSign(true));
            comp11.VerifyDiagnostics();
            var comp12 = CreateCompilation(new AssemblyIdentity("lib1", new Version("4.1.0.0"), publicKeyOrToken: SigningTestHelpers.PublicKey, hasPublicKey: true),
                                           new[] { source1 }, TargetFrameworkUtil.GetReferences(TargetFramework.Standard, null).ToArray(), TestOptions.DebugDll.WithPublicSign(true));
            comp12.VerifyDiagnostics();
 
            var source2 =
@"
public class C2 : C1 {}
";
 
            var comp2 = CreateCompilation(new[] { source2 }, references: new[] { comp12.EmitToImageReference() }, assemblyName: "lib2");
            comp2.VerifyDiagnostics();
 
            var source3 =
@"
interface I1
{
    void Method1();
}
 
#pragma warning disable CS1701
class C3 : C2,
#pragma warning restore CS1701
               I1
{
}
";
            var comp3 = CreateCompilation(new[] { source3 }, references: new[] { comp11.EmitToImageReference(), comp2.EmitToImageReference() }, assemblyName: "lib3");
 
            // The unification warning shouldn't suppress the CS0535 error.
            comp3.VerifyDiagnostics(
                // warning CS1701: Assuming assembly reference 'lib1, Version=4.1.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' used by 'lib2' matches identity 'lib1, Version=4.2.1.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' of 'lib1', you may need to supply runtime policy
                Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("lib1, Version=4.1.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "lib2", "lib1, Version=4.2.1.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "lib1").WithLocation(1, 1),
                // warning CS1701: Assuming assembly reference 'lib1, Version=4.1.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' used by 'lib2' matches identity 'lib1, Version=4.2.1.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2' of 'lib1', you may need to supply runtime policy
                Diagnostic(ErrorCode.WRN_UnifyReferenceMajMin).WithArguments("lib1, Version=4.1.0.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "lib2", "lib1, Version=4.2.1.0, Culture=neutral, PublicKeyToken=ce65828c82a341f2", "lib1").WithLocation(1, 1),
                // (10,16): error CS0535: 'C3' does not implement interface member 'I1.Method1()'
                //                I1
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("C3", "I1.Method1()").WithLocation(10, 16)
                );
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceProperty()
        {
            var text = @"
interface Interface
{
    object Property1 { get; set; }
 
    object Property2 { get; set; }
    object Property3 { get; set; }
    object Property4 { get; }
    object Property5 { get; }
    object Property6 { set; }
    object Property7 { set; }
 
    ref object Property8 { get; }
    object Property9 { get; }
}
 
class Class : Interface
{
    //missed Property1 entirely
 
    //wrong accessors
    public object Property2 { get { return null; } }
    public object Property3 { set { } }
    public object Property4 { get; set; }
    public object Property5 { set { } }
    public object Property6 { get; set; }
    public object Property7 { get { return null; } }
 
    //wrong by-{value,ref} return
    object o = null;
    public object Property8 { get { return null; } }
    public ref object Property9 { get { return ref o; } }
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.Property2.set'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Property2.set").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.Property3.get'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Property3.get").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.Property5.get'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Property5.get").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.Property7.set'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Property7.set").WithLocation(17, 15),
                // (17,15): error CS8152: 'Class' does not implement interface member 'Interface.Property8'. 'Class.Property8' cannot implement 'Interface.Property8' because it does not have matching return by reference.
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "Interface").WithArguments("Class", "Interface.Property8", "Class.Property8").WithLocation(17, 15),
                // (17,15): error CS8152: 'Class' does not implement interface member 'Interface.Property9'. 'Class.Property9' cannot implement 'Interface.Property9' because it does not have matching return by reference.
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "Interface").WithArguments("Class", "Interface.Property9", "Class.Property9").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.Property1'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.Property1").WithLocation(17, 15));
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceIndexer()
        {
            var text = @"
interface Interface
{
    object this[int w, int x, int y, string z] { get; set; }
 
    object this[int w, int x, string y, int z] { get; set; }
    object this[int w, int x, string y, string z] { get; set; }
    object this[int w, string x, int y, int z] { get; }
    object this[int w, string x, int y, string z] { get; }
    object this[int w, string x, string y, int z] { set; }
    object this[int w, string x, string y, string z] { set; }
 
    ref object this[string w, int x, int y, int z] { get; }
    object this[string w, int x, int y, string z] { get; }
}
 
class Class : Interface
{
    //missed first indexer entirely
 
    //wrong accessors
    public object this[int w, int x, string y, int z] { get { return null; } }
    public object this[int w, int x, string y, string z] { set { } }
    public object this[int w, string x, int y, int z] { get { return 0; } set { } }
    public object this[int w, string x, int y, string z] { set { } }
    public object this[int w, string x, string y, int z] { get { return 0; } set { } }
    public object this[int w, string x, string y, string z] { get { return null; } }
 
    // wrong by-{value,ref} return
    object o = null;
    public object this[string w, int x, int y, int z] { get { return null; } }
    public ref object this[string w, int x, int y, string z] { get { return ref o; } }
}
";
            CreateCompilationWithMscorlib461(text).VerifyDiagnostics(
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, string, string, string].set'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, string, string, string].set").WithLocation(17, 15),
                // (17,15): error CS8152: 'Class' does not implement interface member 'Interface.this[string, int, int, int]'. 'Class.this[string, int, int, int]' cannot implement 'Interface.this[string, int, int, int]' because it does not have matching return by reference.
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "Interface").WithArguments("Class", "Interface.this[string, int, int, int]", "Class.this[string, int, int, int]").WithLocation(17, 15),
                // (17,15): error CS8152: 'Class' does not implement interface member 'Interface.this[string, int, int, string]'. 'Class.this[string, int, int, string]' cannot implement 'Interface.this[string, int, int, string]' because it does not have matching return by reference.
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongRefReturn, "Interface").WithArguments("Class", "Interface.this[string, int, int, string]", "Class.this[string, int, int, string]").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, int, string, string].get'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, int, string, string].get").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, string, int, string].get'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, string, int, string].get").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, int, string, int].set'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, int, string, int].set").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, int, int, string]'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, int, int, string]").WithLocation(17, 15));
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceEvent()
        {
            var text = @"
interface Interface
{
    event System.Action Event1;
}
 
class Class : Interface
{
    //missed Event1 entirely
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedInterfaceMember, Line = 7, Column = 15 }, //1
            });
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceMethodInBase()
        {
            var text = @"
interface Interface
{
    object Method1();
    object Method2(int i);
}
 
class Base : Interface
{
    //missed Method1 entirely
    public object Method2(long l) { return 0; } //wrong signature
}
 
class Derived1 : Base //not declaring interface
{
}
 
class Derived2 : Base, Interface
{
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,14): error CS0535: 'Base' does not implement interface member 'Interface.Method2(int)'
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Base", "Interface.Method2(int)").WithLocation(8, 14),
                // (8,14): error CS0535: 'Base' does not implement interface member 'Interface.Method1()'
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Base", "Interface.Method1()").WithLocation(8, 14)
                );
        }
 
        [Fact]
        public void TestNoImplementationOfBaseInterfaceMethod()
        {
            var text = @"
interface Interface1
{
    object Method1();
}
interface Interface2
{
    object Method2();
}
class Base : Interface2
{
    public object Method1() { return null; }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface2").WithArguments("Base", "Interface2.Method2()"));
        }
 
        [Fact]
        public void TestNoImplementationOfInterfacePropertyInBase()
        {
            var text = @"
interface Interface
{
    object Property1 { get; set; }
    object Property2 { get; set; }
}
 
class Base : Interface
{
    //missed Property1 entirely
    public long Property2 { get; set; } //wrong type
}
 
class Derived1 : Base //not declaring interface
{
}
 
class Derived2 : Base, Interface
{
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,14): error CS0738: 'Base' does not implement interface member 'Interface.Property2'. 'Base.Property2' cannot implement 'Interface.Property2' because it does not have the matching return type of 'object'.
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Base", "Interface.Property2", "Base.Property2", "object").WithLocation(8, 14),
                // (8,14): error CS0535: 'Base' does not implement interface member 'Interface.Property1'
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Base", "Interface.Property1").WithLocation(8, 14),
                // (18,24): error CS0738: 'Derived2' does not implement interface member 'Interface.Property2'. 'Base.Property2' cannot implement 'Interface.Property2' because it does not have the matching return type of 'object'.
                // class Derived2 : Base, Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Derived2", "Interface.Property2", "Base.Property2", "object").WithLocation(18, 24)
                );
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceIndexerInBase()
        {
            var text = @"
interface Interface
{
    object this[int x] { get; set; }
    object this[string x] { get; set; }
}
 
class Base : Interface
{
    //missed int indexer entirely
    public long this[string x] { get { return 0; } set { } } //wrong type
}
 
class Derived1 : Base //not declaring interface
{
}
 
class Derived2 : Base, Interface
{
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,14): error CS0738: 'Base' does not implement interface member 'Interface.this[string]'. 'Base.this[string]' cannot implement 'Interface.this[string]' because it does not have the matching return type of 'object'.
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Base", "Interface.this[string]", "Base.this[string]", "object").WithLocation(8, 14),
                // (8,14): error CS0535: 'Base' does not implement interface member 'Interface.this[int]'
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Base", "Interface.this[int]").WithLocation(8, 14),
                // (18,24): error CS0738: 'Derived2' does not implement interface member 'Interface.this[string]'. 'Base.this[string]' cannot implement 'Interface.this[string]' because it does not have the matching return type of 'object'.
                // class Derived2 : Base, Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Derived2", "Interface.this[string]", "Base.this[string]", "object").WithLocation(18, 24)
                );
        }
 
        [Fact]
        public void TestNoImplementationOfInterfaceEventInBase()
        {
            var text = @"
interface Interface
{
    event System.Action Event1;
    event System.Action Event2;
}
 
class Base : Interface
{
    //missed Event1 entirely
    public event System.Action<int> Event2 { add { } remove { } } //wrong type
}
 
class Derived1 : Base //not declaring interface
{
}
 
class Derived2 : Base, Interface
{
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,14): error CS0738: 'Base' does not implement interface member 'Interface.Event2'. 'Base.Event2' cannot implement 'Interface.Event2' because it does not have the matching return type of 'Action'.
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Base", "Interface.Event2", "Base.Event2", "System.Action").WithLocation(8, 14),
                // (8,14): error CS0535: 'Base' does not implement interface member 'Interface.Event1'
                // class Base : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Base", "Interface.Event1").WithLocation(8, 14),
                // (18,24): error CS0738: 'Derived2' does not implement interface member 'Interface.Event2'. 'Base.Event2' cannot implement 'Interface.Event2' because it does not have the matching return type of 'Action'.
                // class Derived2 : Base, Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Derived2", "Interface.Event2", "Base.Event2", "System.Action").WithLocation(18, 24)
                );
        }
 
        [Fact]
        public void TestExplicitMethodImplementation()
        {
            var text = @"
 
interface BaseInterface
{
    void Method4();
}
interface Interface : BaseInterface
{
    void Method1();
    void Method2();
}
 
interface Interface2
{
    void Method1();
}
 
class Base : Interface
{
    void System.Object.Method1() { } //not an interface
    void Base.Method1() { } //not an interface
    void System.Int32.Method1() { } //not an interface
    void Interface2.Method1() { } //does not implement Interface2
    void Interface.Method3() { } //not on Interface
    void Interface.Method4() { } //not on Interface
 
    public void Method1() { }
    public void Method2() { }
    public void Method4() { }
}
 
class Derived : Base
{
    void Interface.Method1() { } //does not directly list Interface
}
 
class Derived2 : Base, Interface
{
    void Interface.Method1() { } //fine
    void BaseInterface.Method4() { } //fine
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (20,10): error CS0538: 'object' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Object").WithArguments("object"),
                // (21,10): error CS0538: 'Base' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "Base").WithArguments("Base"),
                // (22,10): error CS0538: 'int' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Int32").WithArguments("int"),
                // (23,10): error CS0540: 'Base.Interface2.Method1()': containing type does not implement interface 'Interface2'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface2").WithArguments("Base.Interface2.Method1()", "Interface2"),
                // (24,20): error CS0539: 'Base.Method3()' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method3").WithArguments("Base.Method3()"),
                // (25,20): error CS0539: 'Base.Method4()' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method4").WithArguments("Base.Method4()"),
                // (34,10): error CS0540: 'Derived.Interface.Method1()': containing type does not implement interface 'Interface'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface").WithArguments("Derived.Interface.Method1()", "Interface"));
        }
 
        [Fact]
        public void TestExplicitPropertyImplementation()
        {
            var text = @"
interface BaseInterface
{
    int Property4 { get; }
}
interface Interface : BaseInterface
{
    int Property1 { set; }
    int Property2 { set; }
}
 
interface Interface2
{
    int Property1 { set; }
}
 
class Base : Interface
{
    int System.Object.Property1 { set { } } //not an interface
    int Base.Property1 { set { } } //not an interface
    int System.Int32.Property1 { set { } } //not an interface
    int Interface2.Property1 { set { } } //does not implement Interface2
    int Interface.Property3 { set { } } //not on Interface
    int Interface.Property4 { get { return 1; } } //not on Interface
 
    public int Property1 { set { } }
    public int Property2 { set { } }
    public int Property4 { get { return 0; } }
}
 
class Derived : Base
{
    int Interface.Property1 { set { } } //does not directly list Interface
}
 
class Derived2 : Base, Interface
{
    int Interface.Property1 { set { } } //fine
    int BaseInterface.Property4 { get { return 1; } } //fine
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (19,9): error CS0538: 'object' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Object").WithArguments("object"),
                // (20,9): error CS0538: 'Base' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "Base").WithArguments("Base"),
                // (21,9): error CS0538: 'int' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Int32").WithArguments("int"),
                // (22,9): error CS0540: 'Base.Interface2.Property1': containing type does not implement interface 'Interface2'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface2").WithArguments("Base.Interface2.Property1", "Interface2"),
                // (23,19): error CS0539: 'Base.Property3' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property3").WithArguments("Base.Property3"),
                // (24,19): error CS0539: 'Base.Property4' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property4").WithArguments("Base.Property4"),
                // (33,9): error CS0540: 'Derived.Interface.Property1': containing type does not implement interface 'Interface'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface").WithArguments("Derived.Interface.Property1", "Interface"));
        }
 
        [Fact]
        public void TestExplicitIndexerImplementation()
        {
            var text = @"
interface BaseInterface
{
    int this[string x, string y] { get; }
}
interface Interface : BaseInterface
{
    int this[int x, int y] { set; }
    int this[int x, string y] { set; }
}
 
interface Interface2
{
    int this[int x, int y] { set; }
}
 
class Base : Interface
{
    int System.Object.this[int x, int y] { set { } } //not an interface
    int Base.this[int x, int y] { set { } } //not an interface
    int System.Int32.this[int x, int y] { set { } } //not an interface
    int Interface2.this[int x, int y] { set { } } //does not implement Interface2
    int Interface.this[string x, int y] { set { } } //not on Interface
    int Interface.this[string x, string y] { get { return 1; } } //not on Interface
 
    public int this[int x, int y] { set { } }
    public int this[int x, string y] { set { } }
    public int this[string x, string y] { get { return 0; } }
}
 
class Derived : Base
{
    int Interface.this[int x, int y] { set { } } //does not directly list Interface
}
 
class Derived2 : Base, Interface
{
    int Interface.this[int x, int y] { set { } } //fine
    int BaseInterface.this[string x, string y] { get { return 1; } } //fine
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (19,9): error CS0538: 'object' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Object").WithArguments("object"),
                // (20,9): error CS0538: 'Base' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "Base").WithArguments("Base"),
                // (21,9): error CS0538: 'int' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Int32").WithArguments("int"),
                // (22,9): error CS0540: 'Base.Interface2.this[int, int]': containing type does not implement interface 'Interface2'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface2").WithArguments("Base.Interface2.this[int, int]", "Interface2"),
                // (23,19): error CS0539: 'Base.this[string, int]' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Base.this[string, int]"),
                // (24,19): error CS0539: 'Base.this[string, string]' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "this").WithArguments("Base.this[string, string]"),
                // (33,9): error CS0540: 'Derived.Interface.this[int, int]': containing type does not implement interface 'Interface'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface").WithArguments("Derived.Interface.this[int, int]", "Interface"));
        }
 
        [Fact]
        public void TestExplicitEventImplementation()
        {
            var text = @"
interface BaseInterface
{
    event System.Action Event4;
}
interface Interface : BaseInterface
{
    event System.Action Event1;
    event System.Action Event2;
}
 
interface Interface2
{
    event System.Action Event1;
}
 
class Base : Interface
{
    event System.Action System.Object.Event1 { add { } remove { } } //not an interface
    event System.Action Base.Event1 { add { } remove { } } //not an interface
    event System.Action System.Int32.Event1 { add { } remove { } } //not an interface
    event System.Action Interface2.Event1 { add { } remove { } } //does not implement Interface2
    event System.Action Interface.Event3 { add { } remove { } } //not on Interface
    event System.Action Interface.Event4 { add { } remove { } } //not on Interface
 
    public event System.Action Event1 { add { } remove { } }
    public event System.Action Event2 { add { } remove { } }
    public event System.Action Event4 { add { } remove { } }
}
 
class Derived : Base
{
    event System.Action Interface.Event1 { add { } remove { } } //does not directly list Interface
}
 
class Derived2 : Base, Interface
{
    event System.Action Interface.Event1 { add { } remove { } } //fine
    event System.Action BaseInterface.Event4 { add { } remove { } } //fine
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (19,25): error CS0538: 'object' in explicit interface declaration is not an interface
                //     event System.Action System.Object.Event1 { add { } remove { } } //not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Object").WithArguments("object"),
                // (20,25): error CS0538: 'Base' in explicit interface declaration is not an interface
                //     event System.Action Base.Event1 { add { } remove { } } //not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "Base").WithArguments("Base"),
                // (21,25): error CS0538: 'int' in explicit interface declaration is not an interface
                //     event System.Action System.Int32.Event1 { add { } remove { } } //not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "System.Int32").WithArguments("int"),
                // (22,25): error CS0540: 'Base.Interface2.Event1': containing type does not implement interface 'Interface2'
                //     event System.Action Interface2.Event1 { add { } remove { } } //does not implement Interface2
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface2").WithArguments("Base.Interface2.Event1", "Interface2"),
                // (23,35): error CS0539: 'Base.Event3' in explicit interface declaration is not a member of interface
                //     event System.Action Interface.Event3 { add { } remove { } } //not on Interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Event3").WithArguments("Base.Event3"),
                // (24,35): error CS0539: 'Base.Event4' in explicit interface declaration is not a member of interface
                //     event System.Action Interface.Event4 { add { } remove { } } //not on Interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Event4").WithArguments("Base.Event4"),
                // (33,25): error CS0540: 'Derived.Interface.Event1': containing type does not implement interface 'Interface'
                //     event System.Action Interface.Event1 { add { } remove { } } //does not directly list Interface
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface").WithArguments("Derived.Interface.Event1", "Interface"));
        }
 
        [Fact]
        public void TestExplicitMethodImplementation2()
        {
            var text = @"
public interface I<T>
{
    void F();
}
 
public class C : I<object>
{
    void I<dynamic>.F() { } // Dev10 Error: we don't implement I<dynamic>
}
";
            CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
                // (9,10): error CS0540: 'C.I<dynamic>.F()': containing type does not implement interface 'I<dynamic>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I<dynamic>").WithArguments("C.I<dynamic>.F()", "I<dynamic>")
                );
        }
 
        [Fact]
        public void TestExplicitPropertyImplementation2()
        {
            var text = @"
public interface I<T>
{
    int P { set; }
}
 
public class C : I<object>
{
    int I<dynamic>.P { set { } } // Dev10 Error: we don't implement I<dynamic>
}
";
            CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
                // (9,9): error CS0540: 'C.I<dynamic>.P': containing type does not implement interface 'I<dynamic>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I<dynamic>").WithArguments("C.I<dynamic>.P", "I<dynamic>")
                );
        }
 
        [Fact]
        public void TestExplicitIndexerImplementation2()
        {
            var text = @"
public interface I<T>
{
    int this[int x] { set; }
}
 
public class C : I<object>
{
    int I<dynamic>.this[int x] { set { } } // Dev10 Error: we don't implement I<dynamic>
}
";
            CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
                // (9,9): error CS0540: 'C.I<dynamic>.this[int]': containing type does not implement interface 'I<dynamic>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I<dynamic>").WithArguments("C.I<dynamic>.this[int]", "I<dynamic>"));
        }
 
        [Fact]
        public void TestExplicitEventImplementation2()
        {
            var text = @"
public interface I<T>
{
    event System.Action E;
}
 
public class C : I<object>
{
    event System.Action I<dynamic>.E { add { } remove { } } // Dev10 Error: we don't implement I<dynamic>
}
";
            CreateCompilationWithMscorlib40AndSystemCore(text).VerifyDiagnostics(
                // (9,25): error CS0540: 'C.I<dynamic>.E': containing type does not implement interface 'I<dynamic>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "I<dynamic>").WithArguments("C.I<dynamic>.E", "I<dynamic>")
                );
        }
 
        [Fact]
        public void TestInterfaceImplementationMistakes()
        {
            var text = @"
interface Interface
{
    void Method1();
    void Method2();
    void Method3();
    void Method4();
    void Method5();
    void Method6();
    void Method7();
}
 
partial class Base : Interface
{
    public static void Method1() { }
    public int Method2() { return 0; }
    private void Method3() { }
    internal void Method4() { }
    protected void Method5() { }
    protected internal void Method6() { }
    partial void Method7();
}";
            CreateCompilation(text).VerifyDiagnostics(
                // (13,22): error CS0737: 'Base' does not implement interface member 'Interface.Method7()'. 'Base.Method7()' cannot implement an interface member because it is not public.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "Interface").WithArguments("Base", "Interface.Method7()", "Base.Method7()").WithLocation(13, 22),
                // (13,22): error CS0738: 'Base' does not implement interface member 'Interface.Method2()'. 'Base.Method2()' cannot implement 'Interface.Method2()' because it does not have the matching return type of 'void'.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Base", "Interface.Method2()", "Base.Method2()", "void").WithLocation(13, 22),
                // (13,22): error CS0737: 'Base' does not implement interface member 'Interface.Method3()'. 'Base.Method3()' cannot implement an interface member because it is not public.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "Interface").WithArguments("Base", "Interface.Method3()", "Base.Method3()").WithLocation(13, 22),
                // (13,22): error CS0737: 'Base' does not implement interface member 'Interface.Method4()'. 'Base.Method4()' cannot implement an interface member because it is not public.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "Interface").WithArguments("Base", "Interface.Method4()", "Base.Method4()").WithLocation(13, 22),
                // (13,22): error CS0737: 'Base' does not implement interface member 'Interface.Method5()'. 'Base.Method5()' cannot implement an interface member because it is not public.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "Interface").WithArguments("Base", "Interface.Method5()", "Base.Method5()").WithLocation(13, 22),
                // (13,22): error CS0737: 'Base' does not implement interface member 'Interface.Method6()'. 'Base.Method6()' cannot implement an interface member because it is not public.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "Interface").WithArguments("Base", "Interface.Method6()", "Base.Method6()").WithLocation(13, 22),
                // (13,22): error CS0736: 'Base' does not implement instance interface member 'Interface.Method1()'. 'Base.Method1()' cannot implement the interface member because it is static.
                // partial class Base : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, "Interface").WithArguments("Base", "Interface.Method1()", "Base.Method1()").WithLocation(13, 22));
        }
 
        [Fact]
        public void TestInterfacePropertyImplementationMistakes()
        {
            var text = @"
interface Interface
{
    long Property1 { get; set; }
    long Property2 { get; set; }
    long Property3 { get; set; }
    long Property4 { get; set; }
    long Property5 { get; set; }
    long Property6 { get; set; }
}
 
class Base : Interface
{
    public static long Property1 { get; set; }
    public int Property2 { get; set; }
    private long Property3 { get; set; }
    internal long Property4 { get; set; }
    protected long Property5 { get; set; }
    protected internal long Property6 { get; set; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
            });
        }
 
        [Fact]
        public void TestInterfaceIndexerImplementationMistakes()
        {
            var text = @"
interface Interface
{
    long this[int x, int y, string z] { get; set; }
    long this[int x, string y, int z] { get; set; }
    long this[int x, string y, string z] { get; set; }
    long this[string x, int y, int z] { get; set; }
    long this[string x, int y, string z] { get; set; }
    long this[string x, string y, int z] { get; set; }
}
 
class Base : Interface
{
    public static long this[int x, int y, string z] { get { return 0; } set { } }
    public int this[int x, string y, int z] { get { return 0; } set { } }
    private long this[int x, string y, string z] { get { return 0; } set { } }
    internal long this[string x, int y, int z] { get { return 0; } set { } }
    protected long this[string x, int y, string z] { get { return 0; } set { } }
    protected internal long this[string x, string y, int z] { get { return 0; } set { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_BadMemberFlag, Line = 14, Column = 24 }, //indexer can't be static
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
            });
        }
 
        [Fact]
        public void TestInterfaceEventImplementationMistakes()
        {
            var text = @"
interface Interface
{
    event System.Action Event1;
    event System.Action Event2;
    event System.Action Event3;
    event System.Action Event4;
    event System.Action Event5;
    event System.Action Event6;
}
 
class Base : Interface
{
    public static event System.Action Event1 { add { } remove { } }
    public event System.Action<int> Event2 { add { } remove { } }
    private event System.Action Event3 { add { } remove { } }
    internal event System.Action Event4 { add { } remove { } }
    protected event System.Action Event5 { add { } remove { } }
    protected internal event System.Action Event6 { add { } remove { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
            });
        }
 
        [Fact]
        public void TestInterfaceImplementationMistakesInBase()
        {
            var text = @"
interface Interface
{
    void Method1();
    void Method2();
    void Method3();
    void Method4();
    void Method5();
    void Method6();
    void Method7();
}
 
partial class Base : Interface
{
    public static void Method1() { }
    public int Method2() { return 0;  }
    private void Method3() { }
    internal void Method4() { }
    protected void Method5() { }
    protected internal void Method6() { }
    partial void Method7();
}
 
class Derived1 : Base //not declaring Interface
{
}
 
class Derived2 : Base, Interface
{
}
 
partial class Base2
{
    public static void Method1() { }
    public int Method2() { return 0;  }
    private void Method3() { }
    internal void Method4() { }
    protected void Method5() { }
    protected internal void Method6() { }
    partial void Method7();
}
 
class Base3 : Base2 { }
 
class Derived : Base3, Interface { }
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                //Base
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 13, Column = 22 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 13, Column = 22 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 13, Column = 22 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 13, Column = 22 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 13, Column = 22 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 13, Column = 22 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 13, Column = 22 },
 
                //Derived2
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 28, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 28, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 28, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 28, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 28, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 28, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 28, Column = 24 },
 
                //Derived3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 45, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 45, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 45, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 45, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 45, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 45, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 45, Column = 24 }
            });
        }
 
        [Fact]
        public void TestInterfacePropertyImplementationMistakesInBase()
        {
            var text = @"
interface Interface
{
    long Property1 { get; set; }
    long Property2 { get; set; }
    long Property3 { get; set; }
    long Property4 { get; set; }
    long Property5 { get; set; }
    long Property6 { get; set; }
}
 
class Base : Interface
{
    public static long Property1 { get; set; }
    public int Property2 { get; set; }
    private long Property3 { get; set; }
    internal long Property4 { get; set; }
    protected long Property5 { get; set; }
    protected internal long Property6 { get; set; }
}
 
class Derived1 : Base //not declaring Interface
{
}
 
class Derived2 : Base, Interface
{
}
 
class Base2
{
    public static long Property1 { get; set; }
    public int Property2 { get; set; }
    private long Property3 { get; set; }
    internal long Property4 { get; set; }
    protected long Property5 { get; set; }
    protected internal long Property6 { get; set; }
}
 
class Derived3 : Base2, Interface
{
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                //Base
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
 
                //Derived2
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
 
                //Derived3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
            });
        }
 
        [Fact]
        public void TestInterfaceIndexerImplementationMistakesInBase()
        {
            var text = @"
interface Interface
{
    long this[int x, int y, string z] { get; set; }
    long this[int x, string y, int z] { get; set; }
    long this[int x, string y, string z] { get; set; }
    long this[string x, int y, int z] { get; set; }
    long this[string x, int y, string z] { get; set; }
    long this[string x, string y, int z] { get; set; }
}
 
class Base : Interface
{
    public static long this[int x, int y, string z] { get { return 0; } set { } }
    public int this[int x, string y, int z] { get { return 0; } set { } }
    private long this[int x, string y, string z] { get { return 0; } set { } }
    internal long this[string x, int y, int z] { get { return 0; } set { } }
    protected long this[string x, int y, string z] { get { return 0; } set { } }
    protected internal long this[string x, string y, int z] { get { return 0; } set { } }
}
 
class Derived1 : Base //not declaring Interface
{
}
 
class Derived2 : Base, Interface
{
}
 
class Base2
{
    public static long this[int x, int y, string z] { get { return 0; } set { } }
    public int this[int x, string y, int z] { get { return 0; } set { } }
    private long this[int x, string y, string z] { get { return 0; } set { } }
    internal long this[string x, int y, int z] { get { return 0; } set { } }
    protected long this[string x, int y, string z] { get { return 0; } set { } }
    protected internal long this[string x, string y, int z] { get { return 0; } set { } }
}
 
class Derived3 : Base2, Interface
{
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                //Base
                new ErrorDescription { Code = (int)ErrorCode.ERR_BadMemberFlag, Line = 14, Column = 24 }, //indexer can't be static
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
 
                //Derived2
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
 
                //Derived3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
 
                //Base2
                new ErrorDescription { Code = (int)ErrorCode.ERR_BadMemberFlag, Line = 32, Column = 24 }, //indexer can't be static
            });
        }
 
        [Fact]
        public void TestInterfaceEventImplementationMistakesInBase()
        {
            var text = @"
interface Interface
{
    event System.Action Event1;
    event System.Action Event2;
    event System.Action Event3;
    event System.Action Event4;
    event System.Action Event5;
    event System.Action Event6;
}
 
class Base : Interface
{
    public static event System.Action Event1 { add { } remove { } }
    public event System.Action<int> Event2 { add { } remove { } }
    private event System.Action Event3 { add { } remove { } }
    internal event System.Action Event4 { add { } remove { } }
    protected event System.Action Event5 { add { } remove { } }
    protected internal event System.Action Event6 { add { } remove { } }
}
 
class Derived1 : Base //not declaring Interface
{
}
 
class Derived2 : Base, Interface
{
}
 
class Base2
{
    public static event System.Action Event1 { add { } remove { } }
    public event System.Action<int> Event2 { add { } remove { } }
    private event System.Action Event3 { add { } remove { } }
    internal event System.Action Event4 { add { } remove { } }
    protected event System.Action Event5 { add { } remove { } }
    protected internal event System.Action Event6 { add { } remove { } }
}
 
class Derived3 : Base2, Interface
{
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                //Base
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 12, Column = 14 },
 
                //Derived2
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 26, Column = 24 },
 
                //Derived3
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberStatic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, Line = 40, Column = 25 },
            });
        }
 
        [Fact]
        public void TestNewRequired()
        {
            var text = @"
interface IBase
{
    void Method1();
}
 
interface IDerived : IBase
{
    void Method1();
}
 
class Base
{
    public int field = 1;
    public int Property { get { return 0; } }
    public interface Interface { }
    public class Class { }
    public struct Struct { }
    public enum Enum { Element }
    public delegate void Delegate();
    public event Delegate Event;
    public int this[int x] { get { return 0; } }
}
 
class Derived : Base
{
    public int field = 2;
    public int Property { get { return 0; } }
    public interface Interface { }
    public class Class { }
    public struct Struct { }
    public enum Enum { Element }
    public delegate void Delegate();
    public event Delegate Event;
    public int this[int x] { get { return 0; } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (9,10): warning CS0108: 'IDerived.Method1()' hides inherited member 'IBase.Method1()'. Use the new keyword if hiding was intended.
                //     void Method1();
                Diagnostic(ErrorCode.WRN_NewRequired, "Method1").WithArguments("IDerived.Method1()", "IBase.Method1()"),
                // (27,16): warning CS0108: 'Derived.field' hides inherited member 'Base.field'. Use the new keyword if hiding was intended.
                //     public int field = 2;
                Diagnostic(ErrorCode.WRN_NewRequired, "field").WithArguments("Derived.field", "Base.field"),
                // (28,16): warning CS0108: 'Derived.Property' hides inherited member 'Base.Property'. Use the new keyword if hiding was intended.
                //     public int Property { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewRequired, "Property").WithArguments("Derived.Property", "Base.Property"),
                // (29,22): warning CS0108: 'Derived.Interface' hides inherited member 'Base.Interface'. Use the new keyword if hiding was intended.
                //     public interface Interface { }
                Diagnostic(ErrorCode.WRN_NewRequired, "Interface").WithArguments("Derived.Interface", "Base.Interface"),
                // (30,18): warning CS0108: 'Derived.Class' hides inherited member 'Base.Class'. Use the new keyword if hiding was intended.
                //     public class Class { }
                Diagnostic(ErrorCode.WRN_NewRequired, "Class").WithArguments("Derived.Class", "Base.Class"),
                // (31,19): warning CS0108: 'Derived.Struct' hides inherited member 'Base.Struct'. Use the new keyword if hiding was intended.
                //     public struct Struct { }
                Diagnostic(ErrorCode.WRN_NewRequired, "Struct").WithArguments("Derived.Struct", "Base.Struct"),
                // (32,17): warning CS0108: 'Derived.Enum' hides inherited member 'Base.Enum'. Use the new keyword if hiding was intended.
                //     public enum Enum { Element }
                Diagnostic(ErrorCode.WRN_NewRequired, "Enum").WithArguments("Derived.Enum", "Base.Enum"),
                // (33,26): warning CS0108: 'Derived.Delegate' hides inherited member 'Base.Delegate'. Use the new keyword if hiding was intended.
                //     public delegate void Delegate();
                Diagnostic(ErrorCode.WRN_NewRequired, "Delegate").WithArguments("Derived.Delegate", "Base.Delegate"),
                // (34,27): warning CS0108: 'Derived.Event' hides inherited member 'Base.Event'. Use the new keyword if hiding was intended.
                //     public event Delegate Event;
                Diagnostic(ErrorCode.WRN_NewRequired, "Event").WithArguments("Derived.Event", "Base.Event"),
                // (35,16): warning CS0108: 'Derived.this[int]' hides inherited member 'Base.this[int]'. Use the new keyword if hiding was intended.
                //     public int this[int x] { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewRequired, "this").WithArguments("Derived.this[int]", "Base.this[int]"),
 
                // (34,27): warning CS0067: The event 'Derived.Event' is never used
                //     public event Delegate Event;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("Derived.Event"),
                // (21,27): warning CS0067: The event 'Base.Event' is never used
                //     public event Delegate Event;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("Base.Event"));
        }
 
        [Fact]
        public void TestNewNotRequired()
        {
            var text = @"
class C
{
    //not hiding anything
    public new int field;
    public new int Property { get { return 0; } }
    public new interface Interface { }
    public new class Class { }
    public new struct Struct { }
    public new enum Enum { Element }
    public new delegate void Delegate();
    public new event Delegate Event;
    public new int this[int x] { get { return 0; } }
}
 
struct S
{
    //not hiding anything
    public new int field;
    public new int Property { get { return 0; } }
    public new interface Interface { }
    public new class Class { }
    public new struct Struct { }
    public new enum Enum { Element }
    public new delegate void Delegate();
    public new event Delegate Event;
    public new int this[int x] { get { return 0; } }
}
 
interface Interface
{
    void Method();
    int Property { get; }
}
 
class D : Interface
{
    //not required for interface impls
    public new void Method() { }
    public new int Property { get { return 0; } }
}
 
class Base : Interface
{
    void Interface.Method() { }
    int Interface.Property { get { return 0; } }
}
 
class Derived : Base
{
    //not hiding Base members because impls are explicit
    public new void Method() { } 
    public new int Property { get { return 0; } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (5,20): warning CS0109: The member 'C.field' does not hide an accessible member. The new keyword is not required.
                //     public new int field;
                Diagnostic(ErrorCode.WRN_NewNotRequired, "field").WithArguments("C.field"),
                // (6,20): warning CS0109: The member 'C.Property' does not hide an accessible member. The new keyword is not required.
                //     public new int Property { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Property").WithArguments("C.Property"),
                // (12,31): warning CS0109: The member 'C.Event' does not hide an accessible member. The new keyword is not required.
                //     public new event Delegate Event;
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Event").WithArguments("C.Event"),
                // (7,26): warning CS0109: The member 'C.Interface' does not hide an accessible member. The new keyword is not required.
                //     public new interface Interface { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Interface").WithArguments("C.Interface"),
                // (8,22): warning CS0109: The member 'C.Class' does not hide an accessible member. The new keyword is not required.
                //     public new class Class { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Class").WithArguments("C.Class"),
                // (9,23): warning CS0109: The member 'C.Struct' does not hide an accessible member. The new keyword is not required.
                //     public new struct Struct { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Struct").WithArguments("C.Struct"),
                // (10,21): warning CS0109: The member 'C.Enum' does not hide an accessible member. The new keyword is not required.
                //     public new enum Enum { Element }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Enum").WithArguments("C.Enum"),
                // (11,30): warning CS0109: The member 'C.Delegate' does not hide an accessible member. The new keyword is not required.
                //     public new delegate void Delegate();
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Delegate").WithArguments("C.Delegate"),
                // (13,20): warning CS0109: The member 'C.this[int]' does not hide an accessible member. The new keyword is not required.
                //     public new int this[int x] { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "this").WithArguments("C.this[int]"),
                // (19,20): warning CS0109: The member 'S.field' does not hide an accessible member. The new keyword is not required.
                //     public new int field;
                Diagnostic(ErrorCode.WRN_NewNotRequired, "field").WithArguments("S.field"),
                // (20,20): warning CS0109: The member 'S.Property' does not hide an accessible member. The new keyword is not required.
                //     public new int Property { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Property").WithArguments("S.Property"),
                // (26,31): warning CS0109: The member 'S.Event' does not hide an accessible member. The new keyword is not required.
                //     public new event Delegate Event;
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Event").WithArguments("S.Event"),
                // (21,26): warning CS0109: The member 'S.Interface' does not hide an accessible member. The new keyword is not required.
                //     public new interface Interface { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Interface").WithArguments("S.Interface"),
                // (22,22): warning CS0109: The member 'S.Class' does not hide an accessible member. The new keyword is not required.
                //     public new class Class { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Class").WithArguments("S.Class"),
                // (23,23): warning CS0109: The member 'S.Struct' does not hide an accessible member. The new keyword is not required.
                //     public new struct Struct { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Struct").WithArguments("S.Struct"),
                // (24,21): warning CS0109: The member 'S.Enum' does not hide an accessible member. The new keyword is not required.
                //     public new enum Enum { Element }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Enum").WithArguments("S.Enum"),
                // (25,30): warning CS0109: The member 'S.Delegate' does not hide an accessible member. The new keyword is not required.
                //     public new delegate void Delegate();
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Delegate").WithArguments("S.Delegate"),
                // (27,20): warning CS0109: The member 'S.this[int]' does not hide an accessible member. The new keyword is not required.
                //     public new int this[int x] { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "this").WithArguments("S.this[int]"),
                // (39,21): warning CS0109: The member 'D.Method()' does not hide an accessible member. The new keyword is not required.
                //     public new void Method() { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Method").WithArguments("D.Method()"),
                // (40,20): warning CS0109: The member 'D.Property' does not hide an accessible member. The new keyword is not required.
                //     public new int Property { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Property").WithArguments("D.Property"),
                // (52,21): warning CS0109: The member 'Derived.Method()' does not hide an accessible member. The new keyword is not required.
                //     public new void Method() { } 
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Method").WithArguments("Derived.Method()"),
                // (53,20): warning CS0109: The member 'Derived.Property' does not hide an accessible member. The new keyword is not required.
                //     public new int Property { get { return 0; } }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Property").WithArguments("Derived.Property"),
 
                // (5,20): warning CS0649: Field 'C.field' is never assigned to, and will always have its default value 0
                //     public new int field;
                Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("C.field", "0"),
                // (26,31): warning CS0067: The event 'S.Event' is never used
                //     public new event Delegate Event;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("S.Event"),
                // (19,20): warning CS0649: Field 'S.field' is never assigned to, and will always have its default value 0
                //     public new int field;
                Diagnostic(ErrorCode.WRN_UnassignedInternalField, "field").WithArguments("S.field", "0"),
                // (12,31): warning CS0067: The event 'C.Event' is never used
                //     public new event Delegate Event;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("C.Event")
                );
        }
 
        [Fact]
        public void TestNewOrOverrideRequired()
        {
            var text = @"
abstract class Base
{
    //for abstract case in Derived
    public abstract void Method1();
    public abstract void Method2();
    public abstract void Method3();
 
    //for virtual case in Derived
    public virtual void Method4() { }
    public virtual void Method5() { }
    public virtual void Method6() { }
 
    //for override case in Derived2
    public virtual void Method7() { }
    public virtual void Method8() { }
    public virtual void Method9() { }
 
    //for grandparent case in Derived2
    public virtual void Method10() { }
    public virtual void Method11() { }
    public virtual void Method12() { }
}
 
abstract class Derived : Base
{
    //abstract -> *
    public void Method1() { }
    public abstract void Method2();
    public virtual void Method3() { }
    
    //virtual -> *
    public void Method4() { }
    public abstract void Method5();
    public virtual void Method6() { }
 
    //for override case in Derived2
    public override void Method7() { }
    public override void Method8() { }
    public override void Method9() { }
}
 
abstract class Derived2 : Derived
{
    //override -> *
    public void Method7() { }
    public abstract void Method8();
    public virtual void Method9() { }
 
    //grandparent case
    public void Method10() { }
    public abstract void Method11();
    public virtual void Method12() { }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 28, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 28, Column = 17, IsWarning = false },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 29, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 29, Column = 26, IsWarning = false },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 30, Column = 25, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 30, Column = 25, IsWarning = false },
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 33, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 34, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 35, Column = 25, IsWarning = true },
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 46, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 47, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 48, Column = 25, IsWarning = true },
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 51, Column = 17, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 52, Column = 26, IsWarning = true },
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 53, Column = 25, IsWarning = true },
            });
        }
 
        [Fact]
        public void TestPropertyNewOrOverrideRequired()
        {
            var text = @"
abstract class Base
{
    //for abstract case in Derived
    public abstract long Property1 { get; set; }
    public abstract long Property2 { get; set; }
    public abstract long Property3 { get; set; }
 
    //for virtual case in Derived
    public virtual long Property4 { get; set; }
    public virtual long Property5 { get; set; }
    public virtual long Property6 { get; set; }
 
    //for override case in Derived2
    public virtual long Property7 { get; set; }
    public virtual long Property8 { get; set; }
    public virtual long Property9 { get; set; }
 
    //for grandparent case in Derived2
    public virtual long Property10 { get; set; }
    public virtual long Property11 { get; set; }
    public virtual long Property12 { get; set; }
}
 
abstract class Derived : Base
{
    //abstract -> *
    public long Property1 { get; set; }
    public abstract long Property2 { get; set; }
    public virtual long Property3 { get; set; }
    
    //virtual -> *
    public long Property4 { get; set; }
    public abstract long Property5 { get; set; }
    public virtual long Property6 { get; set; }
 
    //for override case in Derived2
    public override long Property7 { get; set; }
    public override long Property8 { get; set; }
    public override long Property9 { get; set; }
}
 
abstract class Derived2 : Derived
{
    //override -> *
    public long Property7 { get; set; }
    public abstract long Property8 { get; set; }
    public virtual long Property9 { get; set; }
 
    //grandparent case
    public long Property10 { get; set; }
    public abstract long Property11 { get; set; }
    public virtual long Property12 { get; set; }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 28, Column = 17, IsWarning = true }, //1
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 28, Column = 17, IsWarning = false }, //1.get/set
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 29, Column = 26, IsWarning = true }, //2
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 29, Column = 26, IsWarning = false }, //2.get/set
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 30, Column = 25, IsWarning = true }, //3
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 30, Column = 25, IsWarning = false }, //3.get/set
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 33, Column = 17, IsWarning = true }, //4
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 34, Column = 26, IsWarning = true }, //5
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 35, Column = 25, IsWarning = true }, //6
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 46, Column = 17, IsWarning = true }, //7
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 47, Column = 26, IsWarning = true }, //8
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 48, Column = 25, IsWarning = true }, //9
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 51, Column = 17, IsWarning = true }, //10
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 52, Column = 26, IsWarning = true }, //11
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 53, Column = 25, IsWarning = true }, //12
            });
        }
 
        [Fact]
        public void TestIndexerNewOrOverrideRequired()
        {
            var text = @"
abstract class Base
{
    //for abstract case in Derived
    public abstract long this[int w, int x, int y, string z] { get; set; }
    public abstract long this[int w, int x, string y, int z] { get; set; }
    public abstract long this[int w, int x, string y, string z] { get; set; }
 
    //for virtual case in Derived
    public virtual long this[int w, string x, int y, int z] { get { return 0; } set { } }
    public virtual long this[int w, string x, int y, string z] { get { return 0; } set { } }
    public virtual long this[int w, string x, string y, int z] { get { return 0; } set { } }
 
    //for override case in Derived2
    public virtual long this[int w, string x, string y, string z] { get { return 0; } set { } }
    public virtual long this[string w, int x, int y, int z] { get { return 0; } set { } }
    public virtual long this[string w, int x, int y, string z] { get { return 0; } set { } }
 
    //for grandparent case in Derived2
    public virtual long this[string w, int x, string y, int z] { get { return 0; } set { } }
    public virtual long this[string w, int x, string y, string z] { get { return 0; } set { } }
    public virtual long this[string w, string x, int y, int z] { get { return 0; } set { } }
}
 
abstract class Derived : Base
{
    //abstract -> *
    public long this[int w, int x, int y, string z] { get { return 0; } set { } }
    public abstract long this[int w, int x, string y, int z] { get; set; }
    public virtual long this[int w, int x, string y, string z] { get { return 0; } set { } }
    
    //virtual -> *
    public long this[int w, string x, int y, int z] { get { return 0; } set { } }
    public abstract long this[int w, string x, int y, string z] { get; set; }
    public virtual long this[int w, string x, string y, int z] { get { return 0; } set { } }
 
    //for override case in Derived2
    public override long this[int w, string x, string y, string z] { get { return 0; } set { } }
    public override long this[string w, int x, int y, int z] { get { return 0; } set { } }
    public override long this[string w, int x, int y, string z] { get { return 0; } set { } }
}
 
abstract class Derived2 : Derived
{
    //override -> *
    public long this[int w, string x, string y, string z] { get { return 0; } set { } }
    public abstract long this[string w, int x, int y, int z] { get; set; }
    public virtual long this[string w, int x, int y, string z] { get { return 0; } set { } }
 
    //grandparent case
    public long this[string w, int x, string y, int z] { get { return 0; } set { } }
    public abstract long this[string w, int x, string y, string z] { get; set; }
    public virtual long this[string w, string x, int y, int z] { get { return 0; } set { } }
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 28, Column = 17, IsWarning = true }, //1
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 28, Column = 17, IsWarning = false }, //1.get/set
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 29, Column = 26, IsWarning = true }, //2
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 29, Column = 26, IsWarning = false }, //2.get/set
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 30, Column = 25, IsWarning = true }, //3
                new ErrorDescription { Code = (int)ErrorCode.ERR_HidingAbstractMethod, Line = 30, Column = 25, IsWarning = false }, //3.get/set
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 33, Column = 17, IsWarning = true }, //4
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 34, Column = 26, IsWarning = true }, //5
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 35, Column = 25, IsWarning = true }, //6
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 46, Column = 17, IsWarning = true }, //7
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 47, Column = 26, IsWarning = true }, //8
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 48, Column = 25, IsWarning = true }, //9
 
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 51, Column = 17, IsWarning = true }, //10
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 52, Column = 26, IsWarning = true }, //11
                new ErrorDescription { Code = (int)ErrorCode.WRN_NewOrOverrideExpected, Line = 53, Column = 25, IsWarning = true }, //12
            });
        }
 
        [Fact]
        public void TestEventNewOrOverrideRequired()
        {
            var text = @"
abstract class Base
{
    //for abstract case in Derived
    public abstract event System.Action Event1;
    public abstract event System.Action Event2;
    public abstract event System.Action Event3;
 
    //for virtual case in Derived
    public virtual event System.Action Event4 { add { } remove { } }
    public virtual event System.Action Event5 { add { } remove { } }
    public virtual event System.Action Event6 { add { } remove { } }
 
    //for override case in Derived2
    public virtual event System.Action Event7 { add { } remove { } }
    public virtual event System.Action Event8 { add { } remove { } }
    public virtual event System.Action Event9 { add { } remove { } }
 
    //for grandparent case in Derived2
    public virtual event System.Action Event10 { add { } remove { } }
    public virtual event System.Action Event11 { add { } remove { } }
    public virtual event System.Action Event12 { add { } remove { } }
}
 
abstract class Derived : Base
{
    //abstract -> *
    public event System.Action Event1 { add { } remove { } }
    public abstract event System.Action Event2;
    public virtual event System.Action Event3 { add { } remove { } }
    
    //virtual -> *
    public event System.Action Event4 { add { } remove { } }
    public abstract event System.Action Event5;
    public virtual event System.Action Event6 { add { } remove { } }
 
    //for override case in Derived2
    public override event System.Action Event7 { add { } remove { } }
    public override event System.Action Event8 { add { } remove { } }
    public override event System.Action Event9 { add { } remove { } }
}
 
abstract class Derived2 : Derived
{
    //override -> *
    public event System.Action Event7 { add { } remove { } }
    public abstract event System.Action Event8;
    public virtual event System.Action Event9 { add { } remove { } }
 
    //grandparent case
    public event System.Action Event10 { add { } remove { } }
    public abstract event System.Action Event11;
    public virtual event System.Action Event12 { add { } remove { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (28,32): error CS0533: 'Derived.Event1' hides inherited abstract member 'Base.Event1'
                //     public event System.Action Event1 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Event1").WithArguments("Derived.Event1", "Base.Event1"),
                // (28,32): warning CS0114: 'Derived.Event1' hides inherited member 'Base.Event1'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public event System.Action Event1 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event1").WithArguments("Derived.Event1", "Base.Event1"),
                // (29,41): error CS0533: 'Derived.Event2' hides inherited abstract member 'Base.Event2'
                //     public abstract event System.Action Event2;
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Event2").WithArguments("Derived.Event2", "Base.Event2"),
                // (29,41): warning CS0114: 'Derived.Event2' hides inherited member 'Base.Event2'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public abstract event System.Action Event2;
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event2").WithArguments("Derived.Event2", "Base.Event2"),
                // (30,40): error CS0533: 'Derived.Event3' hides inherited abstract member 'Base.Event3'
                //     public virtual event System.Action Event3 { add { } remove { } }
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Event3").WithArguments("Derived.Event3", "Base.Event3"),
                // (30,40): warning CS0114: 'Derived.Event3' hides inherited member 'Base.Event3'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public virtual event System.Action Event3 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event3").WithArguments("Derived.Event3", "Base.Event3"),
                // (33,32): warning CS0114: 'Derived.Event4' hides inherited member 'Base.Event4'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public event System.Action Event4 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event4").WithArguments("Derived.Event4", "Base.Event4"),
                // (34,41): warning CS0114: 'Derived.Event5' hides inherited member 'Base.Event5'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public abstract event System.Action Event5;
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event5").WithArguments("Derived.Event5", "Base.Event5"),
                // (35,40): warning CS0114: 'Derived.Event6' hides inherited member 'Base.Event6'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public virtual event System.Action Event6 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event6").WithArguments("Derived.Event6", "Base.Event6"),
                // (46,32): warning CS0114: 'Derived2.Event7' hides inherited member 'Derived.Event7'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public event System.Action Event7 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event7").WithArguments("Derived2.Event7", "Derived.Event7"),
                // (47,41): warning CS0114: 'Derived2.Event8' hides inherited member 'Derived.Event8'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public abstract event System.Action Event8;
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event8").WithArguments("Derived2.Event8", "Derived.Event8"),
                // (48,40): warning CS0114: 'Derived2.Event9' hides inherited member 'Derived.Event9'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public virtual event System.Action Event9 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event9").WithArguments("Derived2.Event9", "Derived.Event9"),
                // (51,32): warning CS0114: 'Derived2.Event10' hides inherited member 'Base.Event10'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public event System.Action Event10 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event10").WithArguments("Derived2.Event10", "Base.Event10"),
                // (52,41): warning CS0114: 'Derived2.Event11' hides inherited member 'Base.Event11'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public abstract event System.Action Event11;
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event11").WithArguments("Derived2.Event11", "Base.Event11"),
                // (53,40): warning CS0114: 'Derived2.Event12' hides inherited member 'Base.Event12'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                //     public virtual event System.Action Event12 { add { } remove { } }
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Event12").WithArguments("Derived2.Event12", "Base.Event12"));
        }
 
        [Fact]
        public void TestExplicitImplementationAmbiguousInterfaceMethod()
        {
            var text = @"
public interface Interface<T>
{
    void Method(int i);
    void Method(T i);
}
 
public class Class : Interface<int>
{
    void Interface<int>.Method(int i) { } //this explicitly implements both methods in Interface<int>
    public void Method(int i) { } //this is here to avoid CS0535 - not implementing interface method
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_ExplicitImplCollision, Line = 10, Column = 25, IsWarning = true },
            });
        }
 
        [Fact]
        public void TestExplicitImplementationAmbiguousInterfaceMethodWithDifferingConstraints()
        {
            var text = @"
public interface Interface<T>
{
    void Method<V>(int i) where V : new();
    void Method<V>(T i);
}
 
public class Class : Interface<int>
{
    void Interface<int>.Method<V>(int i) { _ = new V(); } //this explicitly implements both methods in Interface<int>
    public void Method<V>(int i) { } //this is here to avoid CS0535 - not implementing interface method
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (10,25): warning CS0473: Explicit interface implementation 'Class.Interface<int>.Method<V>(int)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
                //     void Interface<int>.Method<V>(int i) { _ = new V(); } //this explicitly implements both methods in Interface<int>
                Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Class.Interface<int>.Method<V>(int)").WithLocation(10, 25));
        }
 
        [Fact]
        public void TestExplicitImplementationAmbiguousInterfaceMethodWithDifferingConstraints_OppositeDeclarationOrder()
        {
            var text = @"
public interface Interface<T>
{
    void Method<V>(T i);
    void Method<V>(int i) where V : new();
}
 
public class Class : Interface<int>
{
    void Interface<int>.Method<V>(int i) { _ = new V(); } //this explicitly implements both methods in Interface<int>
    public void Method<V>(int i) { } //this is here to avoid CS0535 - not implementing interface method
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (10,25): warning CS0473: Explicit interface implementation 'Class.Interface<int>.Method<V>(int)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
                //     void Interface<int>.Method<V>(int i) { _ = new V(); } //this explicitly implements both methods in Interface<int>
                Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Class.Interface<int>.Method<V>(int)").WithLocation(10, 25),
                // (10,48): error CS0304: Cannot create an instance of the variable type 'V' because it does not have the new() constraint
                //     void Interface<int>.Method<V>(int i) { _ = new V(); } //this explicitly implements both methods in Interface<int>
                Diagnostic(ErrorCode.ERR_NoNewTyvar, "new V()").WithArguments("V").WithLocation(10, 48),
                // (11,17): error CS0425: The constraints for type parameter 'V' of method 'Class.Method<V>(int)' must match the constraints for type parameter 'V' of interface method 'Interface<int>.Method<V>(int)'. Consider using an explicit interface implementation instead.
                //     public void Method<V>(int i) { } //this is here to avoid CS0535 - not implementing interface method
                Diagnostic(ErrorCode.ERR_ImplBadConstraints, "Method").WithArguments("V", "Class.Method<V>(int)", "V", "Interface<int>.Method<V>(int)").WithLocation(11, 17));
        }
 
        [Fact]
        public void TestExplicitImplementationAmbiguousInterfaceIndexer()
        {
            var text = @"
public interface Interface<T>
{
    long this[int i] { set; }
    long this[T i] { set; }
}
 
public class Class : Interface<int>
{
    long Interface<int>.this[int i] { set { } } //this explicitly implements both methods in Interface<int>
    public long this[int i] { set { } } //this is here to avoid CS0535 - not implementing interface method
}
";
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.WRN_ExplicitImplCollision, Line = 10, Column = 25, IsWarning = true },
            });
        }
 
        [Fact]
        public void TestAmbiguousImplementationMethod()
        {
            var text = @"
public interface Interface<T, U>
{
    void Method(int i);
    void Method(T i);
    void Method(U i);
}
 
public class Base<T> : Interface<T, T>
{
    public void Method(int i) { }
    public void Method(T i) { }
}
 
public class Derived : Base<int>, Interface<int, int>
{
}
 
class Other : Interface<int, int>
{
    void Interface<int, int>.Method(int i) { }
}
 
class YetAnother : Interface<int, int>
{
    public void Method(int i) { }
}
";
            //Both Base methods implement Interface.Method(int)
            //Both Base methods implement Interface.Method(T)
            //Both Base methods implement Interface.Method(U)
            CreateCompilation(text).VerifyDiagnostics(
                // (15,35): warning CS1956: Member 'Base<int>.Method(int)' implements interface member 'Interface<int, int>.Method(int)' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called.
                // public class Derived : Base<int>, Interface<int, int>
                Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.Method(int)", "Interface<int, int>.Method(int)", "Derived").WithLocation(15, 35),
                // (15,35): warning CS1956: Member 'Base<int>.Method(int)' implements interface member 'Interface<int, int>.Method(int)' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called.
                // public class Derived : Base<int>, Interface<int, int>
                Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.Method(int)", "Interface<int, int>.Method(int)", "Derived").WithLocation(15, 35),
                // (15,35): warning CS1956: Member 'Base<int>.Method(int)' implements interface member 'Interface<int, int>.Method(int)' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called.
                // public class Derived : Base<int>, Interface<int, int>
                Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.Method(int)", "Interface<int, int>.Method(int)", "Derived").WithLocation(15, 35),
                // (19,15): error CS0535: 'Other' does not implement interface member 'Interface<int, int>.Method(int)'
                // class Other : Interface<int, int>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface<int, int>").WithArguments("Other", "Interface<int, int>.Method(int)").WithLocation(19, 15),
                // (19,15): error CS0535: 'Other' does not implement interface member 'Interface<int, int>.Method(int)'
                // class Other : Interface<int, int>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface<int, int>").WithArguments("Other", "Interface<int, int>.Method(int)").WithLocation(19, 15),
                // (21,30): warning CS0473: Explicit interface implementation 'Other.Interface<int, int>.Method(int)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
                //     void Interface<int, int>.Method(int i) { }
                Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Other.Interface<int, int>.Method(int)").WithLocation(21, 30)
                );
        }
 
        [Fact]
        public void TestAmbiguousImplementationIndexer()
        {
            var text = @"
public interface Interface<T, U>
{
    long this[int i] { set; }
    long this[T i] { set; }
    long this[U i] { set; }
}
 
public class Base<T> : Interface<T, T>
{
    public long this[int i] { set { } }
    public long this[T i] { set { } }
}
 
public class Derived : Base<int>, Interface<int, int>
{
}
";
            // CONSIDER: Dev10 doesn't report these warnings -  not sure why
            CreateCompilation(text).VerifyDiagnostics(
                // (15,35): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called.
                // public class Derived : Base<int>, Interface<int, int>
                Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.this[int]", "Interface<int, int>.this[int]", "Derived").WithLocation(15, 35),
                // (15,35): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called.
                // public class Derived : Base<int>, Interface<int, int>
                Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.this[int]", "Interface<int, int>.this[int]", "Derived").WithLocation(15, 35),
                // (15,35): warning CS1956: Member 'Base<int>.this[int]' implements interface member 'Interface<int, int>.this[int]' in type 'Derived'. There are multiple matches for the interface member at run-time. It is implementation dependent which method will be called.
                // public class Derived : Base<int>, Interface<int, int>
                Diagnostic(ErrorCode.WRN_MultipleRuntimeImplementationMatches, "Interface<int, int>").WithArguments("Base<int>.this[int]", "Interface<int, int>.this[int]", "Derived").WithLocation(15, 35));
        }
 
        [Fact]
        public void TestHideAmbiguousImplementationMethod()
        {
            var text = @"
public interface Interface<T, U>
{
    void Method(int i);
    void Method(T i);
    void Method(U i);
}
 
public class Base<T> : Interface<T, T>
{
    public void Method(int i) { }
    public void Method(T i) { }
}
 
public class Derived : Base<int>, Interface<int, int>
{
    public new void Method(int i) { } //overrides Base's interface mapping
}
";
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestHideAmbiguousImplementationIndexer()
        {
            var text = @"
public interface Interface<T, U>
{
    long this[int i] { set; }
    long this[T i] { set; }
    long this[U i] { set; }
}
 
public class Base<T> : Interface<T, T>
{
    public long this[int i] { set { } }
    public long this[T i] { set { } }
}
 
public class Derived : Base<int>, Interface<int, int>
{
    public new long this[int i] { set { } } //overrides Base's interface mapping
}
";
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestHideAmbiguousOverridesMethod()
        {
            var text = @"
public class Base<T, U>
{
    public virtual void Method(int i) { }
    public virtual void Method(T i) { }
    public virtual void Method(U i) { }
}
 
public class Derived : Base<int, int>
{
    public new virtual void Method(int i) { }
}
 
public class Derived2 : Derived
{
    public override void Method(int i) { base.Method(i); }
}
";
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestHideAmbiguousOverridesIndexer()
        {
            var text = @"
public class Base<T, U>
{
    public virtual long this[int i] { set { } }
    public virtual long this[T i] { set { } }
    public virtual long this[U i] { set { } }
}
 
public class Derived : Base<int, int>
{
    public new virtual long this[int i] { set { } }
}
 
public class Derived2 : Derived
{
    public override long this[int i] { set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void TestAmbiguousOverrideMethod()
        {
            var text = @"
public class Base<TShort, TInt>
{
    public virtual void Method(TShort s, int i) { }
    public virtual void Method(short s, TInt i) { }
}
 
public class Derived : Base<short, int>
{
    public override void Method(short s, int i) { }
}
";
            CSharpCompilation comp = CreateCompilation(text, targetFramework: TargetFramework.NetLatest);
            Assert.Equal(RuntimeUtilities.IsCoreClrRuntime, comp.Assembly.RuntimeSupportsCovariantReturnsOfClasses);
            Assert.Equal(RuntimeUtilities.IsCoreClrRuntime, comp.SupportsRuntimeCapability(RuntimeCapability.CovariantReturnsOfClasses));
 
            if (comp.Assembly.RuntimeSupportsDefaultInterfaceImplementation)
            {
                comp.VerifyDiagnostics(
                    // (10,26): error CS0462: The inherited members 'Base<TShort, TInt>.Method(TShort, int)' and 'Base<TShort, TInt>.Method(short, TInt)' have the same signature in type 'Derived', so they cannot be overridden
                    //     public override void Method(short s, int i) { }
                    Diagnostic(ErrorCode.ERR_AmbigOverride, "Method").WithArguments("Base<TShort, TInt>.Method(TShort, int)", "Base<TShort, TInt>.Method(short, TInt)", "Derived").WithLocation(10, 26)
                    );
            }
            else
            {
                comp.VerifyDiagnostics(
                    // (4,25): warning CS1957: Member 'Derived.Method(short, int)' overrides 'Base<short, int>.Method(short, int)'. There are multiple override candidates at run-time. It is implementation dependent which method will be called. Please use a newer runtime.
                    //     public virtual void Method(TShort s, int i) { }
                    Diagnostic(ErrorCode.WRN_MultipleRuntimeOverrideMatches, "Method").WithArguments("Base<short, int>.Method(short, int)", "Derived.Method(short, int)").WithLocation(4, 25),
                    // (10,26): error CS0462: The inherited members 'Base<TShort, TInt>.Method(TShort, int)' and 'Base<TShort, TInt>.Method(short, TInt)' have the same signature in type 'Derived', so they cannot be overridden
                    //     public override void Method(short s, int i) { }
                    Diagnostic(ErrorCode.ERR_AmbigOverride, "Method").WithArguments("Base<TShort, TInt>.Method(TShort, int)", "Base<TShort, TInt>.Method(short, TInt)", "Derived").WithLocation(10, 26)
                    );
            }
        }
 
        [Fact]
        public void TestAmbiguousOverrideIndexer()
        {
            var text = @"
public class Base<TShort, TInt>
{
    public virtual long this[TShort s, int i] { set { } }
    public virtual long this[short s, TInt i] { set { } }
}
 
public class Derived : Base<short, int>
{
    public override long this[short s, int i] { set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (10,26): error CS0462: The inherited members 'Base<TShort, TInt>.this[TShort, int]' and 'Base<TShort, TInt>.this[short, TInt]' have the same signature in type 'Derived', so they cannot be overridden
                Diagnostic(ErrorCode.ERR_AmbigOverride, "this").WithArguments("Base<TShort, TInt>.this[TShort, int]", "Base<TShort, TInt>.this[short, TInt]", "Derived"));
        }
 
        [Fact]
        public void TestRuntimeAmbiguousOverride()
        {
            var text = @"
class Base<TInt>
{
    //these signatures differ only in ref/out
    public virtual void Method(int @in, ref int @ref) { }
    public virtual void Method(TInt @in, out TInt @out) { @out = @in; }
}
 
class Derived : Base<int>
{
    public override void Method(int @in, ref int @ref) { }
}
";
            var compilation = CreateCompilation(text, targetFramework: TargetFramework.NetLatest);
            Assert.Equal(RuntimeUtilities.IsCoreClrRuntime, compilation.Assembly.RuntimeSupportsCovariantReturnsOfClasses);
            Assert.Equal(RuntimeUtilities.IsCoreClrRuntime, compilation.SupportsRuntimeCapability(RuntimeCapability.CovariantReturnsOfClasses));
 
            if (compilation.Assembly.RuntimeSupportsCovariantReturnsOfClasses)
            {
                // We no longer report a runtime ambiguous override because the compiler
                // produces a methodimpl record to disambiguate.
                compilation.VerifyDiagnostics(
                    );
            }
            else
            {
                compilation.VerifyDiagnostics(
                    // (5,25): warning CS1957: Member 'Derived.Method(int, ref int)' overrides 'Base<int>.Method(int, ref int)'. There are multiple override candidates at run-time. It is implementation dependent which method will be called. Please use a newer runtime.
                    //     public virtual void Method(int @in, ref int @ref) { }
                    Diagnostic(ErrorCode.WRN_MultipleRuntimeOverrideMatches, "Method").WithArguments("Base<int>.Method(int, ref int)", "Derived.Method(int, ref int)").WithLocation(5, 25)
                    );
            }
        }
 
        [Fact]
        public void TestOverrideInaccessibleMethod()
        {
            var text1 = @"
public class Base
{
    internal virtual void Method() {}
}
";
 
            var text2 = @"
public class Derived : Base
{
    internal override void Method() { }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 4, Column = 28 }, //can't see internal method in other compilation
            });
        }
 
        [Fact]
        public void TestOverrideInaccessibleProperty()
        {
            var text1 = @"
public class Base
{
    internal virtual long Property { get; set; }
}
";
 
            var text2 = @"
public class Derived : Base
{
    internal override long Property { get; set; }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 4, Column = 28 }, //can't see internal method in other compilation
            });
        }
 
        [Fact]
        public void TestOverrideInaccessibleIndexer()
        {
            var text1 = @"
public class Base
{
    internal virtual long this[int x] { get { return 0; } set { } }
}
";
 
            var text2 = @"
public class Derived : Base
{
    internal override long this[int x] { get { return 0; } set { } }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 4, Column = 28 }, //can't see internal method in other compilation
            });
        }
 
        [Fact]
        public void TestOverrideInaccessibleEvent()
        {
            var text1 = @"
public class Base
{
    internal virtual event System.Action Event { add { } remove { } }
}
";
 
            var text2 = @"
public class Derived : Base
{
    internal override event System.Action Event { add { } remove { } }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 4, Column = 43 }, //can't see internal method in other compilation
            });
        }
 
        [Fact]
        public void TestVirtualMethodAccessibilityWithinAssembly()
        {
            var text = @"
public class Base
{
    internal virtual void Method1() { }
    internal virtual void Method2() { }
    internal virtual void Method3() { }
 
    protected virtual void Method4() { }
    protected virtual void Method5() { }
    protected virtual void Method6() { }
 
    protected internal virtual void Method7() { }
    protected internal virtual void Method8() { }
    protected internal virtual void Method9() { }
    protected internal virtual void Method10() { }
 
    public virtual void Method11() { }
    public virtual void Method12() { }
    public virtual void Method13() { }
 
    private protected virtual void Method14() { }
    private protected virtual void Method15() { }
    private protected virtual void Method16() { }
    private protected virtual void Method17() { }
}
 
public class Derived1 : Base
{
    protected override void Method1() { }
    protected internal override void Method2() { }
    public override void Method3() { }
 
    internal override void Method4() { }
    protected internal override void Method5() { }
    public override void Method6() { }
 
    internal override void Method7() { }
    protected override void Method8() { }
    protected internal override void Method9() { } //correct
    public override void Method10() { }
 
    internal override void Method11() { }
    protected override void Method12() { }
    protected internal override void Method13() { }
 
    internal override void Method14() { }
    protected override void Method15() { }
    protected internal override void Method16() { }
    public override void Method17() { }
}
";
            CreateCompilation(text, parseOptions: TestOptions.Regular7_2).VerifyDiagnostics(
                // (30,38): error CS0507: 'Derived1.Method2()': cannot change access modifiers when overriding 'internal' inherited member 'Base.Method2()'
                //     protected internal override void Method2() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method2").WithArguments("Derived1.Method2()", "internal", "Base.Method2()").WithLocation(30, 38),
                // (31,26): error CS0507: 'Derived1.Method3()': cannot change access modifiers when overriding 'internal' inherited member 'Base.Method3()'
                //     public override void Method3() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method3").WithArguments("Derived1.Method3()", "internal", "Base.Method3()").WithLocation(31, 26),
                // (33,28): error CS0507: 'Derived1.Method4()': cannot change access modifiers when overriding 'protected' inherited member 'Base.Method4()'
                //     internal override void Method4() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method4").WithArguments("Derived1.Method4()", "protected", "Base.Method4()").WithLocation(33, 28),
                // (34,38): error CS0507: 'Derived1.Method5()': cannot change access modifiers when overriding 'protected' inherited member 'Base.Method5()'
                //     protected internal override void Method5() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method5").WithArguments("Derived1.Method5()", "protected", "Base.Method5()").WithLocation(34, 38),
                // (35,26): error CS0507: 'Derived1.Method6()': cannot change access modifiers when overriding 'protected' inherited member 'Base.Method6()'
                //     public override void Method6() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method6").WithArguments("Derived1.Method6()", "protected", "Base.Method6()").WithLocation(35, 26),
                // (37,28): error CS0507: 'Derived1.Method7()': cannot change access modifiers when overriding 'protected internal' inherited member 'Base.Method7()'
                //     internal override void Method7() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method7").WithArguments("Derived1.Method7()", "protected internal", "Base.Method7()").WithLocation(37, 28),
                // (38,29): error CS0507: 'Derived1.Method8()': cannot change access modifiers when overriding 'protected internal' inherited member 'Base.Method8()'
                //     protected override void Method8() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method8").WithArguments("Derived1.Method8()", "protected internal", "Base.Method8()").WithLocation(38, 29),
                // (40,26): error CS0507: 'Derived1.Method10()': cannot change access modifiers when overriding 'protected internal' inherited member 'Base.Method10()'
                //     public override void Method10() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method10").WithArguments("Derived1.Method10()", "protected internal", "Base.Method10()").WithLocation(40, 26),
                // (42,28): error CS0507: 'Derived1.Method11()': cannot change access modifiers when overriding 'public' inherited member 'Base.Method11()'
                //     internal override void Method11() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method11").WithArguments("Derived1.Method11()", "public", "Base.Method11()").WithLocation(42, 28),
                // (43,29): error CS0507: 'Derived1.Method12()': cannot change access modifiers when overriding 'public' inherited member 'Base.Method12()'
                //     protected override void Method12() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method12").WithArguments("Derived1.Method12()", "public", "Base.Method12()").WithLocation(43, 29),
                // (44,38): error CS0507: 'Derived1.Method13()': cannot change access modifiers when overriding 'public' inherited member 'Base.Method13()'
                //     protected internal override void Method13() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method13").WithArguments("Derived1.Method13()", "public", "Base.Method13()").WithLocation(44, 38),
                // (46,28): error CS0507: 'Derived1.Method14()': cannot change access modifiers when overriding 'private protected' inherited member 'Base.Method14()'
                //     internal override void Method14() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method14").WithArguments("Derived1.Method14()", "private protected", "Base.Method14()").WithLocation(46, 28),
                // (47,29): error CS0507: 'Derived1.Method15()': cannot change access modifiers when overriding 'private protected' inherited member 'Base.Method15()'
                //     protected override void Method15() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method15").WithArguments("Derived1.Method15()", "private protected", "Base.Method15()").WithLocation(47, 29),
                // (48,38): error CS0507: 'Derived1.Method16()': cannot change access modifiers when overriding 'private protected' inherited member 'Base.Method16()'
                //     protected internal override void Method16() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method16").WithArguments("Derived1.Method16()", "private protected", "Base.Method16()").WithLocation(48, 38),
                // (49,26): error CS0507: 'Derived1.Method17()': cannot change access modifiers when overriding 'private protected' inherited member 'Base.Method17()'
                //     public override void Method17() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method17").WithArguments("Derived1.Method17()", "private protected", "Base.Method17()").WithLocation(49, 26),
                // (29,29): error CS0507: 'Derived1.Method1()': cannot change access modifiers when overriding 'internal' inherited member 'Base.Method1()'
                //     protected override void Method1() { }
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "Method1").WithArguments("Derived1.Method1()", "internal", "Base.Method1()").WithLocation(29, 29)
                );
        }
 
        [Fact]
        public void TestVirtualPropertyAccessibilityWithinAssembly()
        {
            var text = @"
public class Base
{
    internal virtual long Property1 { get; set; }
    internal virtual long Property2 { get; set; }
    internal virtual long Property3 { get; set; }
 
    protected virtual long Property4 { get; set; }
    protected virtual long Property5 { get; set; }
    protected virtual long Property6 { get; set; }
 
    protected internal virtual long Property7 { get; set; }
    protected internal virtual long Property8 { get; set; }
    protected internal virtual long Property9 { get; set; }
    protected internal virtual long Property10 { get; set; }
 
    public virtual long Property11 { get; set; }
    public virtual long Property12 { get; set; }
    public virtual long Property13 { get; set; }
}
 
public class Derived1 : Base
{
    protected override long Property1 { get; set; }
    protected internal override long Property2 { get; set; }
    public override long Property3 { get; set; }
 
    internal override long Property4 { get; set; }
    protected internal override long Property5 { get; set; }
    public override long Property6 { get; set; }
 
    internal override long Property7 { get; set; }
    protected override long Property8 { get; set; }
    protected internal override long Property9 { get; set; } //correct
    public override long Property10 { get; set; }
 
    internal override long Property11 { get; set; }
    protected override long Property12 { get; set; }
    protected internal override long Property13 { get; set; }
}
";
 
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 24, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 25, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 26, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 28, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 29, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 30, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 32, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 33, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 35, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 37, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 38, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 39, Column = 38 },
            });
        }
 
        [Fact]
        public void TestVirtualIndexerAccessibilityWithinAssembly()
        {
            var text = @"
public class Base
{
    internal virtual long this[int w, int x, int y, string z] { get { return 0; } set { } }
    internal virtual long this[int w, int x, string y, int z] { get { return 0; } set { } }
    internal virtual long this[int w, int x, string y, string z] { get { return 0; } set { } }
 
    protected virtual long this[int w, string x, int y, int z] { get { return 0; } set { } }
    protected virtual long this[int w, string x, int y, string z] { get { return 0; } set { } }
    protected virtual long this[int w, string x, string y, int z] { get { return 0; } set { } }
 
    protected internal virtual long this[int w, string x, string y, string z] { get { return 0; } set { } }
    protected internal virtual long this[string w, int x, int y, int z] { get { return 0; } set { } }
    protected internal virtual long this[string w, int x, int y, string z] { get { return 0; } set { } }
    protected internal virtual long this[string w, int x, string y, int z] { get { return 0; } set { } }
 
    public virtual long this[string w, int x, string y, string z] { get { return 0; } set { } }
    public virtual long this[string w, string x, int y, int z] { get { return 0; } set { } }
    public virtual long this[string w, string x, int y, string z] { get { return 0; } set { } }
}
 
public class Derived1 : Base
{
    protected override long this[int w, int x, int y, string z] { get { return 0; } set { } }
    protected internal override long this[int w, int x, string y, int z] { get { return 0; } set { } }
    public override long this[int w, int x, string y, string z] { get { return 0; } set { } }
 
    internal override long this[int w, string x, int y, int z] { get { return 0; } set { } }
    protected internal override long this[int w, string x, int y, string z] { get { return 0; } set { } }
    public override long this[int w, string x, string y, int z] { get { return 0; } set { } }
 
    internal override long this[int w, string x, string y, string z] { get { return 0; } set { } }
    protected override long this[string w, int x, int y, int z] { get { return 0; } set { } }
    protected internal override long this[string w, int x, int y, string z] { get { return 0; } set { } } //correct
    public override long this[string w, int x, string y, int z] { get { return 0; } set { } }
 
    internal override long this[string w, int x, string y, string z] { get { return 0; } set { } }
    protected override long this[string w, string x, int y, int z] { get { return 0; } set { } }
    protected internal override long this[string w, string x, int y, string z] { get { return 0; } set { } }
}
";
 
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 24, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 25, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 26, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 28, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 29, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 30, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 32, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 33, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 35, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 37, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 38, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 39, Column = 38 },
            });
        }
 
        [Fact]
        public void TestVirtualEventAccessibilityWithinAssembly()
        {
            var text = @"
public class Base
{
    internal virtual event System.Action Event1 { add { } remove { } }
    internal virtual event System.Action Event2 { add { } remove { } }
    internal virtual event System.Action Event3 { add { } remove { } }
 
    protected virtual event System.Action Event4 { add { } remove { } }
    protected virtual event System.Action Event5 { add { } remove { } }
    protected virtual event System.Action Event6 { add { } remove { } }
 
    protected internal virtual event System.Action Event7 { add { } remove { } }
    protected internal virtual event System.Action Event8 { add { } remove { } }
    protected internal virtual event System.Action Event9 { add { } remove { } }
    protected internal virtual event System.Action Event10 { add { } remove { } }
 
    public virtual event System.Action Event11 { add { } remove { } }
    public virtual event System.Action Event12 { add { } remove { } }
    public virtual event System.Action Event13 { add { } remove { } }
}
 
public class Derived1 : Base
{
    protected override event System.Action Event1 { add { } remove { } }
    protected internal override event System.Action Event2 { add { } remove { } }
    public override event System.Action Event3 { add { } remove { } }
 
    internal override event System.Action Event4 { add { } remove { } }
    protected internal override event System.Action Event5 { add { } remove { } }
    public override event System.Action Event6 { add { } remove { } }
 
    internal override event System.Action Event7 { add { } remove { } }
    protected override event System.Action Event8 { add { } remove { } }
    protected internal override event System.Action Event9 { add { } remove { } } //correct
    public override event System.Action Event10 { add { } remove { } }
 
    internal override event System.Action Event11 { add { } remove { } }
    protected override event System.Action Event12 { add { } remove { } }
    protected internal override event System.Action Event13 { add { } remove { } }
}
";
 
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 24, Column = 44 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 25, Column = 53 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 26, Column = 41 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 28, Column = 43 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 29, Column = 53 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 30, Column = 41 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 32, Column = 43 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 33, Column = 44 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 35, Column = 41 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 37, Column = 43 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 38, Column = 44 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 39, Column = 53 },
            });
        }
 
        [WorkItem(540185, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540185")]
        [Fact]
        public void TestChangeVirtualPropertyAccessorAccessibilityWithinAssembly()
        {
            var text = @"
public class Base
{
    public virtual long Property1 { get; protected set; }
}
 
public class Derived1 : Base
{
    public override long Property1 { get; private set; }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "set").WithArguments("Derived1.Property1.set", "protected", "Base.Property1.set"));
        }
 
        [Fact]
        public void TestChangeVirtualIndexerAccessorAccessibilityWithinAssembly()
        {
            var text = @"
public class Base
{
    public virtual long this[int x] { get { return 0; } protected set { } }
}
 
public class Derived1 : Base
{
    public override long this[int x] { get { return 0; } private set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (9,66): error CS0507: 'Derived1.this[int].set': cannot change access modifiers when overriding 'protected' inherited member 'Base.this[int].set'
                Diagnostic(ErrorCode.ERR_CantChangeAccessOnOverride, "set").WithArguments("Derived1.this[int].set", "protected", "Base.this[int].set"));
        }
 
        [Fact]
        public void TestVirtualMethodAccessibilityAcrossAssemblies()
        {
            var text1 = @"
public class Base
{
    internal virtual void Method1() { }
    internal virtual void Method2() { }
    internal virtual void Method3() { }
 
    protected virtual void Method4() { }
    protected virtual void Method5() { }
    protected virtual void Method6() { }
 
    protected internal virtual void Method7() { }
    protected internal virtual void Method8() { }
    protected internal virtual void Method9() { }
    protected internal virtual void Method10() { }
 
    public virtual void Method11() { }
    public virtual void Method12() { }
    public virtual void Method13() { }
}
";
 
            var text2 = @"
public class Derived2 : Base
{
    //can't find to override
    protected override void Method1() { }
    protected internal override void Method2() { }
    public override void Method3() { }
 
    internal override void Method4() { }
    protected internal override void Method5() { }
    public override void Method6() { }
 
    //protected internal in another assembly is protected in this one
    internal override void Method7() { }
    protected override void Method8() { } //correct
    protected internal override void Method9() { }
    public override void Method10() { }
 
    internal override void Method11() { }
    protected override void Method12() { }
    protected internal override void Method13() { }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 5, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 6, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 7, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 9,  Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 10, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 11, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 14, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 16, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 17, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 19, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 20, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 21, Column = 38 },
            });
        }
 
        [Fact]
        public void TestVirtualPropertyAccessibilityAcrossAssemblies()
        {
            var text1 = @"
public class Base
{
    internal virtual long Property1 { get; set; }
    internal virtual long Property2 { get; set; }
    internal virtual long Property3 { get; set; }
 
    protected virtual long Property4 { get; set; }
    protected virtual long Property5 { get; set; }
    protected virtual long Property6 { get; set; }
 
    protected internal virtual long Property7 { get; set; }
    protected internal virtual long Property8 { get; set; }
    protected internal virtual long Property9 { get; set; }
    protected internal virtual long Property10 { get; set; }
 
    public virtual long Property11 { get; set; }
    public virtual long Property12 { get; set; }
    public virtual long Property13 { get; set; }
}
";
 
            var text2 = @"
public class Derived2 : Base
{
    //can't find to override
    protected override long Property1 { get; set; }
    protected internal override long Property2 { get; set; }
    public override long Property3 { get; set; }
 
    internal override long Property4 { get; set; }
    protected internal override long Property5 { get; set; }
    public override long Property6 { get; set; }
 
    //protected internal in another assembly is protected in this one
    internal override long Property7 { get; set; }
    protected override long Property8 { get; set; } //correct
    protected internal override long Property9 { get; set; }
    public override long Property10 { get; set; }
 
    internal override long Property11 { get; set; }
    protected override long Property12 { get; set; }
    protected internal override long Property13 { get; set; }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 5, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 6, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 7, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 9,  Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 10, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 11, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 14, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 16, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 17, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 19, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 20, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 21, Column = 38 },
            });
        }
 
        [Fact]
        public void TestVirtualIndexerAccessibilityAcrossAssemblies()
        {
            var text1 = @"
public class Base
{
    internal virtual long this[int w, int x, int y, string z] { get { return 0; } set { } }
    internal virtual long this[int w, int x, string y, int z] { get { return 0; } set { } }
    internal virtual long this[int w, int x, string y, string z] { get { return 0; } set { } }
 
    protected virtual long this[int w, string x, int y, int z] { get { return 0; } set { } }
    protected virtual long this[int w, string x, int y, string z] { get { return 0; } set { } }
    protected virtual long this[int w, string x, string y, int z] { get { return 0; } set { } }
 
    protected internal virtual long this[int w, string x, string y, string z] { get { return 0; } set { } }
    protected internal virtual long this[string w, int x, int y, int z] { get { return 0; } set { } }
    protected internal virtual long this[string w, int x, int y, string z] { get { return 0; } set { } }
    protected internal virtual long this[string w, int x, string y, int z] { get { return 0; } set { } }
 
    public virtual long this[string w, int x, string y, string z] { get { return 0; } set { } }
    public virtual long this[string w, string x, int y, int z] { get { return 0; } set { } }
    public virtual long this[string w, string x, int y, string z] { get { return 0; } set { } }
}
";
 
            var text2 = @"
public class Derived2 : Base
{
    //can't find to override
    protected override long this[int w, int x, int y, string z] { get { return 0; } set { } }
    protected internal override long this[int w, int x, string y, int z] { get { return 0; } set { } }
    public override long this[int w, int x, string y, string z] { get { return 0; } set { } }
 
    internal override long this[int w, string x, int y, int z] { get { return 0; } set { } }
    protected internal override long this[int w, string x, int y, string z] { get { return 0; } set { } }
    public override long this[int w, string x, string y, int z] { get { return 0; } set { } }
 
    //protected internal in another assembly is protected in this one
    internal override long this[int w, string x, string y, string z] { get { return 0; } set { } }
    protected override long this[string w, int x, int y, int z] { get { return 0; } set { } } //correct
    protected internal override long this[string w, int x, int y, string z] { get { return 0; } set { } }
    public override long this[string w, int x, string y, int z] { get { return 0; } set { } }
 
    internal override long this[string w, int x, string y, string z] { get { return 0; } set { } }
    protected override long this[string w, string x, int y, int z] { get { return 0; } set { } }
    protected internal override long this[string w, string x, int y, string z] { get { return 0; } set { } }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 5, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 6, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 7, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 9,  Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 10, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 11, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 14, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 16, Column = 38 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 17, Column = 26 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 19, Column = 28 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 20, Column = 29 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 21, Column = 38 },
            });
        }
 
        [Fact]
        public void TestVirtualEventAccessibilityAcrossAssemblies()
        {
            var text1 = @"
public class Base
{
    internal virtual event System.Action Event1 { add { } remove { } }
    internal virtual event System.Action Event2 { add { } remove { } }
    internal virtual event System.Action Event3 { add { } remove { } }
 
    protected virtual event System.Action Event4 { add { } remove { } }
    protected virtual event System.Action Event5 { add { } remove { } }
    protected virtual event System.Action Event6 { add { } remove { } }
 
    protected internal virtual event System.Action Event7 { add { } remove { } }
    protected internal virtual event System.Action Event8 { add { } remove { } }
    protected internal virtual event System.Action Event9 { add { } remove { } }
    protected internal virtual event System.Action Event10 { add { } remove { } }
 
    public virtual event System.Action Event11 { add { } remove { } }
    public virtual event System.Action Event12 { add { } remove { } }
    public virtual event System.Action Event13 { add { } remove { } }
}
";
 
            var text2 = @"
public class Derived2 : Base
{
    //can't find to override
    protected override event System.Action Event1 { add { } remove { } }
    protected internal override event System.Action Event2 { add { } remove { } }
    public override event System.Action Event3 { add { } remove { } }
 
    internal override event System.Action Event4 { add { } remove { } }
    protected internal override event System.Action Event5 { add { } remove { } }
    public override event System.Action Event6 { add { } remove { } }
 
    //protected internal in another assembly is protected in this one
    internal override event System.Action Event7 { add { } remove { } }
    protected override event System.Action Event8 { add { } remove { } } //correct
    protected internal override event System.Action Event9 { add { } remove { } }
    public override event System.Action Event10 { add { } remove { } }
 
    internal override event System.Action Event11 { add { } remove { } }
    protected override event System.Action Event12 { add { } remove { } }
    protected internal override event System.Action Event13 { add { } remove { } }
}
";
            CompileAndVerifyDiagnostics(text1, text2, Array.Empty<ErrorDescription>(), new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 5, Column = 44 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 6, Column = 53 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_OverrideNotExpected, Line = 7, Column = 41 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 9,  Column = 43 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 10, Column = 53 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 11, Column = 41 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 14, Column = 43 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 16, Column = 53 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 17, Column = 41 },
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 19, Column = 43 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 20, Column = 44 },
                new ErrorDescription { Code = (int)ErrorCode.ERR_CantChangeAccessOnOverride, Line = 21, Column = 53 },
            });
        }
 
        [Fact]
        public void TestExplicitPropertyChangeAccessors()
        {
            var text = @"
interface Interface
{
    int Property1 { get; set; }
    int Property2 { get; set; }
    int Property3 { get; set; }
 
    int Property4 { get; }
    int Property5 { get; }
    int Property6 { get; }
 
    int Property7 { set; }
    int Property8 { set; }
    int Property9 { set; }
}
 
class Class : Interface
{
    int Interface.Property1 { get { return 1; } }
    int Interface.Property2 { set { } }
    int Interface.Property3 { get { return 1; } set { } }
 
    int Interface.Property4 { get { return 1; } }
    int Interface.Property5 { set { } }
    int Interface.Property6 { get { return 1; } set { } }
    
    int Interface.Property7 { get { return 1; } }
    int Interface.Property8 { set { } }
    int Interface.Property9 { get { return 1; } set { } }
}
";
 
            CompileAndVerifyDiagnostics(text, new ErrorDescription[] {
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyMissingAccessor, Line = 19, Column = 19 }, //1
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyMissingAccessor, Line = 20, Column = 19 }, //2
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyMissingAccessor, Line = 24, Column = 19 }, //4
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyAddingAccessor, Line = 24, Column = 31 }, //4
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyAddingAccessor, Line = 25, Column = 49 }, //5
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyMissingAccessor, Line = 27, Column = 19 }, //7
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyAddingAccessor, Line = 27, Column = 31 }, //7
                new ErrorDescription { Code = (int)ErrorCode.ERR_ExplicitPropertyAddingAccessor, Line = 29, Column = 31 }, //9
 
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedInterfaceMember, Line = 17, Column = 15 }, //1
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedInterfaceMember, Line = 17, Column = 15 }, //2
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedInterfaceMember, Line = 17, Column = 15 }, //4
                new ErrorDescription { Code = (int)ErrorCode.ERR_UnimplementedInterfaceMember, Line = 17, Column = 15 }, //7
            });
        }
 
        [Fact]
        public void TestExplicitIndexerChangeAccessors()
        {
            var text = @"
interface Interface
{
    int this[int w, int x, int y, string z] { get; set; }
    int this[int w, int x, string y, int z] { get; set; }
    int this[int w, int x, string y, string z] { get; set; }
 
    int this[int w, string x, int y, int z] { get; }
    int this[int w, string x, int y, string z] { get; }
    int this[int w, string x, string y, int z] { get; }
 
    int this[int w, string x, string y, string z] { set; }
    int this[string w, int x, int y, int z] { set; }
    int this[string w, int x, int y, string z] { set; }
}
 
class Class : Interface
{
    int Interface.this[int w, int x, int y, string z] { get { return 1; } }
    int Interface.this[int w, int x, string y, int z] { set { } }
    int Interface.this[int w, int x, string y, string z] { get { return 1; } set { } }
 
    int Interface.this[int w, string x, int y, int z] { get { return 1; } }
    int Interface.this[int w, string x, int y, string z] { set { } }
    int Interface.this[int w, string x, string y, int z] { get { return 1; } set { } }
    
    int Interface.this[int w, string x, string y, string z] { get { return 1; } }
    int Interface.this[string w, int x, int y, int z] { set { } }
    int Interface.this[string w, int x, int y, string z] { get { return 1; } set { } }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (19,19): error CS0551: Explicit interface implementation 'Class.Interface.this[int, int, int, string]' is missing accessor 'Interface.this[int, int, int, string].set'
                //     int Interface.this[int w, int x, int y, string z] { get { return 1; } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Class.Interface.this[int, int, int, string]", "Interface.this[int, int, int, string].set").WithLocation(19, 19),
                // (20,19): error CS0551: Explicit interface implementation 'Class.Interface.this[int, int, string, int]' is missing accessor 'Interface.this[int, int, string, int].get'
                //     int Interface.this[int w, int x, string y, int z] { set { } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Class.Interface.this[int, int, string, int]", "Interface.this[int, int, string, int].get").WithLocation(20, 19),
                // (24,19): error CS0551: Explicit interface implementation 'Class.Interface.this[int, string, int, string]' is missing accessor 'Interface.this[int, string, int, string].get'
                //     int Interface.this[int w, string x, int y, string z] { set { } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Class.Interface.this[int, string, int, string]", "Interface.this[int, string, int, string].get").WithLocation(24, 19),
                // (24,60): error CS0550: 'Class.Interface.this[int, string, int, string].set' adds an accessor not found in interface member 'Interface.this[int, string, int, string]'
                //     int Interface.this[int w, string x, int y, string z] { set { } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("Class.Interface.this[int, string, int, string].set", "Interface.this[int, string, int, string]").WithLocation(24, 60),
                // (25,78): error CS0550: 'Class.Interface.this[int, string, string, int].set' adds an accessor not found in interface member 'Interface.this[int, string, string, int]'
                //     int Interface.this[int w, string x, string y, int z] { get { return 1; } set { } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "set").WithArguments("Class.Interface.this[int, string, string, int].set", "Interface.this[int, string, string, int]").WithLocation(25, 78),
                // (27,63): error CS0550: 'Class.Interface.this[int, string, string, string].get' adds an accessor not found in interface member 'Interface.this[int, string, string, string]'
                //     int Interface.this[int w, string x, string y, string z] { get { return 1; } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("Class.Interface.this[int, string, string, string].get", "Interface.this[int, string, string, string]").WithLocation(27, 63),
                // (27,19): error CS0551: Explicit interface implementation 'Class.Interface.this[int, string, string, string]' is missing accessor 'Interface.this[int, string, string, string].set'
                //     int Interface.this[int w, string x, string y, string z] { get { return 1; } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyMissingAccessor, "this").WithArguments("Class.Interface.this[int, string, string, string]", "Interface.this[int, string, string, string].set").WithLocation(27, 19),
                // (29,60): error CS0550: 'Class.Interface.this[string, int, int, string].get' adds an accessor not found in interface member 'Interface.this[string, int, int, string]'
                //     int Interface.this[string w, int x, int y, string z] { get { return 1; } set { } }
                Diagnostic(ErrorCode.ERR_ExplicitPropertyAddingAccessor, "get").WithArguments("Class.Interface.this[string, int, int, string].get", "Interface.this[string, int, int, string]").WithLocation(29, 60),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, int, string, int].get'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, int, string, int].get").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, string, int, string].get'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, string, int, string].get").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, int, int, string].set'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, int, int, string].set").WithLocation(17, 15),
                // (17,15): error CS0535: 'Class' does not implement interface member 'Interface.this[int, string, string, string].set'
                // class Class : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class", "Interface.this[int, string, string, string].set").WithLocation(17, 15));
        }
 
        [WorkItem(539162, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539162")]
        [Fact]
        public void TestAbstractTypeMember()
        {
            var text = @"
abstract partial class ConstantValue
{
  abstract class ConstantValueDiscriminated : ConstantValue
  {
  }
 
  class ConstantValueBad : ConstantValue
  {
  }
}
";
 
            //no errors
            CompileAndVerifyDiagnostics(text, new ErrorDescription[0]);
        }
 
        [Fact]
        public void OverridePrivatePropertyAccessor()
        {
            var text = @"
public class Base
{
    public virtual long Property1 { get; private set; }
}
public class Derived1 : Base
{
    public override long Property1 { get; private set; }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "set").WithArguments("Derived1.Property1.set"));
        }
 
        [Fact]
        public void OverridePrivateIndexerAccessor()
        {
            var text = @"
public class Base
{
    public virtual long this[int x] { get { return 0; } private set { } }
}
public class Derived1 : Base
{
    public override long this[int x] { get { return 0; } private set { } }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (8,66): error CS0115: 'Derived1.this[int].set': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "set").WithArguments("Derived1.this[int].set"));
        }
 
        [WorkItem(540221, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540221")]
        [Fact]
        public void AbstractOverrideOnePropertyAccessor()
        {
            var text = @"
public class Base1
{
    public virtual long Property1 { get { return 0; } set { } }
}
abstract public class Base2 : Base1
{
    public abstract override long Property1 { get; }
    void test1()
    {
        Property1 += 1;
    }
}
public class Derived : Base2
{
    public override long Property1 { get { return 1; } set { } }
    void test2()
    {
        base.Property1++;
        base.Property1 = 2;
        long x = base.Property1;
    }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (19,9): error CS0205: Cannot call an abstract base member: 'Base2.Property1'
                Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Property1").WithArguments("Base2.Property1").WithLocation(19, 9),
                // (21,18): error CS0205: Cannot call an abstract base member: 'Base2.Property1'
                Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base.Property1").WithArguments("Base2.Property1").WithLocation(21, 18));
        }
 
        [Fact]
        public void AbstractOverrideOneIndexerAccessor()
        {
            var text = @"
public class Base1
{
    public virtual long this[long x] { get { return 0; } set { } }
}
abstract public class Base2 : Base1
{
    public abstract override long this[long x] { get; }
    void test1()
    {
        this[0] += 1;
    }
}
public class Derived : Base2
{
    public override long this[long x] { get { return 1; } set { } }
    void test2()
    {
        base[0]++;
        base[0] = 2;
        long x = base[0];
    }
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (19,9): error CS0205: Cannot call an abstract base member: 'Base2.this[long]'
                Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base[0]").WithArguments("Base2.this[long]").WithLocation(19, 9),
                // (21,18): error CS0205: Cannot call an abstract base member: 'Base2.this[long]'
                Diagnostic(ErrorCode.ERR_AbstractBaseCall, "base[0]").WithArguments("Base2.this[long]").WithLocation(21, 18));
        }
 
        [Fact]
        public void TestHidingErrors()
        {
            // Tests:
            // Hide base virtual member using new
            // By default members should be hidden by signature if new is not specified
            // new should hide by signature
 
            var text = @"
using System.Collections.Generic;
class Base<T>
{
    public virtual void Method() { }
    public virtual void Method(T x) { }
    public virtual void Method(T x, T y, List<T> a, Dictionary<T, T> b) { }
    public virtual void Method<U>(T x, T y) { }
    public virtual void Method<U>(U x, T y, List<U> a, Dictionary<T, U> b) { }
    public virtual int Property1 { get { return 0; } }
    public virtual int Property2 { get { return 0; } set { } }
    public virtual void Method2() { }
    public virtual void Method3() { }
}
class Derived<U> : Base<U>
{
    public void Method(U x, U y) { }
    public new void Method(U x, U y, List<U> a, Dictionary<U, U> b) { }
    public new void Method<V>(V x, U y, List<V> a, Dictionary<U, V> b) { }
    public void Method<V>(V x, U y, List<V> a, Dictionary<V, U> b) { }
    public new virtual int Property1 { set {  } }
    public new static int Property2 { get; set; }
    public new static void Method(U i) { }
    public new class Method2 { }
    public void Method<A, B>(U x, U y) {  }
    public new int Method3 { get; set; } 
}
class Derived2 : Derived<int>
{
    public override void Method() { }
    public override void Method(int i) { }
    public override void Method(int x, int y, List<int> a, Dictionary<int, int> b) { }
    public override void Method<V>(V x, int y, List<V> a, Dictionary<int, V> b) { }
    public override void Method<U>(int x, int y) { }
    public override int Property1 { get { return 1; } }
    public override int Property2 { get; set; }
    public override void Method2() { }
    public override void Method3() { }
}
class Test
{
    public static void Main()
    {
        Derived2 d2 = new Derived2();
        Derived<int> d = d2;
        Base<int> b = d2;
 
        b.Method();
        b.Method(1);
        b.Method<int>(1, 1);
        b.Method<int>(1, 1, new List<int>(), new Dictionary<int, int>());
        b.Method(1, 1, new List<int>(), new Dictionary<int, int>());
        b.Method2();
        int x = b.Property1;
        b.Property2 -= 1;
        b.Method3();
 
        d.Method();
        Derived<int>.Method(1);
        d.Method<int>(1, 1);
        d.Method<long>(1, 1, new List<long>(), new Dictionary<int, long>());
        d.Method<long>(1, 1, new List<long>(), new Dictionary<long, int>());
        d.Method(1, 1, new List<int>(), new Dictionary<int, int>());
        d.Method2();
        d.Method<int, int>(1, 1);
        Derived<int>.Method2 y = new Derived<int>.Method2(); // Both Method2's are visible?
        d.Property1 = 1;
        Derived<int>.Property2 = Derived<int>.Property2;
        d.Method3();
        x = d.Method3;
    }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (31,26): error CS0506: 'Derived2.Method(int)': cannot override inherited member 'Derived<int>.Method(int)' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "Method").WithArguments("Derived2.Method(int)", "Derived<int>.Method(int)"),
                // (32,26): error CS0506: 'Derived2.Method(int, int, System.Collections.Generic.List<int>, System.Collections.Generic.Dictionary<int, int>)': cannot override inherited member 'Derived<int>.Method(int, int, System.Collections.Generic.List<int>, System.Collections.Generic.Dictionary<int, int>)' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "Method").WithArguments("Derived2.Method(int, int, System.Collections.Generic.List<int>, System.Collections.Generic.Dictionary<int, int>)", "Derived<int>.Method(int, int, System.Collections.Generic.List<int>, System.Collections.Generic.Dictionary<int, int>)"),
                // (33,26): error CS0506: 'Derived2.Method<V>(V, int, System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<int, V>)': cannot override inherited member 'Derived<int>.Method<V>(V, int, System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<int, V>)' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "Method").WithArguments("Derived2.Method<V>(V, int, System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<int, V>)", "Derived<int>.Method<V>(V, int, System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<int, V>)"),
                // (35,37): error CS0545: 'Derived2.Property1.get': cannot override because 'Derived<int>.Property1' does not have an overridable get accessor
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "get").WithArguments("Derived2.Property1.get", "Derived<int>.Property1"),
                // (36,25): error CS0506: 'Derived2.Property2': cannot override inherited member 'Derived<int>.Property2' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "Property2").WithArguments("Derived2.Property2", "Derived<int>.Property2"),
                // (37,26): error CS0505: 'Derived2.Method2()': cannot override because 'Derived<int>.Method2' is not a function
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Method2").WithArguments("Derived2.Method2()", "Derived<int>.Method2"),
                // (38,26): error CS0505: 'Derived2.Method3()': cannot override because 'Derived<int>.Method3' is not a function
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Method3").WithArguments("Derived2.Method3()", "Derived<int>.Method3"));
        }
 
        [Fact]
        public void TestOverloadingByRefOut()
        {
            var text = @"
using System;
abstract class Base
{
    public abstract void Method(int x, ref int y, out Exception z);
}
abstract class Base2 : Base
{
    public abstract void Method(int x, out int y, ref Exception z); // No warnings about hiding
}
class Derived2 : Base2
{
    public override void Method(int x, out int y, ref Exception z) { y = 0; }
    public override void Method(int x, ref int y, out Exception z) { z = null; }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (14,26): error CS0663: 'Derived2' cannot define an overloaded method that differs only on parameter modifiers 'ref' and 'out'
                //     public override void Method(int x, ref int y, out Exception z) { z = null; }
                Diagnostic(ErrorCode.ERR_OverloadRefKind, "Method").WithArguments("Derived2", "method", "ref", "out").WithLocation(14, 26));
        }
 
        [Fact]
        public void TestOverloadingByParams()
        {
            var text = @"
using System;
abstract class Base
{
    public abstract void Method(int x, params Exception[] z);
    public abstract void Method(int x, int[] z);
}
abstract class Base2 : Base
{
    public abstract void Method(int x, Exception[] z);
    public abstract void Method(int x, params int[] z);
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (10,26): error CS0533: 'Base2.Method(int, System.Exception[])' hides inherited abstract member 'Base.Method(int, params System.Exception[])'
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Method").WithArguments("Base2.Method(int, System.Exception[])", "Base.Method(int, params System.Exception[])"),
                // (10,26): warning CS0114: 'Base2.Method(int, System.Exception[])' hides inherited member 'Base.Method(int, params System.Exception[])'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Method").WithArguments("Base2.Method(int, System.Exception[])", "Base.Method(int, params System.Exception[])"),
                // (11,26): error CS0533: 'Base2.Method(int, params int[])' hides inherited abstract member 'Base.Method(int, int[])'
                Diagnostic(ErrorCode.ERR_HidingAbstractMethod, "Method").WithArguments("Base2.Method(int, params int[])", "Base.Method(int, int[])"),
                // (11,26): warning CS0114: 'Base2.Method(int, params int[])' hides inherited member 'Base.Method(int, int[])'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Method").WithArguments("Base2.Method(int, params int[])", "Base.Method(int, int[])"));
        }
 
        [Fact]
        public void TestOverridingOmitLessAccessibleAccessor()
        {
            var text = @"
using System.Collections.Generic;
 
abstract class Base<T>
{
    public abstract List<T> Property1 { get; internal set; }
    public abstract List<T> Property2 { set; internal get; }
}
 
abstract class Base2<T> : Base<T>
{
}
 
class Derived : Base2<int>
{
    public sealed override List<int> Property1 { get { return null; } }
    public sealed override List<int> Property2 { set { } }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base<int>.Property2.get'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base<int>.Property2.get"),
                // (14,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base<int>.Property1.set'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base<int>.Property1.set"));
        }
 
        [Fact]
        public void TestOverridingOmitInaccessibleAccessorInDifferentAssembly()
        {
            var text1 = @"
using System;
using System.Collections.Generic;
 
public abstract class Base<T>
{
    public abstract List<T> Property1 { get; internal set; }
    public abstract List<T> Property2 { set; internal get; }
}";
            var comp1 = CreateCompilation(text1);
 
            var text2 = @"
using System.Collections.Generic;
 
abstract class Base2<T> : Base<T>
{
}
 
class Derived : Base2<int>
{
    public sealed override List<int> Property1 { get { return null; } }
    public sealed override List<int> Property2 { set { } }
}";
 
            CreateCompilation(text2, new[] { new CSharpCompilationReference(comp1) }).VerifyDiagnostics(
                // (10,38): error CS0546: 'Derived.Property1': cannot override because 'Base<int>.Property1' does not have an overridable set accessor
                Diagnostic(ErrorCode.ERR_NoSetToOverride, "Property1").WithArguments("Derived.Property1", "Base<int>.Property1"),
                // (11,38): error CS0545: 'Derived.Property2': cannot override because 'Base<int>.Property2' does not have an overridable get accessor
                Diagnostic(ErrorCode.ERR_NoGetToOverride, "Property2").WithArguments("Derived.Property2", "Base<int>.Property2"),
                // (8,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base<int>.Property1.set'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base<int>.Property1.set"),
                // (8,7): error CS0534: 'Derived' does not implement inherited abstract member 'Base<int>.Property2.get'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived").WithArguments("Derived", "Base<int>.Property2.get"));
        }
 
        [Fact]
        public void TestEmitSynthesizedSealedAccessorsInDifferentAssembly()
        {
            var source1 = @"
using System;
using System.Collections.Generic;
 
public class Base<T>
{
    public virtual List<T> Property1 { get; set; }
    public virtual List<T> Property2 { set { } get { return null; } }
}";
            var compilation1 = CreateCompilation(source1);
 
            var source2 = @"
using System.Collections.Generic;
 
class Derived : Base<int>
{
    public sealed override List<int> Property1 { get { return null; } }
    public sealed override List<int> Property2 { set { } }
}
class Derived2 : Derived
{
    public override List<int> Property1 { set { } }
    public override List<int> Property2 { get { return null; } }
}";
            var comp = CreateCompilation(source2, new[] { new CSharpCompilationReference(compilation1) });
            comp.VerifyDiagnostics(
                // (11,31): error CS0239: 'Derived2.Property1': cannot override inherited member 'Derived.Property1' because it is sealed
                Diagnostic(ErrorCode.ERR_CantOverrideSealed, "Property1").WithArguments("Derived2.Property1", "Derived.Property1"),
                // (12,31): error CS0239: 'Derived2.Property2': cannot override inherited member 'Derived.Property2' because it is sealed
                Diagnostic(ErrorCode.ERR_CantOverrideSealed, "Property2").WithArguments("Derived2.Property2", "Derived.Property2"));
        }
 
        [Fact]
        public void TestOverrideAndHide()
        {
            // Tests:
            // Sanity check - within the same type declare members that respectively hide and override
            // a base virtual / abstract member
 
            var source = @"
using System.Collections.Generic;
abstract class Base<T>
{
    public virtual void Method<U>(T x) { }
    public abstract int Property { set; }
}
class Derived : Base<List<int>>
{
    public override void Method<U>(List<int> x) { }
    public new void Method<U>(List<int> x) { }
    public override int Property { set { } }
    public new int Property { set{ } }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (11,21): error CS0111: Type 'Derived' already defines a member called 'Method' with the same parameter types
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method").WithArguments("Method", "Derived"),
                // (13,20): error CS0102: The type 'Derived' already contains a definition for 'Property'
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Property").WithArguments("Derived", "Property"));
        }
 
        [Fact]
        public void TestHidingByGenericArity()
        {
            // Tests:
            // Hide base virtual / abstract member with a nested type that has same name but different generic arity
            // Member should be available for overriding in further derived type
 
            var source = @"
using System.Collections.Generic;
class NS1
{
    abstract class Base<T>
    {
        public virtual void Method<U>(T x) { }
        public virtual int Property { set { } }
    }
    class Base2 : Base<List<int>>
    {
        new class Method { } // Warning: new not required
        new class Property { }
    }
    class Derived : Base2
    {
        public override void Method<U>(List<int> x) { }
        public override int Property { set { } }
    }
}
class NS2
{
    abstract class Base<T>
    {
        public virtual void Method<U>(T x) { }
        public virtual int Property { set { } }
    }
    class Base2 : Base<List<int>>
    {
        public class Method { }
        public new class Property { }
    }
    class Derived : Base2
    {
        public override void Method<U>(List<int> x) { }
        public override int Property { set { } } // Error: can't override a type
    }
}
class NS3
{
    abstract class Base<T>
    {
        public virtual void Method<U>(T x) { }
        public virtual int Property { set { } }
    }
    class Base2 : Base<List<int>>
    {
        public class Method<T> { } // Warning: new required
        public new class Property<T> { } // Warning: new not required
    }
    class Derived : Base2
    {
        public override void Method<U>(List<int> x) { } // Error: can't override a type
        public override int Property { set { } }
    }
}
class NS4
{
    abstract class Base<T>
    {
        public virtual void Method<U>(T x) { }
        public virtual int Property { set { } }
    }
    class Base2 : Base<List<int>>
    {
        public class Method<T, U> { }
        public class Property<T, U> { }
    }
    class Derived : Base2
    {
        public override void Method<U>(List<int> x) { }
        public override int Property { set { } }
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (12,19): warning CS0109: The member 'NS1.Base2.Method' does not hide an accessible member. The new keyword is not required.
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Method").WithArguments("NS1.Base2.Method"),
                // (35,30): error CS0505: 'NS2.Derived.Method<U>(System.Collections.Generic.List<int>)': cannot override because 'NS2.Base2.Method' is not a function
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Method").WithArguments("NS2.Derived.Method<U>(System.Collections.Generic.List<int>)", "NS2.Base2.Method"),
                // (36,29): error CS0544: 'NS2.Derived.Property': cannot override because 'NS2.Base2.Property' is not a property
                Diagnostic(ErrorCode.ERR_CantOverrideNonProperty, "Property").WithArguments("NS2.Derived.Property", "NS2.Base2.Property"),
                // (48,22): warning CS0108: 'NS3.Base2.Method<T>' hides inherited member 'NS3.Base<System.Collections.Generic.List<int>>.Method<U>(System.Collections.Generic.List<int>)'. Use the new keyword if hiding was intended.
                Diagnostic(ErrorCode.WRN_NewRequired, "Method").WithArguments("NS3.Base2.Method<T>", "NS3.Base<System.Collections.Generic.List<int>>.Method<U>(System.Collections.Generic.List<int>)"),
                // (49,26): warning CS0109: The member 'NS3.Base2.Property<T>' does not hide an accessible member. The new keyword is not required.
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Property").WithArguments("NS3.Base2.Property<T>"),
                // (53,30): error CS0505: 'NS3.Derived.Method<U>(System.Collections.Generic.List<int>)': cannot override because 'NS3.Base2.Method<T>' is not a function
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Method").WithArguments("NS3.Derived.Method<U>(System.Collections.Generic.List<int>)", "NS3.Base2.Method<T>"));
        }
 
        [WorkItem(540348, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540348")]
        [Fact]
        public void TestOverridingBrokenTypes()
        {
            var text = @"
using System.Collections.Generic;
 
partial class NS1
{
    abstract class Base<T>
    {
        public virtual void Method<U>(T x) { }
        public virtual int Property { set { } }
    }
    class Base2 : Base<List<int>>
    {
        public class Method<T> { }
        public new class Property<T> { }
    }
    class Derived : Base2
    {
        public override void Method<U>(List<int> x) { }
        public override int Property { set { } }
    }
}
partial class NS1
{
    abstract class Base<T>
    {
        public virtual void Method<U>(T x) { }
        public virtual int Property { set { } }
    }
    class Base2 : Base<List<int>>
    {
        public class Method<T, U> { }
        public class Property<T, U> { }
    }
    class Derived : Base2
    {
        public override void Method<U>(List<int> x) { }
        public override int Property { set { } }
    }
}";
 
            // TODO: Dev10 reports fewer cascading errors
            CreateCompilation(text).VerifyDiagnostics(
                // (24,20): error CS0102: The type 'NS1' already contains a definition for 'Base'
                //     abstract class Base<T>
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Base").WithArguments("NS1", "Base"),
                // (29,11): error CS0102: The type 'NS1' already contains a definition for 'Base2'
                //     class Base2 : Base<List<int>>
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Base2").WithArguments("NS1", "Base2"),
                // (34,11): error CS0102: The type 'NS1' already contains a definition for 'Derived'
                //     class Derived : Base2
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Derived").WithArguments("NS1", "Derived"),
                // (36,30): error CS0505: 'NS1.Derived.Method<U>(System.Collections.Generic.List<int>)': cannot override because 'NS1.Base2.Method<T>' is not a function
                //         public override void Method<U>(List<int> x) { }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Method").WithArguments("NS1.Derived.Method<U>(System.Collections.Generic.List<int>)", "NS1.Base2.Method<T>"),
                // (19,29): error CS0462: The inherited members 'NS1.Base<T>.Property' and 'NS1.Base<T>.Property' have the same signature in type 'NS1.Derived', so they cannot be overridden
                //         public override int Property { set { } }
                Diagnostic(ErrorCode.ERR_AmbigOverride, "Property").WithArguments("NS1.Base<T>.Property", "NS1.Base<T>.Property", "NS1.Derived"),
                // (37,29): error CS0462: The inherited members 'NS1.Base<T>.Property' and 'NS1.Base<T>.Property' have the same signature in type 'NS1.Derived', so they cannot be overridden
                //         public override int Property { set { } }
                Diagnostic(ErrorCode.ERR_AmbigOverride, "Property").WithArguments("NS1.Base<T>.Property", "NS1.Base<T>.Property", "NS1.Derived"),
                // (18,30): error CS0505: 'NS1.Derived.Method<U>(System.Collections.Generic.List<int>)': cannot override because 'NS1.Base2.Method<T>' is not a function
                //         public override void Method<U>(List<int> x) { }
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Method").WithArguments("NS1.Derived.Method<U>(System.Collections.Generic.List<int>)", "NS1.Base2.Method<T>"),
                // (36,30): error CS0111: Type 'NS1.Derived' already defines a member called 'Method' with the same parameter types
                //         public override void Method<U>(List<int> x) { }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method").WithArguments("Method", "NS1.Derived"),
                // (26,29): error CS0111: Type 'NS1.Base<T>' already defines a member called 'Method' with the same parameter types
                //         public virtual void Method<U>(T x) { }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method").WithArguments("Method", "NS1.Base<T>"),
                // (13,22): warning CS0108: 'NS1.Base2.Method<T>' hides inherited member 'NS1.Base<System.Collections.Generic.List<int>>.Method<U>(System.Collections.Generic.List<int>)'. Use the new keyword if hiding was intended.
                //         public class Method<T> { }
                Diagnostic(ErrorCode.WRN_NewRequired, "Method").WithArguments("NS1.Base2.Method<T>", "NS1.Base<System.Collections.Generic.List<int>>.Method<U>(System.Collections.Generic.List<int>)"),
                // (14,26): warning CS0109: The member 'NS1.Base2.Property<T>' does not hide an accessible member. The new keyword is not required.
                //         public new class Property<T> { }
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Property").WithArguments("NS1.Base2.Property<T>")
                );
        }
 
        [Fact]
        public void TestHidingErrorsForVirtualMembers()
        {
            // Tests:
            // Hide non-existent base virtual member
            // Hide same virtual member more than once
            // Hide virtual member without specifying new
            // Overload virtual member and also specify new
 
            var text = @"
class Base
{
    internal new virtual void Method() { }
    internal virtual int Property { set { } }
}
partial class Derived : Base
{
    public virtual void Method() { }
    public new virtual int Property { set { } }
}
partial class Derived
{
    internal new virtual int Property { set { } }
    protected new virtual void Method<T>() { }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (4,31): warning CS0109: The member 'Base.Method()' does not hide an accessible member. The new keyword is not required.
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Method").WithArguments("Base.Method()"),
                // (14,30): error CS0102: The type 'Derived' already contains a definition for 'Property'
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Property").WithArguments("Derived", "Property"),
                // (9,25): warning CS0114: 'Derived.Method()' hides inherited member 'Base.Method()'. To make the current member override that implementation, add the override keyword. Otherwise add the new keyword.
                Diagnostic(ErrorCode.WRN_NewOrOverrideExpected, "Method").WithArguments("Derived.Method()", "Base.Method()"),
                // (15,32): warning CS0109: The member 'Derived.Method<T>()' does not hide an accessible member. The new keyword is not required.
                Diagnostic(ErrorCode.WRN_NewNotRequired, "Method").WithArguments("Derived.Method<T>()"));
        }
 
        [Fact]
        public void TestHidingErrorLocations()
        {
            var text = @"
class Base
{
    public virtual void Method() { }
    public virtual int Property { set { } }
    protected class Type { }
    internal int Field = 1;
}
 
class Derived : Base
{
    public new int MethOd = 2, Method = 3, METhod = 4;
    void Test()
    {
        long x = MethOd = Method = METhod;
    }
    class Base2 : Base
    {
        private long Type = 5, method = 2, Field = 2,
                        field = 8, Property = 3;
        void Test()
        {
            long x = Type = method = Field = field = Property;
        }
    }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (12,20): warning CS0109: The member 'Derived.MethOd' does not hide an accessible member. The new keyword is not required.
                //     public new int MethOd = 2, Method = 3, METhod = 4;
                Diagnostic(ErrorCode.WRN_NewNotRequired, "MethOd").WithArguments("Derived.MethOd"),
                // (12,44): warning CS0109: The member 'Derived.METhod' does not hide an accessible member. The new keyword is not required.
                //     public new int MethOd = 2, Method = 3, METhod = 4;
                Diagnostic(ErrorCode.WRN_NewNotRequired, "METhod").WithArguments("Derived.METhod"),
                // (19,22): warning CS0108: 'Derived.Base2.Type' hides inherited member 'Base.Type'. Use the new keyword if hiding was intended.
                //         private long Type = 5, method = 2, Field = 2,
                Diagnostic(ErrorCode.WRN_NewRequired, "Type").WithArguments("Derived.Base2.Type", "Base.Type"),
                // (19,44): warning CS0108: 'Derived.Base2.Field' hides inherited member 'Base.Field'. Use the new keyword if hiding was intended.
                //         private long Type = 5, method = 2, Field = 2,
                Diagnostic(ErrorCode.WRN_NewRequired, "Field").WithArguments("Derived.Base2.Field", "Base.Field"),
                // (20,36): warning CS0108: 'Derived.Base2.Property' hides inherited member 'Base.Property'. Use the new keyword if hiding was intended.
                //                         field = 8, Property = 3;
                Diagnostic(ErrorCode.WRN_NewRequired, "Property").WithArguments("Derived.Base2.Property", "Base.Property")
            );
        }
 
        [Fact]
        public void ImplementInterfaceUsingSealedProperty()
        {
            var text = @"
interface I1
{
    int Bar { get; }
}
class C1
{
    public virtual int Bar { get { return 0;} set { }}
}
 
class C2 : C1, I1
{
    sealed public override int Bar { get; set; }
}
";
            DiagnosticsUtils.VerifyErrorsAndGetCompilationWithMscorlib(text);
        }
 
        [Fact]
        public void ImplementInterfaceUsingSealedEvent()
        {
            var text = @"
interface I1
{
    event System.Action E;
}
class C1
{
    public virtual event System.Action E;
 
    void UseEvent() { E(); }
}
 
class C2 : C1, I1
{
    public sealed override event System.Action E;
 
    void UseEvent() { E(); }
}
";
            DiagnosticsUtils.VerifyErrorsAndGetCompilationWithMscorlib(text);
        }
 
        [Fact]
        public void ImplementInterfaceUsingNonVirtualEvent()
        {
            var text = @"
interface I
{
    event System.Action E;
    event System.Action F;
    event System.Action G;
}
class C : I
{
    event System.Action I.E { add { } remove { } }
    public event System.Action F { add { } remove { } }
    public event System.Action G;
}
";
 
            var compilation = CreateCompilation(text);
 
            // This also forces computation of IsMetadataVirtual.
            compilation.VerifyDiagnostics(
                // (12,32): warning CS0067: The event 'C.G' is never used
                //     public event System.Action G;
                Diagnostic(ErrorCode.WRN_UnreferencedEvent, "G").WithArguments("C.G"));
 
            const int numEvents = 3;
 
            var @interface = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("I");
            var interfaceEvents = new EventSymbol[numEvents];
            interfaceEvents[0] = @interface.GetMember<EventSymbol>("E");
            interfaceEvents[1] = @interface.GetMember<EventSymbol>("F");
            interfaceEvents[2] = @interface.GetMember<EventSymbol>("G");
 
            var @class = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C");
            var classEvents = new EventSymbol[numEvents];
            classEvents[0] = @class.GetEvent("I.E");
            classEvents[1] = @class.GetMember<EventSymbol>("F");
            classEvents[2] = @class.GetMember<EventSymbol>("G");
 
            for (int i = 0; i < numEvents; i++)
            {
                var classEvent = classEvents[i];
                var interfaceEvent = interfaceEvents[i];
 
                Assert.Equal(classEvent, @class.FindImplementationForInterfaceMember(interfaceEvent));
 
                Assert.Equal(classEvent.AddMethod, @class.FindImplementationForInterfaceMember(interfaceEvent.AddMethod));
                Assert.Equal(classEvent.RemoveMethod, @class.FindImplementationForInterfaceMember(interfaceEvent.RemoveMethod));
 
                Assert.True(classEvent.AddMethod.IsMetadataVirtual());
                Assert.True(classEvent.RemoveMethod.IsMetadataVirtual());
            }
        }
 
        [Fact]
        public void TestPrivateMemberHidesVirtualMember()
        {
            var text = @"
abstract public class Class1
{
    public virtual void Member1() { }
    abstract class Class2 : Class1
    {
        new private double[] Member1 = new double[] { };
        abstract class Class3 : Class2
        {
            public override void Member1() { base.Member1(); } // Error
        }
    }
    abstract class Class4 : Class2
    {
        public override void Member1() { base.Member1(); } // OK
    }
}";
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_CantOverrideNonFunction, "Member1").WithArguments("Class1.Class2.Class3.Member1()", "Class1.Class2.Member1"));
        }
 
        [Fact]
        public void ImplicitMultipleInterfaceInGrandChild()
        {
            var text = @"
interface I1
{
    void Bar();
}
interface I2
{
    void Bar();
}
class C1 : I1
{
    public void Bar() { }
}
class C2 : C1, I1, I2
{
    public new void Bar() { }
}
";
            var comp = CreateCompilation(text);
            var c2Type = comp.Assembly.Modules[0].GlobalNamespace.GetTypeMembers("C2").Single();
            comp.VerifyDiagnostics(DiagnosticDescription.None);
            Assert.True(c2Type.Interfaces().All(iface => iface.Name == "I1" || iface.Name == "I2"));
        }
        [WorkItem(540451, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540451")]
        [Fact]
        public void TestImplicitImplSignatureMismatches()
        {
            // Tests: 
            // Mismatching ref / out in signature of implemented member
 
            var source = @"
using System.Collections.Generic;
interface I1<T>
{
    void Method(int a, long b = 2, string c = null, params List<T>[] d);
}
 
interface I2 : I1<string>
{
    void Method<T>(out int a, ref T[] b, List<T>[] c);
}
 
class Base
{
    public void Method(int a, long b = 2, string c = null, params List<string>[] d) { }
    // Toggle ref, out - CS0535
    public void Method<U>(ref int a, out U[] b, List<U>[] c) { b = null; }
}
 
class Derived : Base, I2 // Implicit implementation in base
{
}
 
class Class : I2 // Implicit implementation
{
    public void Method(int a, long b = 2, string c = null, params List<string>[] d) { }
    // Omit ref, out - CS0535
    public void Method<U>(int a, U[] b, List<U>[] c) { b = null; }
}
 
class Class2 : I2 // Implicit implementation
{
    // Additional ref - CS0535
    public void Method(ref int a, long b = 3, string c = null, params List<string>[] d) { }
    // Additional out - CS0535
    public void Method<U>(ref int a, out U[] b, out List<U>[] c) { b = null; c = null; }
}";
            CreateCompilation(source).VerifyDiagnostics(
                // (21,7): error CS0535: 'Derived' does not implement interface member 'I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Derived", "I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])"),
                // (24,7): error CS0535: 'Class' does not implement interface member 'I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Class", "I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])"),
                // (31,7): error CS0535: 'Class2' does not implement interface member 'I1<string>.Method(int, long, string, params System.Collections.Generic.List<string>[])'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Class2", "I1<string>.Method(int, long, string, params System.Collections.Generic.List<string>[])"),
                // (31,7): error CS0535: 'Class2' does not implement interface member 'I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Class2", "I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])"));
        }
 
        [Fact]
        public void TestExplicitImplSignatureMismatches()
        {
            // Tests: 
            // Mismatching ref / out in signature of implemented member
 
            var source = @"
using System.Collections.Generic;
interface I1<T>
{
    void Method(int a, long b = 2, string c = null, params List<T>[] d);
}
 
interface I2 : I1<string>
{
    void Method<T>(out int a, ref T[] b, List<T>[] c);
}
 
class Class1 : I1<string>, I2
{
    void I1<string>.Method(int a, long b = 2, string c = null, params List<string>[] d) { }
    // Toggle ref, out - CS0535
    void I2.Method<U>(ref int a, out U[] b, List<U>[] c) { b = null; }
}
 
class Class : I2
{
    void I1<string>.Method(int a, long b = 2, string c = null, params List<string>[] d) { }
    // Omit ref, out - CS0535
    void I2.Method<U>(int a, U[] b, List<U>[] c) { b = null; }
}
 
class Class2 : I2, I1<string>
{
    // Additional ref - CS0535
    void I1<string>.Method(ref int a, long b = 3, string c = null, params List<string>[] d) { }
    // Additional out - CS0535
    void I2.Method<U>(ref int a, out U[] b, out List<U>[] c) { b = null; c = null; }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (24,13): error CS0539: 'Class.Method<U>(int, U[], System.Collections.Generic.List<U>[])' in explicit interface declaration is not a member of interface
                //     void I2.Method<U>(int a, U[] b, List<U>[] c) { b = null; }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class.Method<U>(int, U[], System.Collections.Generic.List<U>[])"),
                // (17,13): error CS0539: 'Class1.Method<U>(ref int, out U[], System.Collections.Generic.List<U>[])' in explicit interface declaration is not a member of interface
                //     void I2.Method<U>(ref int a, out U[] b, List<U>[] c) { b = null; }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class1.Method<U>(ref int, out U[], System.Collections.Generic.List<U>[])"),
                // (20,15): error CS0535: 'Class' does not implement interface member 'I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])'
                // class Class : I2
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Class", "I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])"),
                // (13,28): error CS0535: 'Class1' does not implement interface member 'I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])'
                // class Class1 : I1<string>, I2
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Class1", "I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])"),
                // (22,40): warning CS1066: The default value specified for parameter 'b' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1<string>.Method(int a, long b = 2, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "b").WithArguments("b"),
                // (15,40): warning CS1066: The default value specified for parameter 'b' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1<string>.Method(int a, long b = 2, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "b").WithArguments("b"),
                // (22,54): warning CS1066: The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1<string>.Method(int a, long b = 2, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "c").WithArguments("c"),
                // (15,54): warning CS1066: The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1<string>.Method(int a, long b = 2, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "c").WithArguments("c"),
                // (32,13): error CS0539: 'Class2.Method<U>(ref int, out U[], out System.Collections.Generic.List<U>[])' in explicit interface declaration is not a member of interface
                //     void I2.Method<U>(ref int a, out U[] b, out List<U>[] c) { b = null; c = null; }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class2.Method<U>(ref int, out U[], out System.Collections.Generic.List<U>[])"),
                // (30,21): error CS0539: 'Class2.Method(ref int, long, string, params System.Collections.Generic.List<string>[])' in explicit interface declaration is not a member of interface
                //     void I1<string>.Method(ref int a, long b = 3, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class2.Method(ref int, long, string, params System.Collections.Generic.List<string>[])"),
                // (27,16): error CS0535: 'Class2' does not implement interface member 'I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])'
                // class Class2 : I2, I1<string>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I2").WithArguments("Class2", "I2.Method<T>(out int, ref T[], System.Collections.Generic.List<T>[])"),
                // (27,20): error CS0535: 'Class2' does not implement interface member 'I1<string>.Method(int, long, string, params System.Collections.Generic.List<string>[])'
                // class Class2 : I2, I1<string>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1<string>").WithArguments("Class2", "I1<string>.Method(int, long, string, params System.Collections.Generic.List<string>[])"),
                // (30,44): warning CS1066: The default value specified for parameter 'b' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1<string>.Method(ref int a, long b = 3, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "b").WithArguments("b"),
                // (30,58): warning CS1066: The default value specified for parameter 'c' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1<string>.Method(ref int a, long b = 3, string c = null, params List<string>[] d) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "c").WithArguments("c"));
        }
 
        [Fact]
        public void TestImplicitImplSignatureMismatches2()
        {
            // Tests:
            // Change return type of implemented member
            // Change parameter types of implemented member
            // Change number / order of generic method type parameters in implemented method
 
            //UNDONE: type constraint mismatch
 
            var text = @"
interface Interface
{
    void Method<T>(long l, int i);
}
 
interface Interface2
{
    void Method<T, U, V>(T l, U i, V z);
}
 
interface Interface3
{
    int Property {set;}
}
 
class Class1 : Interface
{
    public void Method<T, U>(long l, int i) { } //wrong arity
}
 
class Base2
{
    public void Method(long l, int i) { } //wrong arity
}
class Class2 : Base2, Interface { }
 
class Base3
{
    public void Method<V, T, U>(T l, U i, V z) { } //wrong order
}
class Base31 : Base3 { }
class Class3 : Base31, Interface2 { }
 
class Class4 : Interface
{
    public int Method<T>(long l, int i) { return 0; } //wrong return type
}
class Class41 : Interface3
{
    public long Property { set { } } //wrong return type
}
 
class Class5 : Interface
{
    public void Method1<T>(long l, int i) { } //wrong name
}
 
class Class6 : Interface
{
    public void Method<T>(long l) { } //wrong parameter count
}
 
class Base7
{
    public void Method<T>(int i, long l) { } //wrong parameter types
}
class Class7 : Base7, Interface
{
}
";
            CreateCompilation(text).VerifyDiagnostics(
                // (17,16): error CS0535: 'Class1' does not implement interface member 'Interface.Method<T>(long, int)'
                // class Class1 : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class1", "Interface.Method<T>(long, int)").WithLocation(17, 16),
                // (26,23): error CS0535: 'Class2' does not implement interface member 'Interface.Method<T>(long, int)'
                // class Class2 : Base2, Interface { }
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class2", "Interface.Method<T>(long, int)").WithLocation(26, 23),
                // (33,24): error CS0535: 'Class3' does not implement interface member 'Interface2.Method<T, U, V>(T, U, V)'
                // class Class3 : Base31, Interface2 { }
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface2").WithArguments("Class3", "Interface2.Method<T, U, V>(T, U, V)").WithLocation(33, 24),
                // (58,23): error CS0535: 'Class7' does not implement interface member 'Interface.Method<T>(long, int)'
                // class Class7 : Base7, Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class7", "Interface.Method<T>(long, int)").WithLocation(58, 23),
                // (49,16): error CS0535: 'Class6' does not implement interface member 'Interface.Method<T>(long, int)'
                // class Class6 : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class6", "Interface.Method<T>(long, int)").WithLocation(49, 16),
                // (35,16): error CS0738: 'Class4' does not implement interface member 'Interface.Method<T>(long, int)'. 'Class4.Method<T>(long, int)' cannot implement 'Interface.Method<T>(long, int)' because it does not have the matching return type of 'void'.
                // class Class4 : Interface
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface").WithArguments("Class4", "Interface.Method<T>(long, int)", "Class4.Method<T>(long, int)", "void").WithLocation(35, 16),
                // (39,17): error CS0738: 'Class41' does not implement interface member 'Interface3.Property'. 'Class41.Property' cannot implement 'Interface3.Property' because it does not have the matching return type of 'int'.
                // class Class41 : Interface3
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Interface3").WithArguments("Class41", "Interface3.Property", "Class41.Property", "int").WithLocation(39, 17),
                // (44,16): error CS0535: 'Class5' does not implement interface member 'Interface.Method<T>(long, int)'
                // class Class5 : Interface
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class5", "Interface.Method<T>(long, int)").WithLocation(44, 16));
        }
 
        [WorkItem(540470, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/540470")]
        [Fact]
        public void TestExplicitImplSignatureMismatches2()
        {
            // Tests:
            // Change return type of implemented member
            // Change parameter types of implemented member
            // Change number / order of generic method type parameters in implemented method
 
            //UNDONE: type constraint mismatch
 
            var text = @"
interface Interface
{
    void Method<T>(long l, int i);
}
 
interface Interface2
{
    void Method<T, U, V>(T l, U i, V z);
}
 
interface Interface3
{
    int Property {set;}
}
 
class Class1 : Interface
{
    void Interface.Method<T, U>(long l, int i) { } //wrong arity
}
 
class Class2 : Interface
{
    void Interface.Method(long l, int i) { } //wrong arity
}
 
class Class3 : Interface2
{
    void Interface2.Method<V, T, U>(T l, U i, V z) { } //wrong order
}
 
class Class4 : Interface
{
    int Interface.Method<T>(long l, int i) { return 0; } //wrong return type
}
class Class41 : Interface3
{
    long Interface3.Property { set { } } //wrong return type
}
 
class Class5 : Interface
{
    void Interface.Method1<T>(long l, int i) { } //wrong name
}
 
class Class51 : Interface
{
    void INterface.Method<T>(long l, int i) { } //wrong name
}
 
class Class52 : Interface, Interface2
{
    void Interface.Method<T, U, V>(T l, U i, V z) { } //wrong name
}
 
class Class6 : Interface
{
    void Interface.Method<T>(long l) { } //wrong parameter count
}
 
class Class7 : Interface
{
    void Interface.Method<T>(int i, long l) { } //wrong parameter types
}
";
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "INterface").WithArguments("INterface"),
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "INterface").WithArguments("INterface"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class1.Method<T, U>(long, int)"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class4.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class51", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class1", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class4", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property").WithArguments("Class41.Property"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class2.Method(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class2", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface3").WithArguments("Class41", "Interface3.Property"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class52.Method<T, U, V>(T, U, V)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class52", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface2").WithArguments("Class52", "Interface2.Method<T, U, V>(T, U, V)"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class7.Method<T>(int, long)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class7", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method1").WithArguments("Class5.Method1<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class3.Method<V, T, U>(T, U, V)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class5", "Interface.Method<T>(long, int)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface2").WithArguments("Class3", "Interface2.Method<T, U, V>(T, U, V)"),
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Class6.Method<T>(long)"),
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Class6", "Interface.Method<T>(long, int)"));
        }
 
        [Fact]
        public void TestDuplicateImplicitImpl()
        {
            // Tests:
            // Implement same interface member more than once in different parts of a partial type
 
            var text = @"
using System.Collections.Generic;
interface I1
{
    int Property { set; }
}
abstract partial class Class : I2, I1
{
    abstract public int Property { set; }
    abstract public void Method<U>(int a, ref U[] b, out List<U> c);
}
interface I2 : I1
{
    void Method<T>(int a, ref T[] b, out List<T> c);
}
abstract partial class Class : I3
{
    abstract public int Property { get; set; }
    abstract public void Method<T>(int a, ref T[] b, out List<T> c);
    abstract public void Method(int a = 3, params System.Exception[] b);
}
abstract partial class Base
{
    abstract public int Property { set; }
    abstract public void Method<U>(int a, ref U[] b, out List<U> c);
}
interface I3 : I2
{
    void Method(int a = 3, params System.Exception[] b);
}
abstract partial class Base
{
    abstract public int Property { get; set; }
    abstract public void Method<T>(int a, ref T[] b, out List<T> c);
    abstract public void Method(int a = 3, params System.Exception[] b);
}
abstract class Derived : Base, I3, I1
{
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (18,25): error CS0102: The type 'Class' already contains a definition for 'Property'
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Property").WithArguments("Class", "Property"),
                // (19,26): error CS0111: Type 'Class' already defines a member called 'Method' with the same parameter types
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method").WithArguments("Method", "Class"),
                // (33,25): error CS0102: The type 'Base' already contains a definition for 'Property'
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Property").WithArguments("Base", "Property"),
                // (34,26): error CS0111: Type 'Base' already defines a member called 'Method' with the same parameter types
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method").WithArguments("Method", "Base"));
        }
 
        [Fact]
        public void TestDuplicateExplicitImpl()
        {
            // Tests:
            // Implement same interface member more than once in different parts of a partial type
 
            var text = @"
using System.Collections.Generic;
using Type = System.Int32;
interface I1
{
    int Property { set; }
}
abstract partial class Class : I2, I1
{
    int I1.Property { set { } }
    void I2.Method<U>(int a, ref U[] b, out List<U> c) { c = null;  }
}
interface I3 : I2
{
    void Method(int a = 3, params System.Exception[] b);
}
interface I2 : I1
{
    void Method<T>(int a, ref T[] b, out List<T> c);
}
abstract partial class Class : I3
{
    Type I1.Property { set { } }
    void I2.Method<T>(int a, ref T[] b, out List<T> c) { c = null; }
    void I3.Method(int a = 3, params System.Exception[] b) { }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (8,24): error CS8646: 'I2.Method<T>(int, ref T[], out List<T>)' is explicitly implemented more than once.
                // abstract partial class Class : I2, I1
                Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "Class").WithArguments("I2.Method<T>(int, ref T[], out System.Collections.Generic.List<T>)").WithLocation(8, 24),
                // (8,24): error CS8646: 'I1.Property' is explicitly implemented more than once.
                // abstract partial class Class : I2, I1
                Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "Class").WithArguments("I1.Property").WithLocation(8, 24),
                // (25,24): warning CS1066: The default value specified for parameter 'a' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I3.Method(int a = 3, params System.Exception[] b) { }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "a").WithArguments("a"),
                // (23,13): error CS0102: The type 'Class' already contains a definition for 'I1.Property'
                //     Type I1.Property { set { } }
                Diagnostic(ErrorCode.ERR_DuplicateNameInClass, "Property").WithArguments("Class", "I1.Property"),
                // (24,13): error CS0111: Type 'Class' already defines a member called 'I2.Method' with the same parameter types
                //     void I2.Method<T>(int a, ref T[] b, out List<T> c) { c = null; }
                Diagnostic(ErrorCode.ERR_MemberAlreadyExists, "Method").WithArguments("I2.Method", "Class"));
        }
 
        [Fact]
        public void TestMissingImpl()
        {
            // Tests:
            // For partial interfaces – test that compiler generates error if any interface methods have not been implemented
            // Test that compiler generates error if any interface methods have not been implemented in an abstract class
 
            var text = @"
using System.Collections.Generic;
partial interface I1
{
    int Property { set; }
}
abstract partial class Class : I1
{
    int I1.Property { set { } }
    abstract public void Method<U>(int a, ref U[] b, out List<U> c);
}
partial interface I1
{
    void Method<T>(int a, ref T[] b, out List<T> c);
}
abstract partial class Class : I1
{
    void Method(int a = 3, params System.ArgumentException[] b) { } // incorrect parameter type
}
abstract class Base
{
    abstract public void Method(int a = 3, params System.Exception[] b);
    long Property { set { } } // incorrect return type
}
abstract class Base2 : Base
{
}
partial interface I1
{
    void Method(int a = 3, params System.Exception[] b);
}
abstract class Derived : Base2, I1
{
    void I1.Method<T>(int a, ref T[] b, out List<T> c) { c = null; }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (7,32): error CS0535: 'Class' does not implement interface member 'I1.Method(int, params System.Exception[])'
                // abstract partial class Class : I1
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I1").WithArguments("Class", "I1.Method(int, params System.Exception[])").WithLocation(7, 32),
                // (32,33): error CS0737: 'Derived' does not implement interface member 'I1.Property'. 'Base.Property' cannot implement an interface member because it is not public.
                // abstract class Derived : Base2, I1
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "I1").WithArguments("Derived", "I1.Property", "Base.Property").WithLocation(32, 33));
        }
 
        [Fact]
        public void TestInterfaceBaseAccessError()
        {
            // Tests:
            // Invoke base.InterfaceMember from within class that only inherits an interface
 
            var text = @"
using System.Collections.Generic;
partial interface I1
{
    int Property { set; }
    void Method<T>(int a, ref T[] b, out List<T> c);
    void Method(int a = 3, params System.Exception[] b);
}
class Class1 : I1
{
    public int Property { set { base.Property = value; } }
    public void Method<T>(int a, ref T[] b, out List<T> c) { c = null; base.Method<T>(a, b, c); }
    public void Method(int a = 3, params System.Exception[] b) { base.Method(a, b); }
}
class Class2 : I1
{
    int I1.Property { set { base.Property = value; } }
    void I1.Method<T>(int a, ref T[] b, out List<T> c) { c = null; base.Method<T>(a, b, c); }
    void I1.Method(int a = 3, params System.Exception[] b) { base.Method(a, b); }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (19,24): warning CS1066: The default value specified for parameter 'a' will have no effect because it applies to a member that is used in contexts that do not allow optional arguments
                //     void I1.Method(int a = 3, params System.Exception[] b) { base.Method(a, b); }
                Diagnostic(ErrorCode.WRN_DefaultValueForUnconsumedLocation, "a").WithArguments("a"),
                // (11,38): error CS0117: 'object' does not contain a definition for 'Property'
                //     public int Property { set { base.Property = value; } }
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Property").WithArguments("object", "Property"),
                // (12,77): error CS0117: 'object' does not contain a definition for 'Method'
                //     public void Method<T>(int a, ref T[] b, out List<T> c) { c = null; base.Method<T>(a, b, c); }
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Method<T>").WithArguments("object", "Method"),
                // (13,71): error CS0117: 'object' does not contain a definition for 'Method'
                //     public void Method(int a = 3, params System.Exception[] b) { base.Method(a, b); }
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Method").WithArguments("object", "Method"),
                // (17,34): error CS0117: 'object' does not contain a definition for 'Property'
                //     int I1.Property { set { base.Property = value; } }
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Property").WithArguments("object", "Property"),
                // (18,73): error CS0117: 'object' does not contain a definition for 'Method'
                //     void I1.Method<T>(int a, ref T[] b, out List<T> c) { c = null; base.Method<T>(a, b, c); }
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Method<T>").WithArguments("object", "Method"),
                // (19,67): error CS0117: 'object' does not contain a definition for 'Method'
                //     void I1.Method(int a = 3, params System.Exception[] b) { base.Method(a, b); }
                Diagnostic(ErrorCode.ERR_NoSuchMember, "Method").WithArguments("object", "Method"));
        }
 
        [Fact]
        public void TestErrorsImplementingGenericNestedInterfaces_Implicit()
        {
            // Tests:
            // In signature / name of implicitly implemented member, use generic type whose open type (C<T>) matches signature
            // in base interface - but the closed type (C<string> / C<U>) does not match
 
            var text = @"
using System.Collections.Generic;
class Outer<T>
{
    internal class Inner<U>
    {
        protected internal interface Interface<V, W>
        {
            T Property { set; }
            void Method<K>(T a, U[] b, List<V> c, Interface<W, K> d);
        }
 
        internal class Base<X, Y>
        {
            public Y Property
            {
                set { }
            }
            public void Method<V>(X A, int[] b, List<long> C, Outer<Y>.Inner<int>.Interface<Y, V> d)
            {
            }
        }
    }
}
internal class Derived1<U, T> : Outer<U>.Inner<T>.Base<U, T>, Outer<U>.Inner<int>.Interface<long, T>
{
    public class Derived2<T> : Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<long, List<int>>
    {
        public List<List<uint>> Property
        {
            get { return null; }
            set { }
        }
        public void Method<K>(List<List<int>> A, List<List<T>>[] B, List<long> C, Outer<List<List<long>>>.Inner<List<List<T>>>.Interface<List<int>, K> D)
        {
        }
        public void Method<T>(List<List<int>> A, List<List<T>>[] B, List<long> C, Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<List<int>, T> D)
        {
        }
    }
}
public class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (25,63): error CS0535: 'Derived1<U, T>' does not implement interface member 'Outer<U>.Inner<int>.Interface<long, T>.Method<K>(U, int[], System.Collections.Generic.List<long>, Outer<U>.Inner<int>.Interface<T, K>)'
                // internal class Derived1<U, T> : Outer<U>.Inner<T>.Base<U, T>, Outer<U>.Inner<int>.Interface<long, T>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<U>.Inner<int>.Interface<long, T>").WithArguments("Derived1<U, T>", "Outer<U>.Inner<int>.Interface<long, T>.Method<K>(U, int[], System.Collections.Generic.List<long>, Outer<U>.Inner<int>.Interface<T, K>)").WithLocation(25, 63),
                // (25,63): error CS0738: 'Derived1<U, T>' does not implement interface member 'Outer<U>.Inner<int>.Interface<long, T>.Property'. 'Outer<U>.Inner<T>.Base<U, T>.Property' cannot implement 'Outer<U>.Inner<int>.Interface<long, T>.Property' because it does not have the matching return type of 'U'.
                // internal class Derived1<U, T> : Outer<U>.Inner<T>.Base<U, T>, Outer<U>.Inner<int>.Interface<long, T>
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Outer<U>.Inner<int>.Interface<long, T>").WithArguments("Derived1<U, T>", "Outer<U>.Inner<int>.Interface<long, T>.Property", "Outer<U>.Inner<T>.Base<U, T>.Property", "U").WithLocation(25, 63),
                // (27,27): warning CS0693: Type parameter 'T' has the same name as the type parameter from outer type 'Derived1<U, T>'
                //     public class Derived2<T> : Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<long, List<int>>
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "T").WithArguments("T", "Derived1<U, T>").WithLocation(27, 27),
                // (37,28): warning CS0693: Type parameter 'T' has the same name as the type parameter from outer type 'Derived1<U, T>'
                //         public void Method<T>(List<List<int>> A, List<List<T>>[] B, List<long> C, Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<List<int>, T> D)
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "T").WithArguments("T", "Derived1<U, T>").WithLocation(37, 28),
                // (27,32): error CS0535: 'Derived1<U, T>.Derived2<T>' does not implement interface member 'Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<long, System.Collections.Generic.List<int>>.Method<K>(System.Collections.Generic.List<System.Collections.Generic.List<int>>, System.Collections.Generic.List<System.Collections.Generic.List<T>>[], System.Collections.Generic.List<long>, Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<System.Collections.Generic.List<int>, K>)'
                //     public class Derived2<T> : Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<long, List<int>>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<long, List<int>>").WithArguments("Derived1<U, T>.Derived2<T>", "Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<long, System.Collections.Generic.List<int>>.Method<K>(System.Collections.Generic.List<System.Collections.Generic.List<int>>, System.Collections.Generic.List<System.Collections.Generic.List<T>>[], System.Collections.Generic.List<long>, Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<System.Collections.Generic.List<int>, K>)").WithLocation(27, 32),
                // (27,32): error CS0738: 'Derived1<U, T>.Derived2<T>' does not implement interface member 'Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<long, System.Collections.Generic.List<int>>.Property'. 'Derived1<U, T>.Derived2<T>.Property' cannot implement 'Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<long, System.Collections.Generic.List<int>>.Property' because it does not have the matching return type of 'System.Collections.Generic.List<System.Collections.Generic.List<int>>'.
                //     public class Derived2<T> : Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<long, List<int>>
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "Outer<List<List<int>>>.Inner<List<List<T>>>.Interface<long, List<int>>").WithArguments("Derived1<U, T>.Derived2<T>", "Outer<System.Collections.Generic.List<System.Collections.Generic.List<int>>>.Inner<System.Collections.Generic.List<System.Collections.Generic.List<T>>>.Interface<long, System.Collections.Generic.List<int>>.Property", "Derived1<U, T>.Derived2<T>.Property", "System.Collections.Generic.List<System.Collections.Generic.List<int>>").WithLocation(27, 32));
        }
 
        [Fact]
        public void TestErrorsImplementingGenericNestedInterfaces_Explicit()
        {
            // Tests:
            // In signature / name of explicitly implemented member, use generic type whose open type (C<T>) matches signature
            // in base interface - but the closed type (C<string> / C<U>) does not match
 
            var text = @"
using System.Collections.Generic;
class Outer<T>
{
    internal class Inner<U>
    {
        protected internal interface Interface<V, W>
        {
            T Property { set; }
            void Method<Z>(T a, U[] b, List<V> c, Dictionary<W, Z> d);
        }
        internal class Derived1 : Inner<int>.Interface<ulong, string>
        {
            T Outer<T>.Inner<int>.Interface<long, string>.Property
            {
                set { }
            }
            void Inner<int>.Interface<long, string>.Method<K>(T A, int[] B, List<long> c, Dictionary<string, K> D)
            {
            }
            internal class Derived2<X, Y> : Outer<Y>.Inner<int>.Interface<long, X>
            {
                X Outer<X>.Inner<int>.Interface<long, Y>.Property
                {
                    set { }
                }
                void Outer<X>.Inner<int>.Interface<long, Y>.Method<K>(X A, int[] b, List<long> C, Dictionary<Y, K> d)
                {
                }
            }
        }
        internal class Derived3 : Interface<long, string>
        {
            U Inner<U>.Interface<long, string>.Property
            {
                set { }
            }
            void Outer<T>.Inner<U>.Interface<long, string>.Method<K>(T a, K[] B, List<long> C, Dictionary<string, K> d)
            {
            }
        }
        internal class Derived4 : Outer<U>.Inner<T>.Interface<T, U>
        {
            U Outer<U>.Inner<T>.Interface<T, U>.Property
            {
                set { }
            }
            void Outer<U>.Inner<T>.Interface<T, U>.Method<K>(U a, T[] b, List<U> C, Dictionary<U, K> d)
            {
            }
            internal class Derived5 : Outer<T>.Inner<U>.Interface<U, T>
            {
                T Outer<T>.Inner<U>.Interface<U, T>.Property
                {
                    set { }
                }
                void Inner<U>.Interface<U, T>.Method<K>(T a, U[] b, List<U> c, Dictionary<K, T> D)
                {
                }
                internal class Derived6<@u> : Outer<List<T>>.Inner<U>.Interface<List<u>, T>
                {
                    List<T> Outer<List<T>>.Inner<U>.Interface<List<U>, T>.Property
                    {
                        set { }
                    }
                    void Outer<List<T>>.Inner<U>.Interface<List<U>, T>.Method<K>(List<T> AA, U[] b, List<List<U>> c, Dictionary<T, K> d)
                    {
                    }
                }
                internal class Derived7<@u> : Outer<List<T>>.Inner<U>.Interface<List<U>, T>
                {
                    List<u> Outer<List<T>>.Inner<U>.Interface<List<U>, T>.Property
                    {
                        set { }
                    }
                    void Outer<List<T>>.Inner<U>.Interface<List<U>, T>.Method<K>(List<T> AA, U[] b, List<List<u>> c, Dictionary<T, K> d)
                    {
                    }
                }
            }
        }
    }
}
class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (48,52): error CS0539: 'Outer<T>.Inner<U>.Derived4.Method<K>(U, T[], System.Collections.Generic.List<U>, System.Collections.Generic.Dictionary<U, K>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived4.Method<K>(U, T[], System.Collections.Generic.List<U>, System.Collections.Generic.Dictionary<U, K>)"),
                // (42,35): error CS0535: 'Outer<T>.Inner<U>.Derived4' does not implement interface member 'Outer<U>.Inner<T>.Interface<T, U>.Method<Z>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<U>.Inner<T>.Interface<T, U>").WithArguments("Outer<T>.Inner<U>.Derived4", "Outer<U>.Inner<T>.Interface<T, U>.Method<Z>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, Z>)"),
                // (57,47): error CS0539: 'Outer<T>.Inner<U>.Derived4.Derived5.Method<K>(T, U[], System.Collections.Generic.List<U>, System.Collections.Generic.Dictionary<K, T>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Method<K>(T, U[], System.Collections.Generic.List<U>, System.Collections.Generic.Dictionary<K, T>)"),
                // (51,39): error CS0535: 'Outer<T>.Inner<U>.Derived4.Derived5' does not implement interface member 'Outer<T>.Inner<U>.Interface<U, T>.Method<Z>(T, U[], System.Collections.Generic.List<U>, System.Collections.Generic.Dictionary<T, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<T>.Inner<U>.Interface<U, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5", "Outer<T>.Inner<U>.Interface<U, T>.Method<Z>(T, U[], System.Collections.Generic.List<U>, System.Collections.Generic.Dictionary<T, Z>)"),
                // (72,75): error CS0539: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>.Property' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>.Property"),
                // (76,72): error CS0539: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>.Method<K>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<u>>, System.Collections.Generic.Dictionary<T, K>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>.Method<K>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<u>>, System.Collections.Generic.Dictionary<T, K>)"),
                // (70,46): error CS0535: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>' does not implement interface member 'Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Method<Z>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<U>>, System.Collections.Generic.Dictionary<T, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<List<T>>.Inner<U>.Interface<List<U>, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Method<Z>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<U>>, System.Collections.Generic.Dictionary<T, Z>)"),
                // (70,46): error CS0535: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>' does not implement interface member 'Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<List<T>>.Inner<U>.Interface<List<U>, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived7<u>", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Property"),
                // (62,29): error CS0540: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>.Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Property': containing type does not implement interface 'Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Outer<List<T>>.Inner<U>.Interface<List<U>, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>.Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Property", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>"),
                // (66,26): error CS0540: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>.Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Method<K>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<U>>, System.Collections.Generic.Dictionary<T, K>)': containing type does not implement interface 'Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Outer<List<T>>.Inner<U>.Interface<List<U>, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>.Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>.Method<K>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<U>>, System.Collections.Generic.Dictionary<T, K>)", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<U>, T>"),
                // (60,46): error CS0535: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>' does not implement interface member 'Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<u>, T>.Method<Z>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<u>>, System.Collections.Generic.Dictionary<T, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<List<T>>.Inner<U>.Interface<List<u>, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<u>, T>.Method<Z>(System.Collections.Generic.List<T>, U[], System.Collections.Generic.List<System.Collections.Generic.List<u>>, System.Collections.Generic.Dictionary<T, Z>)"),
                // (60,46): error CS0535: 'Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>' does not implement interface member 'Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<u>, T>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<List<T>>.Inner<U>.Interface<List<u>, T>").WithArguments("Outer<T>.Inner<U>.Derived4.Derived5.Derived6<u>", "Outer<System.Collections.Generic.List<T>>.Inner<U>.Interface<System.Collections.Generic.List<u>, T>.Property"),
                // (14,15): error CS0540: 'Outer<T>.Inner<U>.Derived1.Outer<T>.Inner<int>.Interface<long, string>.Property': containing type does not implement interface 'Outer<T>.Inner<int>.Interface<long, string>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Outer<T>.Inner<int>.Interface<long, string>").WithArguments("Outer<T>.Inner<U>.Derived1.Outer<T>.Inner<int>.Interface<long, string>.Property", "Outer<T>.Inner<int>.Interface<long, string>"),
                // (18,18): error CS0540: 'Outer<T>.Inner<U>.Derived1.Outer<T>.Inner<int>.Interface<long, string>.Method<K>(T, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<string, K>)': containing type does not implement interface 'Outer<T>.Inner<int>.Interface<long, string>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Inner<int>.Interface<long, string>").WithArguments("Outer<T>.Inner<U>.Derived1.Outer<T>.Inner<int>.Interface<long, string>.Method<K>(T, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<string, K>)", "Outer<T>.Inner<int>.Interface<long, string>"),
                // (12,35): error CS0535: 'Outer<T>.Inner<U>.Derived1' does not implement interface member 'Outer<T>.Inner<int>.Interface<ulong, string>.Method<Z>(T, int[], System.Collections.Generic.List<ulong>, System.Collections.Generic.Dictionary<string, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Inner<int>.Interface<ulong, string>").WithArguments("Outer<T>.Inner<U>.Derived1", "Outer<T>.Inner<int>.Interface<ulong, string>.Method<Z>(T, int[], System.Collections.Generic.List<ulong>, System.Collections.Generic.Dictionary<string, Z>)"),
                // (12,35): error CS0535: 'Outer<T>.Inner<U>.Derived1' does not implement interface member 'Outer<T>.Inner<int>.Interface<ulong, string>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Inner<int>.Interface<ulong, string>").WithArguments("Outer<T>.Inner<U>.Derived1", "Outer<T>.Inner<int>.Interface<ulong, string>.Property"),
                // (23,19): error CS0540: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Outer<X>.Inner<int>.Interface<long, Y>.Property': containing type does not implement interface 'Outer<X>.Inner<int>.Interface<long, Y>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Outer<X>.Inner<int>.Interface<long, Y>.Property", "Outer<X>.Inner<int>.Interface<long, Y>"),
                // (27,22): error CS0540: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Outer<X>.Inner<int>.Interface<long, Y>.Method<K>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, K>)': containing type does not implement interface 'Outer<X>.Inner<int>.Interface<long, Y>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Outer<X>.Inner<int>.Interface<long, Y>.Method<K>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, K>)", "Outer<X>.Inner<int>.Interface<long, Y>"),
                // (21,45): error CS0535: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>' does not implement interface member 'Outer<Y>.Inner<int>.Interface<long, X>.Method<Z>(Y, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<X, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<Y>.Inner<int>.Interface<long, X>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>", "Outer<Y>.Inner<int>.Interface<long, X>.Method<Z>(Y, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<X, Z>)"),
                // (21,45): error CS0535: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>' does not implement interface member 'Outer<Y>.Inner<int>.Interface<long, X>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<Y>.Inner<int>.Interface<long, X>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>", "Outer<Y>.Inner<int>.Interface<long, X>.Property"),
                // (34,48): error CS0539: 'Outer<T>.Inner<U>.Derived3.Property' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property").WithArguments("Outer<T>.Inner<U>.Derived3.Property"),
                // (38,60): error CS0539: 'Outer<T>.Inner<U>.Derived3.Method<K>(T, K[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<string, K>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived3.Method<K>(T, K[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<string, K>)"),
                // (32,35): error CS0535: 'Outer<T>.Inner<U>.Derived3' does not implement interface member 'Outer<T>.Inner<U>.Interface<long, string>.Method<Z>(T, U[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<string, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface<long, string>").WithArguments("Outer<T>.Inner<U>.Derived3", "Outer<T>.Inner<U>.Interface<long, string>.Method<Z>(T, U[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<string, Z>)"),
                // (32,35): error CS0535: 'Outer<T>.Inner<U>.Derived3' does not implement interface member 'Outer<T>.Inner<U>.Interface<long, string>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface<long, string>").WithArguments("Outer<T>.Inner<U>.Derived3", "Outer<T>.Inner<U>.Interface<long, string>.Property"));
        }
 
        [Fact]
        public void TestErrorsImplementingGenericNestedInterfaces_Explicit_HideTypeParameter()
        {
            // Tests:
            // In signature / name of explicitly implemented member, use generic type whose open type (C<T>) matches signature
            // in base interface - but the closed type (C<string> / C<U>) does not match
 
            var source = @"
using System.Collections.Generic;
class Outer<T>
{
    internal class Inner<U>
    {
        protected internal interface Interface<V, W>
        {
            void Method<X>(T a, U[] b, List<V> c, Dictionary<W, X> d);
            void Method<V, W>(T a, U[] b, List<V> c, Dictionary<W, W> d);
        }
        internal class Derived1<X, Y> : Outer<X>.Inner<int>.Interface<long, Y>
        {
            void Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X A, int[] b, List<long> C, Dictionary<Y, X> d)
            {
            }
            void Outer<X>.Inner<int>.Interface<long, Y>.Method<X, Y>(X A, int[] b, List<X> C, Dictionary<Y, Y> d)
            {
            }
        }
    }
}
class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (14,64): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                //             void Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X A, int[] b, List<long> C, Dictionary<Y, X> d)
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (17,64): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                //             void Outer<X>.Inner<int>.Interface<long, Y>.Method<X, Y>(X A, int[] b, List<X> C, Dictionary<Y, Y> d)
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (17,67): warning CS0693: Type parameter 'Y' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                //             void Outer<X>.Inner<int>.Interface<long, Y>.Method<X, Y>(X A, int[] b, List<X> C, Dictionary<Y, Y> d)
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "Y").WithArguments("Y", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (10,25): warning CS0693: Type parameter 'V' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Interface<V, W>'
                //             void Method<V, W>(T a, U[] b, List<V> c, Dictionary<W, W> d);
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "V").WithArguments("V", "Outer<T>.Inner<U>.Interface<V, W>"),
                // (10,28): warning CS0693: Type parameter 'W' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Interface<V, W>'
                //             void Method<V, W>(T a, U[] b, List<V> c, Dictionary<W, W> d);
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "W").WithArguments("W", "Outer<T>.Inner<U>.Interface<V, W>"),
                // (17,57): error CS0539: 'Outer<T>.Inner<U>.Derived1<X, Y>.Method<X, Y>(X, int[], System.Collections.Generic.List<X>, System.Collections.Generic.Dictionary<Y, Y>)' in explicit interface declaration is not a member of interface
                //             void Outer<X>.Inner<int>.Interface<long, Y>.Method<X, Y>(X A, int[] b, List<X> C, Dictionary<Y, Y> d)
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>.Method<X, Y>(X, int[], System.Collections.Generic.List<X>, System.Collections.Generic.Dictionary<Y, Y>)"),
                // (14,57): error CS0539: 'Outer<T>.Inner<U>.Derived1<X, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)' in explicit interface declaration is not a member of interface
                //             void Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X A, int[] b, List<long> C, Dictionary<Y, X> d)
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)"),
                // (12,41): error CS0535: 'Outer<T>.Inner<U>.Derived1<X, Y>' does not implement interface member 'Outer<X>.Inner<int>.Interface<long, Y>.Method<V, W>(X, int[], System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<W, W>)'
                //         internal class Derived1<X, Y> : Outer<X>.Inner<int>.Interface<long, Y>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>", "Outer<X>.Inner<int>.Interface<long, Y>.Method<V, W>(X, int[], System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<W, W>)"),
                // (12,41): error CS0535: 'Outer<T>.Inner<U>.Derived1<X, Y>' does not implement interface member 'Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)'
                //         internal class Derived1<X, Y> : Outer<X>.Inner<int>.Interface<long, Y>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>", "Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)"));
        }
 
        [Fact]
        public void TestErrorsImplementingGenericNestedInterfaces_Implicit_HideTypeParameter()
        {
            // Tests:
            // In signature / name of explicitly implemented member, use generic type whose open type (C<T>) matches signature
            // in base interface - but the closed type (C<string> / C<U>) does not match
 
            var source = @"
using System.Collections.Generic;
class Outer<T>
{
    internal class Inner<U>
    {
        protected internal interface Interface<V, W>
        {
            void Method<X>(T a, U[] b, List<V> c, Dictionary<W, X> d);
            void Method<V, W>(T a, U[] b, List<V> c, Dictionary<W, W> d);
        }
        internal class Derived1<X, Y> : Outer<X>.Inner<int>.Interface<long, Y>
        {
            void Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X A, int[] b, List<long> C, Dictionary<Y, X> d)
            {
            }
            void Outer<X>.Inner<int>.Interface<long, Y>.Method<X, Y>(X A, int[] b, List<X> C, Dictionary<Y, Y> d)
            {
            }
        }
    }
}
class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (14,64): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (17,64): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (17,67): warning CS0693: Type parameter 'Y' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "Y").WithArguments("Y", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (10,25): warning CS0693: Type parameter 'V' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Interface<V, W>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "V").WithArguments("V", "Outer<T>.Inner<U>.Interface<V, W>"),
                // (10,28): warning CS0693: Type parameter 'W' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Interface<V, W>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "W").WithArguments("W", "Outer<T>.Inner<U>.Interface<V, W>"),
                // (17,57): error CS0539: 'Outer<T>.Inner<U>.Derived1<X, Y>.Method<X, Y>(X, int[], System.Collections.Generic.List<X>, System.Collections.Generic.Dictionary<Y, Y>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>.Method<X, Y>(X, int[], System.Collections.Generic.List<X>, System.Collections.Generic.Dictionary<Y, Y>)"),
                // (14,57): error CS0539: 'Outer<T>.Inner<U>.Derived1<X, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)"),
                // (12,41): error CS0535: 'Outer<T>.Inner<U>.Derived1<X, Y>' does not implement interface member 'Outer<X>.Inner<int>.Interface<long, Y>.Method<V, W>(X, int[], System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<W, W>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>", "Outer<X>.Inner<int>.Interface<long, Y>.Method<V, W>(X, int[], System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<W, W>)"),
                // (12,41): error CS0535: 'Outer<T>.Inner<U>.Derived1<X, Y>' does not implement interface member 'Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>", "Outer<X>.Inner<int>.Interface<long, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)"));
        }
 
        [Fact]
        public void TestErrorsOverridingGenericNestedClasses_HideTypeParameter()
        {
            // Tests:
            // In signature / name of overridden member, use generic type whose open type (C<T>) matches signature
            // in base class - but the closed type (C<string> / C<U>) does not match
 
            var source = @"
using System.Collections.Generic;
class Outer<T>
{
    internal class Inner<U>
    {
        protected internal abstract class Base<V, W>
        {
            internal virtual void Method<X>(T a, U[] b, List<V> c, Dictionary<W, X> d) { }
            internal abstract void Method<V, W>(T a, U[] b, List<V> c, Dictionary<W, W> d);
        }
        internal class Derived1<X, Y> : Outer<X>.Inner<int>.Base<long, Y>
        {
            internal override void Method<X>(X A, int[] b, List<long> C, Dictionary<Y, X> d)
            {
            }
            internal override void Method<X, Y>(X A, int[] b, List<X> C, Dictionary<Y, Y> d)
            {
            }
        }
    }
}
class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (10,43): warning CS0693: Type parameter 'V' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Base<V, W>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "V").WithArguments("V", "Outer<T>.Inner<U>.Base<V, W>"),
                // (10,46): warning CS0693: Type parameter 'W' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Base<V, W>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "W").WithArguments("W", "Outer<T>.Inner<U>.Base<V, W>"),
                // (14,43): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (17,43): warning CS0693: Type parameter 'X' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "X").WithArguments("X", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (17,46): warning CS0693: Type parameter 'Y' has the same name as the type parameter from outer type 'Outer<T>.Inner<U>.Derived1<X, Y>'
                Diagnostic(ErrorCode.WRN_TypeParameterSameAsOuterTypeParameter, "Y").WithArguments("Y", "Outer<T>.Inner<U>.Derived1<X, Y>"),
                // (14,36): error CS0115: 'Outer<T>.Inner<U>.Derived1<X, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>.Method<X>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, X>)"),
                // (17,36): error CS0115: 'Outer<T>.Inner<U>.Derived1<X, Y>.Method<X, Y>(X, int[], System.Collections.Generic.List<X>, System.Collections.Generic.Dictionary<Y, Y>)': no suitable method found to override
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Method").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>.Method<X, Y>(X, int[], System.Collections.Generic.List<X>, System.Collections.Generic.Dictionary<Y, Y>)"),
                // (12,24): error CS0534: 'Outer<T>.Inner<U>.Derived1<X, Y>' does not implement inherited abstract member 'Outer<X>.Inner<int>.Base<long, Y>.Method<V, W>(X, int[], System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<W, W>)'
                Diagnostic(ErrorCode.ERR_UnimplementedAbstractMethod, "Derived1").WithArguments("Outer<T>.Inner<U>.Derived1<X, Y>", "Outer<X>.Inner<int>.Base<long, Y>.Method<V, W>(X, int[], System.Collections.Generic.List<V>, System.Collections.Generic.Dictionary<W, W>)"));
        }
 
        [Fact]
        public void TestErrorsImplementingGenericNestedInterfaces_Explicit_IncorrectPartialQualification()
        {
            // Tests:
            // In name of explicitly implemented member specify incorrect partially qualified type name
 
            var source = @"
using System.Collections.Generic;
class Outer<T>
{
    internal class Inner<U>
    {
        protected internal interface Interface<V, W>
        {
            T Property { set; }
            void Method<Z>(T a, U[] b, List<V> c, Dictionary<W, Z> d);
        }
        internal class Derived1 : Inner<int>.Interface<long, string>
        {
            T Interface<long, string>.Property
            {
                set { }
            }
            void Inner<int>.Interface<long, string>.Method<K>(T A, int[] B, List<long> c, Dictionary<string, K> D)
            {
            }
            internal class Derived2<X, Y> : Outer<X>.Inner<int>.Interface<long, Y>
            {
                X Inner<int>.Interface<long, Y>.Property
                {
                    set { }
                }
                void Inner<long>.Interface<long, Y>.Method<K>(X A, int[] b, List<long> C, Dictionary<Y, K> d)
                {
                }
            }
        }
        internal class Derived3 : Interface<long, string>
        {
            T Interface<long, string>.Property
            {
                set { }
            }
            void Inner<U>.Interface<long, string>.Method<K>(T a, U[] B, List<long> C, Dictionary<string, K> d)
            {
            }
        }
        internal class Derived4 : Outer<U>.Inner<T>.Interface<T, U>
        {
            U Interface<T, U>.Property
            {
                set { }
            }
            void Inner<T>.Interface<T, U>.Method<K>(U a, T[] b, List<T> C, Dictionary<U, K> d)
            {
            }
        }
    }
}
class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (44,15): error CS0540: 'Outer<T>.Inner<U>.Derived4.Property': containing type does not implement interface 'Outer<T>.Inner<U>.Interface<T, U>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface<T, U>").WithArguments("Outer<T>.Inner<U>.Derived4.Property", "Outer<T>.Inner<U>.Interface<T, U>"),
                // (44,31): error CS0539: 'Outer<T>.Inner<U>.Derived4.Property' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property").WithArguments("Outer<T>.Inner<U>.Derived4.Property"),
                // (48,18): error CS0540: 'Outer<T>.Inner<U>.Derived4.Method<K>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, K>)': containing type does not implement interface 'Outer<T>.Inner<T>.Interface<T, U>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Inner<T>.Interface<T, U>").WithArguments("Outer<T>.Inner<U>.Derived4.Method<K>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, K>)", "Outer<T>.Inner<T>.Interface<T, U>"),
                // (48,43): error CS0539: 'Outer<T>.Inner<U>.Derived4.Method<K>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, K>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived4.Method<K>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, K>)"),
                // (42,35): error CS0535: 'Outer<T>.Inner<U>.Derived4' does not implement interface member 'Outer<U>.Inner<T>.Interface<T, U>.Method<Z>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<U>.Inner<T>.Interface<T, U>").WithArguments("Outer<T>.Inner<U>.Derived4", "Outer<U>.Inner<T>.Interface<T, U>.Method<Z>(U, T[], System.Collections.Generic.List<T>, System.Collections.Generic.Dictionary<U, Z>)"),
                // (42,35): error CS0535: 'Outer<T>.Inner<U>.Derived4' does not implement interface member 'Outer<U>.Inner<T>.Interface<T, U>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<U>.Inner<T>.Interface<T, U>").WithArguments("Outer<T>.Inner<U>.Derived4", "Outer<U>.Inner<T>.Interface<T, U>.Property"),
                // (14,15): error CS0540: 'Outer<T>.Inner<U>.Derived1.Outer<T>.Inner<U>.Interface<long, string>.Property': containing type does not implement interface 'Outer<T>.Inner<U>.Interface<long, string>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Interface<long, string>").WithArguments("Outer<T>.Inner<U>.Derived1.Outer<T>.Inner<U>.Interface<long, string>.Property", "Outer<T>.Inner<U>.Interface<long, string>"),
                // (12,35): error CS0535: 'Outer<T>.Inner<U>.Derived1' does not implement interface member 'Outer<T>.Inner<int>.Interface<long, string>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Inner<int>.Interface<long, string>").WithArguments("Outer<T>.Inner<U>.Derived1", "Outer<T>.Inner<int>.Interface<long, string>.Property"),
                // (23,19): error CS0540: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Property': containing type does not implement interface 'Outer<T>.Inner<int>.Interface<long, Y>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Property", "Outer<T>.Inner<int>.Interface<long, Y>"),
                // (23,49): error CS0539: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Property' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Property").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Property"),
                // (27,22): error CS0540: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Method<K>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, K>)': containing type does not implement interface 'Outer<T>.Inner<long>.Interface<long, Y>'
                Diagnostic(ErrorCode.ERR_ClassDoesntImplementInterface, "Inner<long>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Method<K>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, K>)", "Outer<T>.Inner<long>.Interface<long, Y>"),
                // (27,53): error CS0539: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Method<K>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, K>)' in explicit interface declaration is not a member of interface
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Method").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>.Method<K>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, K>)"),
                // (21,45): error CS0535: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>' does not implement interface member 'Outer<X>.Inner<int>.Interface<long, Y>.Method<Z>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, Z>)'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>", "Outer<X>.Inner<int>.Interface<long, Y>.Method<Z>(X, int[], System.Collections.Generic.List<long>, System.Collections.Generic.Dictionary<Y, Z>)"),
                // (21,45): error CS0535: 'Outer<T>.Inner<U>.Derived1.Derived2<X, Y>' does not implement interface member 'Outer<X>.Inner<int>.Interface<long, Y>.Property'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Outer<X>.Inner<int>.Interface<long, Y>").WithArguments("Outer<T>.Inner<U>.Derived1.Derived2<X, Y>", "Outer<X>.Inner<int>.Interface<long, Y>.Property"));
        }
 
        [Fact]
        public void TestImplicitImplementationSubstitutionError()
        {
            // Tests:
            // Implicitly implement interface member in base generic type – the method that implements interface member 
            // should depend on type parameter of base type to satisfy signature (return type / parameter type) equality
            // Test case where substitution is incorrect
 
            var source = @"
using System.Collections.Generic;
interface Interface
{
    void Method(List<int> x);
    void Method(List<long> z);
}
class Base<T>
{
    public void Method(T x) { }
}
class Base2<T> : Base<T>
{
    public void Method(List<long> x) { }
}
class Derived : Base2<List<uint>>, Interface
{
}
class Test
{
    public static void Main()
    {
    }
}";
            CreateCompilation(source).VerifyDiagnostics(
               // (16,7): error CS0535: 'Derived' does not implement interface member 'Interface.Method(System.Collections.Generic.List<int>)'
               Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "Interface").WithArguments("Derived", "Interface.Method(System.Collections.Generic.List<int>)"));
        }
 
        [Fact]
        public void TestImplementAmbiguousSignaturesImplicitly_Errors()
        {
            // Tests:
            // Use a single member to implicitly implement 
            // multiple base interface members that have signatures differing only by params
            // Implicitly implement multiple base interface members that 
            // have signatures differing only by ref/out (some of these will be error cases)
 
            var text = @"
using System;
interface I1
{
    int P { set; }
    void M1(long x);
    void M2(long x);
    void M3(long x);
    void M4(ref long x);
    void M5(out long x);
    void M6(ref long x);
    void M7(out long x);
    void M8(params long[] x);
    void M9(long[] x);
}
interface I2 : I1
{
}
interface I3 : I2
{
    new long P { set; }
    new int M1(long x); // Return type
    void M2(ref long x); // Add ref
    void M3(out long x); // Add out
    void M4(long x); // Omit ref
    void M5(long x); // Omit out
    void M6(out long x); // Toggle ref to out
    void M7(ref long x); // Toggle out to ref
    new void M8(long[] x); // Omit params
    new void M9(params long[] x); // Add params
}
class Test : I3
{
    public int P { get { return 0; } set { Console.WriteLine(""I1.P""); } }
    // public long P { get { return 0; } set { Console.WriteLine(""I3.P""); } } - Not possible to implement I3.P implicitly
    // public void M1(long x) { Console.WriteLine(""I1.M1""); } - Not possible to implement I1.M1 implicitly
    public int M1(long x) { Console.WriteLine(""I3.M1""); return 0; }
    public void M2(ref long x) { Console.WriteLine(""I3.M2""); }
    public void M2(long x) { Console.WriteLine(""I1.M2""); }
    public void M3(long x) { Console.WriteLine(""I1.M3""); }
    public void M3(out long x) { x = 0; Console.WriteLine(""I3.M3""); }
    public void M4(long x) { Console.WriteLine(""I3.M4""); }
    public void M4(ref long x) { Console.WriteLine(""I1.M4""); }
    public void M5(out long x) { x = 0; Console.WriteLine(""I3.M5""); }
    public void M5(long x) { Console.WriteLine(""I1.M5""); }
    // public void M6(ref long x) { x = 0; Console.WriteLine(""I1.M6""); } - Not possible to implement I1.M6 implicitly
    public void M6(out long x) { x = 0; Console.WriteLine(""I3.M6""); }
    public void M7(ref long x) { Console.WriteLine(""I3.M7""); }
    // public void M7(out long x) { x = 0; Console.WriteLine(""I1.M7""); } - Not possible to implement I1.M7 implicitly
    public void M8(long[] x) { Console.WriteLine(""I3.M8+I1.M9""); } // Implements both I3.M8 and I1.M8
    public void M9(params long[] x) { Console.WriteLine(""I3.M9+I1.M9""); } // Implements both I3.M9 and I1.M9
}";
            CreateCompilation(text).VerifyDiagnostics(
                // (32,14): error CS0738: 'Test' does not implement interface member 'I3.P'. 'Test.P' cannot implement 'I3.P' because it does not have the matching return type of 'long'.
                // class Test : I3
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I3").WithArguments("Test", "I3.P", "Test.P", "long").WithLocation(32, 14),
                // (32,14): error CS0738: 'Test' does not implement interface member 'I1.M1(long)'. 'Test.M1(long)' cannot implement 'I1.M1(long)' because it does not have the matching return type of 'void'.
                // class Test : I3
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberWrongReturnType, "I3").WithArguments("Test", "I1.M1(long)", "Test.M1(long)", "void").WithLocation(32, 14),
                // (32,14): error CS0535: 'Test' does not implement interface member 'I1.M6(ref long)'
                // class Test : I3
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test", "I1.M6(ref long)").WithLocation(32, 14),
                // (32,14): error CS0535: 'Test' does not implement interface member 'I1.M7(out long)'
                // class Test : I3
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I3").WithArguments("Test", "I1.M7(out long)").WithLocation(32, 14));
        }
 
        [Fact]
        public void TestImplementAmbiguousSignaturesFromSameInterface_Errors()
        {
            // Tests:
            // Implicitly / explicitly implement multiple base interface members (that have same signature) with a single member
            // Implicitly / explicitly implement multiple base interface members (that have same signature) with a single member from base class
 
            var source = @"
using System;
interface I1<T, U>
{
    void Method<V>(T x, Func<U, T, V> v, U z);
    void Method<Z>(U x, Func<T, U, Z> v, T z);
}
class Implicit : I1<int, Int32>
{
    public void Method<V>(int x, Func<int, int, V> v, int z) { }
}
class Base
{
    public void Method<V>(int x, Func<int, int, V> v, int z) { }
}
class Base2 : Base { }
class ImplicitInBase : Base2, I1<int, Int32> { }
class Explicit : I1<int, Int32>
{
    void I1<Int32, Int32>.Method<V>(int x, Func<int, int, V> v, int z) { }
    public void Method<V>(int x, Func<int, int, V> v, int z) { }
}
class Test
{
    public static void Main()
    {
        I1<int, int> i = new Implicit();
        Func<int, int, string> x = null;
        i.Method<string>(1, x, 1);
 
        i = new ImplicitInBase();
        i.Method<string>(1, x, 1);
 
        i = new Explicit();
        i.Method<string>(1, x, 1);
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
// (20,27): warning CS0473: Explicit interface implementation 'Explicit.I1<int, int>.Method<V>(int, System.Func<int, int, V>, int)' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
//     void I1<Int32, Int32>.Method<V>(int x, Func<int, int, V> v, int z) { }
Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Explicit.I1<int, int>.Method<V>(int, System.Func<int, int, V>, int)"),
// (29,9): error CS0121: The call is ambiguous between the following methods or properties: 'I1<T, U>.Method<V>(T, System.Func<U, T, V>, U)' and 'I1<T, U>.Method<Z>(U, System.Func<T, U, Z>, T)'
//         i.Method<string>(1, x, 1);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method<string>").WithArguments("I1<T, U>.Method<V>(T, System.Func<U, T, V>, U)", "I1<T, U>.Method<Z>(U, System.Func<T, U, Z>, T)"),
// (32,9): error CS0121: The call is ambiguous between the following methods or properties: 'I1<T, U>.Method<V>(T, System.Func<U, T, V>, U)' and 'I1<T, U>.Method<Z>(U, System.Func<T, U, Z>, T)'
//         i.Method<string>(1, x, 1);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method<string>").WithArguments("I1<T, U>.Method<V>(T, System.Func<U, T, V>, U)", "I1<T, U>.Method<Z>(U, System.Func<T, U, Z>, T)"),
// (35,9): error CS0121: The call is ambiguous between the following methods or properties: 'I1<T, U>.Method<V>(T, System.Func<U, T, V>, U)' and 'I1<T, U>.Method<Z>(U, System.Func<T, U, Z>, T)'
//         i.Method<string>(1, x, 1);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method<string>").WithArguments("I1<T, U>.Method<V>(T, System.Func<U, T, V>, U)", "I1<T, U>.Method<Z>(U, System.Func<T, U, Z>, T)"));
        }
 
        [Fact]
        public void TestImplementAmbiguousSignaturesFromSameInterface_Errors2()
        {
            var source = @"
using System;
interface I1<T, U>
{
    Action<T> Method(ref T x);
    Action<U> Method(U x); // Omit ref
    void Method(ref Func<U, T> v);
    void Method(out Func<T, U> v); // Toggle ref to out
    void Method(T x, U[] y);
    void Method(U x, params T[] y); // Add params
    long Method(T x, U v, U[] y);
    int Method(U x, T v, params U[] y); // Add params and change return type
}
class Implicit : I1<int, int>
{
    public Action<int> Method(ref int x) { Console.WriteLine(""Method(ref int x)""); return null; }
    public Action<int> Method(int x) { Console.WriteLine(""Method(int x)""); return null; }
    public void Method(ref Func<int, int> v) { Console.WriteLine(""Method(ref Func<int, int> v)""); }
    // We have to implement this explicitly
    void I1<int, int>.Method(out Func<int, int> v) { v = null; Console.WriteLine(""I1<int, int>.Method(out Func<int, int> v)""); }
    public void Method(int x, int[] y) { Console.WriteLine(""Method(int x, int[] y)""); }
    // Implements both params and non-params version
    public long Method(int x, int v, int[] y) { Console.WriteLine(""Method(int x, int v, int[] y)""); return 0; }
    // We have to implement this explicitly
    int I1<int, int>.Method(int x, int v, params int[] y) { Console.WriteLine(""I1<int, int>.Method(int x, int v, params int[] y)""); return 0; }
}
class Test
{
    public static void Main()
    {
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (3,11): error CS0767: "Cannot inherit interface 'I1<int, int>' with the specified type parameters because it causes method 'I1<int, int>.Method(out System.Func<int, int>)' to contain overloads which differ only on ref and out."
                Diagnostic(ErrorCode.ERR_ExplicitImplCollisionOnRefOut, "I1").WithArguments("I1<int, int>", "I1<int, int>.Method(out System.Func<int, int>)"));
        }
 
        [Fact]
        public void TestImplementAmbiguousSignaturesFromSameInterface_Errors3()
        {
            var source = @"
using System;
interface I1<T, U>
{
    Action<T> Method(ref T x);
    Action<U> Method(U x); // Omit ref
    void Method(ref Func<U, T> v);
    void Method(out Func<T, U> v); // Toggle ref to out
    void Method(T x, U[] y);
    void Method(U x, params T[] y); // Add params
    long Method(T x, Func<T, U> v, U[] y);
    int Method(U x, Func<T, U> v, params U[] y); // Add params and change return type
}
class Base
{
    public Action<int> Method(ref int x) { Console.WriteLine(""Method(ref int x)""); return null; }
    public Action<int> Method(int x) { Console.WriteLine(""Method(int x)""); return null; }
    public void Method(ref Func<int, int> v) { Console.WriteLine(""Method(ref Func<int, int> v)""); }
    public void Method(int x, int[] y) { Console.WriteLine(""Method(int x, int[] y)""); }
    public long Method(int x, Func<int, int> v, int[] y) { Console.WriteLine(""long Method(int x, Func<int, int> v, int[] y)""); return 0; }
}
class ImplicitInBase : Base, I1<int, int>
{
    public void Method(out Func<int, int> v) { v = null; Console.WriteLine(""Method(out Func<int, int> v)""); }
    public int Method(int x, Func<int, int> v, params int[] y) { Console.WriteLine(""int Method(int x, Func<int, int> v, params int[] y)""); return 0; }
}
class Test
{
    public static void Main()
    {
        I1<int, int> i = new ImplicitInBase();
        int x = 1; Func<int, int> y = null;
        i.Method(ref x); i.Method(x); i.Method(ref y); i.Method(out y);
        i.Method(x, new int[] { x, x, x }); i.Method(x, x, x, x);
        i.Method(x, y, new int[] { x, x, x }); i.Method(x, y, x, x, x);
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
// (25,16): warning CS0108: 'ImplicitInBase.Method(int, System.Func<int, int>, params int[])' hides inherited member 'Base.Method(int, System.Func<int, int>, int[])'. Use the new keyword if hiding was intended.
//     public int Method(int x, Func<int, int> v, params int[] y) { Console.WriteLine("int Method(int x, Func<int, int> v, params int[] y)"); return 0; }
Diagnostic(ErrorCode.WRN_NewRequired, "Method").WithArguments("ImplicitInBase.Method(int, System.Func<int, int>, params int[])", "Base.Method(int, System.Func<int, int>, int[])"),
// (34,9): error CS0121: The call is ambiguous between the following methods or properties: 'I1<T, U>.Method(T, U[])' and 'I1<T, U>.Method(U, params T[])'
//         i.Method(x, new int[] { x, x, x }); i.Method(x, x, x, x);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("I1<T, U>.Method(T, U[])", "I1<T, U>.Method(U, params T[])"),
// (35,9): error CS0121: The call is ambiguous between the following methods or properties: 'I1<T, U>.Method(T, System.Func<T, U>, U[])' and 'I1<T, U>.Method(U, System.Func<T, U>, params U[])'
//         i.Method(x, y, new int[] { x, x, x }); i.Method(x, y, x, x, x);
Diagnostic(ErrorCode.ERR_AmbigCall, "Method").WithArguments("I1<T, U>.Method(T, System.Func<T, U>, U[])", "I1<T, U>.Method(U, System.Func<T, U>, params U[])"));
        }
 
        [Fact]
        public void TestImplementAmbiguousSignaturesFromSameInterface_Errors4()
        {
            var source = @"
using System;
interface I1<T, U>
{
    Action<T> Method(ref T x);
    Action<U> Method(U x); // Omit ref
    void Method(ref Func<U, T> v);
    void Method(out Func<T, U> v); // Toggle ref to out
    void Method(T x, U[] y);
    void Method(U x, params T[] y); // Add params
    long Method(T x, Func<T, U> v, U[] y);
    int Method(U x, Func<T, U> v, params U[] y); // Add params and change return type
}
class Explicit : I1<int, int>
{
    Action<int> I1<int, int>.Method(ref int x) { Console.WriteLine(""I1<int, int>.Method(ref int x)""); return null; }
    Action<int> I1<int, int>.Method(int x) { Console.WriteLine(""I1<int, int>.Method(int x)""); return null; }
    void I1<int, int>.Method(ref Func<int, int> v) { Console.WriteLine(""I1<int, int>.Method(ref Func<int, int> v)""); }
    void I1<int, int>.Method(out Func<int, int> v) { v = null; Console.WriteLine(""I1<int, int>.Method(out Func<int, int> v)""); }
    void I1<int, int>.Method(int x, int[] y) { Console.WriteLine(""I1<int, int>.Method(int x, int[] y)""); }
    // This has to be implicit so as not to clash with the above
    public void Method(int x, params int[] y) { Console.WriteLine(""Method(int x, params int[] y)""); }
    long I1<int, int>.Method(int x, Func<int, int> v, int[] y) { Console.WriteLine(""long I1<int, int>.Method(int x, Func<int, int> v, int[] y)""); return 0; }
    int I1<int, int>.Method(int x, Func<int, int> v, params int[] y) { Console.WriteLine(""int I1<int, int>.Method(int x, Func<int, int> v, params int[] y)""); return 0; }
}
class Test
{
    public static void Main()
    {
        I1<int, int> i = new Explicit();
        int x = 1; Func<int, int> y = null;
        i.Method(ref x); i.Method(x); i.Method(ref y); i.Method(out y);
        i.Method(x, x, x, x); i.Method(x, y, x, x, x);
    }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (3,11): error CS0767: "Cannot inherit interface 'I1<int, int>' with the specified type parameters because it causes method 'I1<int, int>.Method(ref System.Func<int, int>)' to contain overloads which differ only on ref and out."
                Diagnostic(ErrorCode.ERR_ExplicitImplCollisionOnRefOut, "I1").WithArguments("I1<int, int>", "I1<int, int>.Method(ref System.Func<int, int>)"),
                // (3,11): error CS0767: "Cannot inherit interface 'I1<int, int>' with the specified type parameters because it causes method 'I1<int, int>.Method(out System.Func<int, int>)' to contain overloads which differ only on ref and out."
                Diagnostic(ErrorCode.ERR_ExplicitImplCollisionOnRefOut, "I1").WithArguments("I1<int, int>", "I1<int, int>.Method(out System.Func<int, int>)"),
                // (20,23): warning CS0473: Explicit interface implementation 'Explicit.I1<int, int>.Method(int, int[])' matches more than one interface member. Which interface member is actually chosen is implementation-dependent. Consider using a non-explicit implementation instead.
                Diagnostic(ErrorCode.WRN_ExplicitImplCollision, "Method").WithArguments("Explicit.I1<int, int>.Method(int, int[])"));
        }
        [Fact]
 
        public void TestErrorsOverridingImplementingMember()
        {
            // Tests:
            // Members that implement interface members are usually marked as virtual sealed -
            // test the errors that are reported when trying to override these implementing members
 
            var source = @"
interface I
{
    void M();
    int P { set; }
}
class Base : I
{
    public void M() { }
    public int P { set { } }
}
class Derived : Base
{
    public override void M() { }
    public override int P { set { } }
}
class Base2
{
    public void M() { }
    public int P { set { } }
}
class Derived2 : Base2, I
{
}
class Derived3 : Derived2
{
    public override void M() { }
    public override int P { set { } }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (14,26): error CS0506: 'Derived.M()': cannot override inherited member 'Base.M()' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "M").WithArguments("Derived.M()", "Base.M()"),
                // (15,25): error CS0506: 'Derived.P': cannot override inherited member 'Base.P' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "P").WithArguments("Derived.P", "Base.P"),
                // (27,26): error CS0506: 'Derived3.M()': cannot override inherited member 'Base2.M()' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "M").WithArguments("Derived3.M()", "Base2.M()"),
                // (28,25): error CS0506: 'Derived3.P': cannot override inherited member 'Base2.P' because it is not marked virtual, abstract, or override
                Diagnostic(ErrorCode.ERR_CantOverrideNonVirtual, "P").WithArguments("Derived3.P", "Base2.P"));
        }
 
        [Fact]
        public void TestImplementingMethodNamedFinalize()
        {
            var source = @"
interface I
{
    void Finalize();
}
class C1 : I { public void Finalize() { } }
class C2 : I { }
class Test
{
    public static void Main() { I i = new C1(); i.Finalize(); }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (4,10): warning CS0465: Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?
                //     void Finalize();
                Diagnostic(ErrorCode.WRN_FinalizeMethod, "Finalize").WithLocation(4, 10),
                // (6,28): warning CS0465: Introducing a 'Finalize' method can interfere with destructor invocation. Did you intend to declare a destructor?
                // class C1 : I { public void Finalize() { } }
                Diagnostic(ErrorCode.WRN_FinalizeMethod, "Finalize").WithLocation(6, 28),
                // (7,12): error CS0737: 'C2' does not implement interface member 'I.Finalize()'. 'object.~Object()' cannot implement an interface member because it is not public.
                // class C2 : I { }
                Diagnostic(ErrorCode.ERR_CloseUnimplementedInterfaceMemberNotPublic, "I").WithArguments("C2", "I.Finalize()", "object.~Object()").WithLocation(7, 12));
        }
 
        [Fact]
        public void TestImplementingMethodNamedFinalize2()
        {
            var source = @"
interface I
{
    int Finalize();
    void Finalize(int i);
}
class Base 
{
    public void Finalize(int j) { }
}
class Derived : Base, I
{
    public int Finalize() { return 0; }
}
class Test
{
    public static void Main() { I i = new Derived(); i.Finalize(i.Finalize()); }
}";
 
            CreateCompilation(source).VerifyDiagnostics();
        }
 
        [WorkItem(542361, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542361")]
        [Fact]
        public void TestTypeParameterExplicitMethodImplementation()
        {
            var source = @"
interface T
{
    void T<S>();
}
class A<T> : global::T
{
    void T.T<S>() { }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (8,10): error CS0538: 'T' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "T").WithArguments("T"),
                // (6,7): error CS0535: 'A<T>' does not implement interface member 'T.T<S>()'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "global::T").WithArguments("A<T>", "T.T<S>()"));
        }
 
        [WorkItem(542361, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542361")]
        [Fact]
        public void TestTypeParameterExplicitPropertyImplementation()
        {
            var source = @"
interface T
{
    int T { get; set; }
}
class A<T> : global::T
{
    int T.T { get; set; }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (8,9): error CS0538: 'T' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "T").WithArguments("T"),
                // (6,7): error CS0535: 'A<T>' does not implement interface member 'T.T'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "global::T").WithArguments("A<T>", "T.T"));
        }
 
        [WorkItem(542361, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/542361")]
        [Fact]
        public void TestTypeParameterExplicitEventImplementation()
        {
            var source = @"
interface T
{
    event System.Action T;
}
class A<T> : global::T
{
    event System.Action T.T { add { } remove { } }
}";
 
            CreateCompilation(source).VerifyDiagnostics(
                // (8,25): error CS0538: 'T' in explicit interface declaration is not an interface
                Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationNotInterface, "T").WithArguments("T"),
                // (6,7): error CS0535: 'A<T>' does not implement interface member 'T.T'
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "global::T").WithArguments("A<T>", "T.T"));
        }
 
        private static CSharpCompilation CompileAndVerifyDiagnostics(string text, ErrorDescription[] expectedErrors, params CSharpCompilation[] baseCompilations)
        {
            var refs = new List<MetadataReference>(baseCompilations.Select(c => new CSharpCompilationReference(c)));
            var comp = CreateCompilation(text, refs);
            var actualErrors = comp.GetDiagnostics();
 
            //ostensibly, we could just pass exactMatch: true to VerifyErrorCodes, but that method is short-circuited when 0 errors are expected
            Assert.Equal(expectedErrors.Length, actualErrors.Count());
            DiagnosticsUtils.VerifyErrorCodes(actualErrors, expectedErrors);
 
            return comp;
        }
 
        private static CSharpCompilation CompileAndVerifyDiagnostics(string text1, string text2, ErrorDescription[] expectedErrors1, ErrorDescription[] expectedErrors2)
        {
            var comp1 = CompileAndVerifyDiagnostics(text1, expectedErrors1);
            var comp2 = CompileAndVerifyDiagnostics(text2, expectedErrors2, comp1);
            return comp2;
        }
 
        [Fact]
        [WorkItem(1016693, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1016693")]
        public void Bug1016693()
        {
            const string source = @"
public class A
{
    public virtual int P { get; set; }
 
    public class B : A
    {
        public override int P { get; set; }
    }
}";
            CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem(31974, "https://github.com/dotnet/roslyn/issues/31974")]
        public void Issue31974()
        {
            const string source = @"
namespace Ns1
{
    public interface I1<I1T1>
    {
        void M();
        int P {get; set;}
        event System.Action E;
    }
 
    public class C0<ST1, ST2>
    { }
 
    public interface I2<I2T1, I2T2> : I1<C0<I2T1, I2T2>>
    {
    }
 
    class C1<C1T1, C1T2> : I2<C1T1, C1T2>
    {
        void I1<C0<C1T1, C1T2>>.M()
        {
        }
 
        void global::Ns1.I1<C0<C1T1, C1T2>>.M()
        {
        }
 
        int I1<C0<C1T1, C1T2>>.P
        {
            get => throw null;
            set => throw null;
        }
 
        int global::Ns1.I1<C0<C1T1, C1T2>>.P
        {
            get => throw null;
            set => throw null;
        }
 
        event System.Action I1<C0<C1T1, C1T2>>.E
        {
            add => throw null;
            remove => throw null;
        }
 
        event System.Action global::Ns1.I1<C0<C1T1, C1T2>>.E
        {
            add => throw null;
            remove => throw null;
        }
    }
}";
            CreateCompilation(source).VerifyDiagnostics(
                // (18,11): error CS8646: 'I1<C0<C1T1, C1T2>>.P' is explicitly implemented more than once.
                //     class C1<C1T1, C1T2> : I2<C1T1, C1T2>
                Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("Ns1.I1<Ns1.C0<C1T1, C1T2>>.P").WithLocation(18, 11),
                // (18,11): error CS8646: 'I1<C0<C1T1, C1T2>>.E' is explicitly implemented more than once.
                //     class C1<C1T1, C1T2> : I2<C1T1, C1T2>
                Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("Ns1.I1<Ns1.C0<C1T1, C1T2>>.E").WithLocation(18, 11),
                // (18,11): error CS8646: 'I1<C0<C1T1, C1T2>>.M()' is explicitly implemented more than once.
                //     class C1<C1T1, C1T2> : I2<C1T1, C1T2>
                Diagnostic(ErrorCode.ERR_DuplicateExplicitImpl, "C1").WithArguments("Ns1.I1<Ns1.C0<C1T1, C1T2>>.M()").WithLocation(18, 11)
                );
        }
 
        [Fact]
        public void DynamicMismatch_01()
        {
            var source = @"
public interface I0<T> { }
public interface I1 : I0<object> { }
public interface I2 : I0<dynamic> { }
public interface I3 : I0<object> { }
 
public class C : I1, I2 { }
public class D : I1, I3 { }
";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (4,23): error CS1966: 'I2': cannot implement a dynamic interface 'I0<dynamic>'
                // public interface I2 : I0<dynamic> { }
                Diagnostic(ErrorCode.ERR_DeriveFromConstructedDynamic, "I0<dynamic>").WithArguments("I2", "I0<dynamic>").WithLocation(4, 23),
                // (7,14): error CS8779: 'I0<dynamic>' is already listed in the interface list on type 'C' as 'I0<object>'.
                // public class C : I1, I2 { }
                Diagnostic(ErrorCode.ERR_DuplicateInterfaceWithDifferencesInBaseList, "C").WithArguments("I0<dynamic>", "I0<object>", "C").WithLocation(7, 14)
                );
        }
 
        [Fact]
        public void DynamicMismatch_02()
        {
            var source = @"
public interface I0<T> 
{
    void M();
}
 
public class C : I0<object>
{
    void I0<object>.M(){}
}
public class D : C, I0<dynamic>
{ }
";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (11,21): error CS1966: 'D': cannot implement a dynamic interface 'I0<dynamic>'
                // public class D : C, I0<dynamic>
                Diagnostic(ErrorCode.ERR_DeriveFromConstructedDynamic, "I0<dynamic>").WithArguments("D", "I0<dynamic>").WithLocation(11, 21),
                // (11,21): error CS0535: 'D' does not implement interface member 'I0<dynamic>.M()'
                // public class D : C, I0<dynamic>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0<dynamic>").WithArguments("D", "I0<dynamic>.M()").WithLocation(11, 21)
                );
        }
 
        [Fact]
        public void DynamicMismatch_03()
        {
            var source = @"
public interface I0<T> 
{
    void M();
}
 
public class C : I0<object>
{
    void I0<object>.M(){}
    public void M(){}
}
public class D : C, I0<dynamic>
{ }
";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (12,21): error CS1966: 'D': cannot implement a dynamic interface 'I0<dynamic>'
                // public class D : C, I0<dynamic>
                Diagnostic(ErrorCode.ERR_DeriveFromConstructedDynamic, "I0<dynamic>").WithArguments("D", "I0<dynamic>").WithLocation(12, 21),
                // (12,21): error CS0535: 'D' does not implement interface member 'I0<dynamic>.M()'
                // public class D : C, I0<dynamic>
                Diagnostic(ErrorCode.ERR_UnimplementedInterfaceMember, "I0<dynamic>").WithArguments("D", "I0<dynamic>.M()").WithLocation(12, 21)
                );
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void ImplementMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter1()
        {
            var source = @"
interface I
{
    void Goo<T>(T? value) where T : struct;
}
 
class C1 : I
{
    public void Goo<T>(T? value) where T : struct { }
}
 
class C2 : I
{
    void I.Goo<T>(T? value) { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(c2Goo.Parameters[0].Type.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void ImplementMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter2()
        {
            var source = @"
interface I
{
    void Goo<T>(T?[] value) where T : struct;
}
 
class C1 : I
{
    public void Goo<T>(T?[] value) where T : struct { }
}
 
class C2 : I
{
    void I.Goo<T>(T?[] value) { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(((ArrayTypeSymbol)c2Goo.Parameters[0].Type).ElementType.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void ImplementMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter3()
        {
            var source = @"
interface I
{
    void Goo<T>((T a, T? b)? value) where T : struct;
}
 
class C1 : I
{
    public void Goo<T>((T a, T? b)? value) where T : struct { }
}
 
class C2 : I
{
    void I.Goo<T>((T a, T? b)? value) { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(c2Goo.Parameters[0].Type.IsNullableType());
            var tuple = c2Goo.Parameters[0].Type.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0];
            Assert.False(tuple.TupleElements[0].Type.IsNullableType());
            Assert.True(tuple.TupleElements[1].Type.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void ImplementMethodReturningNullableStructParameter_WithMethodReturningNullableStruct1()
        {
            var source = @"
interface I
{
    T? Goo<T>() where T : struct;
}
 
class C1 : I
{
    public T? Goo<T>() where T : struct => default;
}
 
class C2 : I
{
    T? I.Goo<T>() => default;
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(c2Goo.ReturnType.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void ImplementMethodReturningNullableStructParameter_WithMethodReturningNullableStruct2()
        {
            var source = @"
interface I
{
    T?[] Goo<T>() where T : struct;
}
 
class C1 : I
{
    public T?[] Goo<T>() where T : struct => default;
}
 
class C2 : I
{
    T?[] I.Goo<T>() => default;
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(((ArrayTypeSymbol)c2Goo.ReturnType).ElementType.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void ImplementMethodReturningNullableStructParameter_WithMethodReturningNullableStruct3()
        {
            var source = @"
interface I
{
    (T a, T? b)? Goo<T>() where T : struct;
}
 
class C1 : I
{
    public (T a, T? b)? Goo<T>() where T : struct => default;
}
 
class C2 : I
{
    (T a, T? b)? I.Goo<T>() => default;
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(c2Goo.ReturnType.IsNullableType());
            var tuple = c2Goo.ReturnType.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0];
            Assert.False(tuple.TupleElements[0].Type.IsNullableType());
            Assert.True(tuple.TupleElements[1].Type.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void OverrideMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter1()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T? value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>(T? value) { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(dGoo.Parameters[0].Type.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void OverrideMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter2()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T?[] value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>(T?[] value) { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(((ArrayTypeSymbol)dGoo.Parameters[0].Type).ElementType.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void OverrideMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter3()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>((T a, T? b)? value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>((T a, T? b)? value) { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(dGoo.Parameters[0].Type.IsNullableType());
            var tuple = dGoo.Parameters[0].Type.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0];
            Assert.False(tuple.TupleElements[0].Type.IsNullableType());
            Assert.True(tuple.TupleElements[1].Type.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void OverrideMethodReturningNullableStructParameter_WithMethodReturningNullableStruct1()
        {
            var source = @"
abstract class Base
{
    public abstract T? Goo<T>() where T : struct;
}
 
class Derived : Base
{
    public override T? Goo<T>() => default;
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(dGoo.ReturnType.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void OverrideMethodReturningNullableStructParameter_WithMethodReturningNullableStruct2()
        {
            var source = @"
abstract class Base
{
    public abstract T?[] Goo<T>() where T : struct;
}
 
class Derived : Base
{
    public override T?[] Goo<T>() => default;
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(((ArrayTypeSymbol)dGoo.ReturnType).ElementType.IsNullableType());
        }
 
        [Fact]
        [WorkItem(34508, "https://github.com/dotnet/roslyn/issues/34508")]
        public void OverrideMethodReturningNullableStructParameter_WithMethodReturningNullableStruct3()
        {
            var source = @"
abstract class Base
{
    public abstract (T a, T? b)? Goo<T>() where T : struct;
}
 
class Derived : Base
{
    public override (T a, T? b)? Goo<T>() => default;
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(dGoo.ReturnType.IsNullableType());
            var tuple = dGoo.ReturnType.GetMemberTypeArgumentsNoUseSiteDiagnostics()[0];
            Assert.False(tuple.TupleElements[0].Type.IsNullableType());
            Assert.True(tuple.TupleElements[1].Type.IsNullableType());
        }
 
        [Fact]
        public void ImplementMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter_WithStructConstraint()
        {
            var source = @"
interface I
{
    void Goo<T>(T? value) where T : struct;
}
 
class C1 : I
{
    public void Goo<T>(T? value) where T : struct { }
}
 
class C2 : I
{
    void I.Goo<T>(T? value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var c2Goo = (MethodSymbol)comp.GetMember("C2.I.Goo");
 
            Assert.True(c2Goo.Parameters[0].Type.IsNullableType());
 
            CreateCompilation(source, parseOptions: TestOptions.Regular8).VerifyDiagnostics();
 
            CreateCompilation(source, parseOptions: TestOptions.Regular7_3).VerifyDiagnostics(
                // (14,29): error CS8652: The feature 'constraints for override and explicit interface implementation methods' is not available in C# 7.3. Please use language version 8.0 or greater.
                //     void I.Goo<T>(T? value) where T : struct { }
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "where").WithArguments("constraints for override and explicit interface implementation methods", "8.0").WithLocation(14, 29)
                );
        }
 
        [Fact]
        public void OverrideMethodTakingNullableStructParameter_WithMethodTakingNullableStructParameter_WithStructConstraint()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T? value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>(T? value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            var dGoo = (MethodSymbol)comp.GetMember("Derived.Goo");
 
            Assert.True(dGoo.Parameters[0].Type.IsNullableType());
        }
 
        [Fact]
        public void AllowStructConstraintInOverride()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void AllowClassConstraintInOverride()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : class;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
 
            CreateCompilation(source, parseOptions: TestOptions.Regular8).VerifyDiagnostics();
 
            CreateCompilation(source, parseOptions: TestOptions.Regular7_3).VerifyDiagnostics(
                // (9,42): error CS8652: The feature 'constraints for override and explicit interface implementation methods' is not available in C# 7.3. Please use language version 8.0 or greater.
                //     public override void Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "where").WithArguments("constraints for override and explicit interface implementation methods", "8.0").WithLocation(9, 42)
                );
        }
 
        [Fact]
        public void ErrorIfNonExistentTypeParameter_HasStructConstraintInOverride()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value);
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where U : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,48): error CS0699: 'Derived.Goo<T>(T)' does not define type parameter 'U'
                //     public override void Goo<T>(T value) where U : struct { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "Derived.Goo<T>(T)").WithLocation(9, 48));
        }
 
        [Fact]
        public void ErrorIfNonExistentTypeParameter_HasClassConstraintInOverride()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value);
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where U : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,48): error CS0699: 'Derived.Goo<T>(T)' does not define type parameter 'U'
                //     public override void Goo<T>(T value) where U : class { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "Derived.Goo<T>(T)").WithLocation(9, 48));
        }
 
        [Fact]
        public void ErrorIfTypeParameterDeclaredOutsideMethod_HasStructConstraintInOverride()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value);
}
 
class Derived<U> : Base
{
    public override void Goo<T>(T value) where U : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,48): error CS0699: 'Derived<U>.Goo<T>(T)' does not define type parameter 'U'
                //     public override void Goo<T>(T value) where U : struct { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "Derived<U>.Goo<T>(T)").WithLocation(9, 48));
        }
 
        [Fact]
        public void ErrorIfTypeParameterDeclaredOutsideMethod_HasClassConstraintInOverride()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value);
}
 
class Derived<U> : Base
{
    public override void Goo<T>(T value) where U : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,48): error CS0699: 'Derived<U>.Goo<T>(T)' does not define type parameter 'U'
                //     public override void Goo<T>(T value) where U : class { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "Derived<U>.Goo<T>(T)").WithLocation(9, 48));
        }
 
        [Fact]
        public void AllowStructConstraintInExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    void Goo<T>(T value) where T : struct;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void AllowClassConstraintInExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    void Goo<T>(T value) where T : class;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void ErrorIfNonExistentTypeParameter_HasStructConstraintInExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    void Goo<T>(T value);
}
 
class C : I
{
    void I.Goo<T>(T value) where U : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,34): error CS0699: 'C.I.Goo<T>(T)' does not define type parameter 'U'
                //     void I.Goo<T>(T value) where U : struct { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "C.I.Goo<T>(T)").WithLocation(9, 34));
        }
 
        [Fact]
        public void ErrorIfNonExistentTypeParameter_HasClassConstraintInExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    void Goo<T>(T value);
}
 
class C : I
{
    void I.Goo<T>(T value) where U : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,34): error CS0699: 'C.I.Goo<T>(T)' does not define type parameter 'U'
                //     void I.Goo<T>(T value) where U : class { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "C.I.Goo<T>(T)").WithLocation(9, 34));
        }
 
        [Fact]
        public void ErrorIfTypeParameterDeclaredOutsideMethod_HasStructConstraintInExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    void Goo<T>(T value);
}
 
class C<U> : I
{
    void I.Goo<T>(T value) where U : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,34): error CS0699: 'C<U>.I.Goo<T>(T)' does not define type parameter 'U'
                //     void I.Goo<T>(T value) where U : struct { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "C<U>.I.Goo<T>(T)").WithLocation(9, 34));
        }
 
        [Fact]
        public void ErrorIfTypeParameterDeclaredOutsideMethod_HasClassConstraintInExplicitInterfaceImplementation()
        {
            var source = @"
interface I
{
    void Goo<T>(T value);
}
 
class C<U> : I
{
    void I.Goo<T>(T value) where U : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,34): error CS0699: 'C<U>.I.Goo<T>(T)' does not define type parameter 'U'
                //     void I.Goo<T>(T value) where U : class { }
                Diagnostic(ErrorCode.ERR_TyVarNotFoundInConstraint, "U").WithArguments("U", "C<U>.I.Goo<T>(T)").WithLocation(9, 34));
        }
 
        [Fact]
        public void ErrorIfNonExistentTypeParameter()
        {
            var source = @"
interface I
{
    void Goo();
}
 
class C : I
{
    void I.Goo() where U : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,18): error CS0080: Constraints are not allowed on non-generic declarations
                //     void I.Goo() where U : class { }
                Diagnostic(ErrorCode.ERR_ConstraintOnlyAllowedOnGenericDecl, "where").WithLocation(9, 18)
                );
        }
 
        [Fact]
        public void ErrorIfDuplicateConstraintClause()
        {
            var source = @"
interface I
{
    void Goo<T>(T? value) where T : struct;
}
 
class C<U> : I
{
    void I.Goo<T>(T? value) where T : struct where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,52): error CS0409: A constraint clause has already been specified for type parameter 'T'. All of the constraints for a type parameter must be specified in a single where clause.
                //     void I.Goo<T>(T? value) where T : struct where T : class { }
                Diagnostic(ErrorCode.ERR_DuplicateConstraintClause, "T").WithArguments("T").WithLocation(9, 52)
                );
        }
 
        [Fact]
        public void Error_WhenOverride_HasStructAndClassConstraints1()
        {
            var source = @"
abstract class Base
{
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct, class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (8,26): error CS0115: 'Derived.Goo<T>(T)': no suitable method found to override
                //     public override void Goo<T>(T value) where T : struct, class { }
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Goo").WithArguments("Derived.Goo<T>(T)").WithLocation(8, 26),
                // (8,60): error CS0449: The 'class', 'struct', 'unmanaged', 'notnull', and 'default' constraints cannot be combined or duplicated, and must be specified first in the constraints list.
                //     public override void Goo<T>(T value) where T : struct, class { }
                Diagnostic(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, "class").WithLocation(8, 60));
        }
 
        [Fact]
        public void Error_WhenOverride_HasStructAndClassConstraints2()
        {
            var source = @"
abstract class Base
{
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class, struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (8,26): error CS0115: 'Derived.Goo<T>(T)': no suitable method found to override
                //     public override void Goo<T>(T value) where T : class, struct { }
                Diagnostic(ErrorCode.ERR_OverrideNotExpected, "Goo").WithArguments("Derived.Goo<T>(T)").WithLocation(8, 26),
                // (8,59): error CS0449: The 'class', 'struct', 'unmanaged', 'notnull', and 'default' constraints cannot be combined or duplicated, and must be specified first in the constraints list.
                //     public override void Goo<T>(T value) where T : class, struct { }
                Diagnostic(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, "struct").WithLocation(8, 59));
        }
 
        [Fact]
        public void Error_WhenOverride_HasStructAndClassConstraints3()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct, class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,60): error CS0449: The 'class', 'struct', 'unmanaged', 'notnull', and 'default' constraints cannot be combined or duplicated, and must be specified first in the constraints list.
                //     public override void Goo<T>(T value) where T : struct, class { }
                Diagnostic(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, "class").WithLocation(9, 60));
        }
 
        [Fact]
        public void Error_WhenExplicitImplementation_HasStructAndClassConstraints1()
        {
            var source = @"
interface I
{
}
 
class C : I
{
    void I.Goo<T>(T value) where T : struct, class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (8,12): error CS0539: 'C.Goo<T>(T)' in explicit interface declaration is not found among members of the interface that can be implemented
                //     void I.Goo<T>(T value) where T : struct, class { }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C.Goo<T>(T)").WithLocation(8, 12),
                // (8,46): error CS0449: The 'class', 'struct', 'unmanaged', 'notnull', and 'default' constraints cannot be combined or duplicated, and must be specified first in the constraints list.
                //     void I.Goo<T>(T value) where T : struct, class { }
                Diagnostic(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, "class").WithLocation(8, 46));
        }
 
        [Fact]
        public void Error_WhenExplicitImplementation_HasStructAndClassConstraints2()
        {
            var source = @"
interface I
{
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class, struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (8,12): error CS0539: 'C.Goo<T>(T)' in explicit interface declaration is not found among members of the interface that can be implemented
                //     void I.Goo<T>(T value) where T : class, struct { }
                Diagnostic(ErrorCode.ERR_InterfaceMemberNotFound, "Goo").WithArguments("C.Goo<T>(T)").WithLocation(8, 12),
                // (8,45): error CS0449: The 'class', 'struct', 'unmanaged', 'notnull', and 'default' constraints cannot be combined or duplicated, and must be specified first in the constraints list.
                //     void I.Goo<T>(T value) where T : class, struct { }
                Diagnostic(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, "struct").WithLocation(8, 45));
        }
 
        [Fact]
        public void Error_WhenExplicitImplementation_HasStructAndClassConstraints3()
        {
            var source = @"
interface I
{
    void Goo<T>(T value) where T : struct;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : struct, class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,46): error CS0449: The 'class', 'struct', 'unmanaged', 'notnull', and 'default' constraints cannot be combined or duplicated, and must be specified first in the constraints list.
                //     void I.Goo<T>(T value) where T : struct, class { }
                Diagnostic(ErrorCode.ERR_TypeConstraintsMustBeUniqueAndFirst, "class").WithLocation(9, 46));
        }
 
        [Fact]
        public void Error_WhenOverride_HasNullableClassConstraint()
        {
            var source = @"
#nullable enable
abstract class Base
{
    public abstract void Goo<T>(T value) where T : class?;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class? { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,52): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : class? { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "class?").WithLocation(10, 52));
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementation_HasNullableClassConstraint()
        {
            var source = @"
#nullable enable
interface I
{
    void Goo<T>(T value) where T : class?;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class? { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,38): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     void I.Goo<T>(T value) where T : class? { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "class?").WithLocation(10, 38));
        }
 
        [Fact]
        public void Error_WhenOverride_HasReferenceTypeConstraint1()
        {
            var source = @"
using System.IO;
abstract class Base
{
    public abstract void Goo<T>(T value) where T : Stream;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : Stream { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,52): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : Stream { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "Stream").WithLocation(10, 52));
        }
 
        [Fact]
        public void Error_WhenOverride_HasReferenceTypeConstraint2()
        {
            var source = @"
using System.IO;
abstract class Base
{
    public abstract void Goo<T>(T value) where T : Stream;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class, Stream { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,59): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : class, Stream { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "Stream").WithLocation(10, 59));
        }
 
        [Fact]
        public void Error_WhenOverride_HasReferenceTypeConstraint3()
        {
            var source = @"
using System.IO;
abstract class Base
{
    public abstract void Goo<T, U>(T value) where T : class where U : Stream;
}
 
class Derived : Base
{
    public override void Goo<T, U>(T value) where T : class where U : Stream { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,71): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T, U>(T value) where T : class where U Stream { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "Stream").WithLocation(10, 71));
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementation_HasReferenceTypeConstraint1()
        {
            var source = @"
using System.IO;
interface I
{
    void Goo<T>(T value) where T : Stream;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : Stream { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,38): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     void I.Goo<T>(T value) where T : Stream { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "Stream").WithLocation(10, 38));
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementation_HasReferenceTypeConstraint2()
        {
            var source = @"
using System.IO;
interface I
{
    void Goo<T>(T value) where T : Stream;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class, Stream { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,45): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     void I.Goo<T>(T value) where T : class, Stream { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "Stream").WithLocation(10, 45));
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementation_HasReferenceTypeConstraint3()
        {
            var source = @"
using System.IO;
interface I
{
    void Goo<T, U>(T value) where T : class where U : Stream;
}
 
class C : I
{
    void I.Goo<T, U>(T value) where T : class where U : Stream { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,57): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     void I.Goo<T, U>(T value) where T : class where U : Stream { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "Stream").WithLocation(10, 57));
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementationHasStructConstraint_AndInterfaceDoesNot1()
        {
            var source = @"
interface I
{
    void Goo<U>(U value);
}
 
class C : I
{
    void I.Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,16): error CS8666: Method 'C.I.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'U' of overridden or explicitly implemented method 'I.Goo<U>(U)' is not a non-nullable value type.
                //     void I.Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("C.I.Goo<T>(T)", "T", "U", "I.Goo<U>(U)").WithLocation(9, 16)
                );
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementationHasStructConstraint_AndInterfaceDoesNot2()
        {
            var source = @"
interface I
{
    void Goo<T>(T value) where T : class;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,16): error CS8666: Method 'C.I.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'I.Goo<T>(T)' is not a non-nullable value type.
                //     void I.Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("C.I.Goo<T>(T)", "T", "T", "I.Goo<T>(T)").WithLocation(9, 16)
                );
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementationHasStructConstraint_AndInterfaceDoesNot3()
        {
            var source = @"
using System.IO;
interface I
{
    void Goo<T>(T value) where T : Stream;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,16): error CS8666: Method 'C.I.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'I.Goo<T>(T)' is not a non-nullable value type.
                //     void I.Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("C.I.Goo<T>(T)", "T", "T", "I.Goo<T>(T)").WithLocation(10, 16)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasStructConstraint_AndOverriddenDoesNot1()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value);
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,30): error CS8666: Method 'Derived.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a non-nullable value type.
                //     public override void Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(9, 30)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasStructConstraint_AndOverriddenDoesNot2()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : class;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,30): error CS8666: Method 'Derived.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a non-nullable value type.
                //     public override void Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(9, 30)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasStructConstraint_AndOverriddenDoesNot3()
        {
            var source = @"
using System.IO;
abstract class Base
{
    public abstract void Goo<T>(T value) where T : Stream;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,30): error CS8666: Method 'Derived.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a non-nullable value type.
                //     public override void Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(10, 30)
                );
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementationHasClassConstraint_AndInterfaceDoesNot1()
        {
            var source = @"
interface I
{
    void Goo<U>(U value);
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,16): error CS8665: Method 'C.I.Goo<T>(T)' specifies a 'class' constraint for type parameter 'T', but corresponding type parameter 'U' of overridden or explicitly implemented method 'I.Goo<U>(U)' is not a reference type.
                //     void I.Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_OverrideRefConstraintNotSatisfied, "T").WithArguments("C.I.Goo<T>(T)", "T", "U", "I.Goo<U>(U)").WithLocation(9, 16)
                );
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementationHasClassConstraint_AndInterfaceDoesNot2()
        {
            var source = @"
interface I
{
    void Goo<T>(T value) where T : struct;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,16): error CS8665: Method 'C.I.Goo<T>(T)' specifies a 'class' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'I.Goo<T>(T)' is not a reference type.
                //     void I.Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_OverrideRefConstraintNotSatisfied, "T").WithArguments("C.I.Goo<T>(T)", "T", "T", "I.Goo<T>(T)").WithLocation(9, 16)
                );
        }
 
        [Fact]
        public void Error_WhenExplicitInterfaceImplementationHasClassConstraint_AndInterfaceDoesNot3()
        {
            var source = @"
using System;
interface I
{
    void Goo<T>(T value) where T : Enum;
}
 
class C : I
{
    void I.Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,16): error CS8665: Method 'C.I.Goo<T>(T)' specifies a 'class' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'I.Goo<T>(T)' is not a reference type.
                //     void I.Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_OverrideRefConstraintNotSatisfied, "T").WithArguments("C.I.Goo<T>(T)", "T", "T", "I.Goo<T>(T)").WithLocation(10, 16)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasClassConstraint_AndOverriddenDoesNot1()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value);
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,30): error CS8665: Method 'Derived.Goo<T>(T)' specifies a 'class' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a reference type.
                //     public override void Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_OverrideRefConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(9, 30)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasClassConstraint_AndOverriddenDoesNot2()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : struct;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,30): error CS8665: Method 'Derived.Goo<T>(T)' specifies a 'class' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a reference type.
                //     public override void Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_OverrideRefConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(9, 30)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasClassConstraint_AndOverriddenDoesNot3()
        {
            var source = @"
using System;
abstract class Base
{
    public abstract void Goo<T>(T value) where T : Enum;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,30): error CS8665: Method 'Derived.Goo<T>(T)' specifies a 'class' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a reference type.
                //     public override void Goo<T>(T value) where T : class { }
                Diagnostic(ErrorCode.ERR_OverrideRefConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(10, 30)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasStructConstraint_AndOverriddenHasEnumConstraint()
        {
            var source = @"
using System;
abstract class Base
{
    public abstract void Goo<T>(T value) where T : Enum;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (10,30): error CS8666: Method 'Derived.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base.Goo<T>(T)' is not a non-nullable value type.
                //     public override void Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base.Goo<T>(T)").WithLocation(10, 30)
                );
        }
 
        [Fact]
        public void Error_WhenOverrideHasStructConstraint_AndOverriddenHasNullableConstraint()
        {
            var source = @"
abstract class Base<U>
{
    public abstract void Goo<T>(T value) where T : U;
}
 
class Derived : Base<int?>
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,30): error CS8666: Method 'Derived.Goo<T>(T)' specifies a 'struct' constraint for type parameter 'T', but corresponding type parameter 'T' of overridden or explicitly implemented method 'Base<int?>.Goo<T>(T)' is not a non-nullable value type.
                //     public override void Goo<T>(T value) where T : struct { }
                Diagnostic(ErrorCode.ERR_OverrideValConstraintNotSatisfied, "T").WithArguments("Derived.Goo<T>(T)", "T", "T", "Base<int?>.Goo<T>(T)").WithLocation(9, 30)
                );
        }
 
        [Fact]
        public void NoError_WhenOverrideHasStructConstraint_AndOverriddenHasUnmanagedConstraint()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : unmanaged;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : struct { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void NoError_WhenOverrideHasClassConstraint_AndOverriddenHasReferenceTypeConstraint()
        {
            var source = @"
using System.IO;
abstract class Base
{
    public abstract void Goo<T>(T value) where T : Stream;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        public void Error_WhenOverride_HasDefaultConstructorConstraint1()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : new();
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : new() { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,52): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : new() { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "new()").WithLocation(9, 52)
                );
        }
 
        [Fact]
        public void Error_WhenOverride_HasDefaultConstructorConstraint2()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : class, new();
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : class, new() { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,59): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : class, new() { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "new()").WithLocation(9, 59)
                );
        }
 
        [Fact]
        public void Error_WhenOverride_HasUnmanagedConstraint1()
        {
            var source = @"
abstract class Base
{
    public abstract void Goo<T>(T value) where T : unmanaged;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : unmanaged { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (9,52): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : unmanaged { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "unmanaged").WithLocation(9, 52)
                );
        }
 
        [Fact]
        public void Error_WhenOverride_HasUnmanagedConstraint2()
        {
            var source = @"
interface I {}
 
abstract class Base
{
    public abstract void Goo<T>(T value) where T : unmanaged, I;
}
 
class Derived : Base
{
    public override void Goo<T>(T value) where T : unmanaged, I { }
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics(
                // (11,52): error CS0460: Constraints for override and explicit interface implementation methods are inherited from the base method, so they cannot be specified directly, except for either a 'class', or a 'struct' constraint.
                //     public override void Goo<T>(T value) where T : unmanaged, I { }
                Diagnostic(ErrorCode.ERR_OverrideWithConstraints, "unmanaged").WithLocation(11, 52)
                );
        }
 
        [Fact]
        [WorkItem(34583, "https://github.com/dotnet/roslyn/issues/34583")]
        public void ExplicitImplementationOfNullableStructWithMultipleTypeParameters()
        {
            var source = @"
interface I
{
    void Goo<T, U>(T? value) where T : struct;
}
 
class C1 : I
{
    public void Goo<T, U>(T? value) where T : struct {}
}
 
class C2 : I
{
    void I.Goo<T, U>(T? value) {}
}
";
            var comp = CreateCompilation(source).VerifyDiagnostics();
        }
 
        [Fact]
        [WorkItem(63490, "https://github.com/dotnet/roslyn/issues/63490")]
        public void MultipleBasesWithObliviousDifferencesAndInterfaces()
        {
            var source1 = @"
#nullable enable
interface ITest
{
    void Test();
}
 
class Generic<T> { }
class Argument { }
partial class Partial : Generic<Argument> { }
";
 
            var source2 = @"
#nullable disable
partial class Partial : Generic<Argument>, ITest
{
    void ITest.Test() { }
}
";
            CreateCompilation(source1 + source2).VerifyDiagnostics();
            CreateCompilation(source2 + source1).VerifyDiagnostics();
        }
    }
}