File: Symbols\Source\BaseClassTests.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Symbol\Microsoft.CodeAnalysis.CSharp.Symbol.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Symbol.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.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Emit;
using Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using Retargeting = Microsoft.CodeAnalysis.CSharp.Symbols.Retargeting;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
    public class BaseClassTests : CSharpTestBase
    {
        [Fact]
        public void CyclicBases1()
        {
            var text =
@"
class X : Y {}
class Y : X {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var x = global.GetTypeMembers("X", 0).Single();
            var y = global.GetTypeMembers("Y", 0).Single();
            Assert.NotEqual(y, x.BaseType());
            Assert.NotEqual(x, y.BaseType());
            Assert.Equal(SymbolKind.ErrorType, x.BaseType().Kind);
            Assert.Equal(SymbolKind.ErrorType, y.BaseType().Kind);
            Assert.Equal("Y", x.BaseType().Name);
            Assert.Equal("X", y.BaseType().Name);
        }
 
        [Fact]
        public void CyclicBases2()
        {
            var text =
@"
class X : Y.n {}
class Y : X.n {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var x = global.GetTypeMembers("X", 0).Single();
            var y = global.GetTypeMembers("Y", 0).Single();
            Assert.NotEqual(y, x.BaseType());
            Assert.NotEqual(x, y.BaseType());
            Assert.Equal(SymbolKind.ErrorType, x.BaseType().Kind);
            Assert.Equal(SymbolKind.ErrorType, y.BaseType().Kind);
            Assert.Equal("n", x.BaseType().Name);
            Assert.Equal("n", y.BaseType().Name);
        }
 
        [Fact]
        public void CyclicBases3()
        {
            var C1 = TestReferences.SymbolsTests.CyclicInheritance.Class1;
            var C2 = TestReferences.SymbolsTests.CyclicInheritance.Class2;
 
            var text =
@"
class C4 : C1 {}
";
 
            var comp = CreateCompilation(text, new[] { C1, C2 });
            var global = comp.GlobalNamespace;
            var x = global.GetTypeMembers("C4", 0).Single();
 
            var x_base_base = x.BaseType().BaseType() as ErrorTypeSymbol;
            var er = x_base_base.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'C2' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
        }
 
        [WorkItem(538506, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538506")]
        [Fact]
        public void CyclicBasesRegress4140()
        {
            var text =
@"
class A<T>
{
    class B : A<E> { }
    class E : B.E { }
}
 
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 1).Single();
            var b = a.GetTypeMembers("B", 0).Single();
            var e = a.GetTypeMembers("E", 0).Single();
            Assert.NotEqual(e, e.BaseType());
 
            var x_base = e.BaseType() as ErrorTypeSymbol;
            var er = x_base.ErrorInfo;
 
            Assert.Equal("error CS0146: Circular base type dependency involving 'A<A<T>.E>.E' and 'A<T>.E'",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
        }
 
        [WorkItem(538526, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/538526")]
        [Fact]
        public void CyclicBasesRegress4166()
        {
            var text =
@"
class A<T> {
    public class C : B.D { }
}
 
class B {
    public class D : A<int>.C { }
}
 
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 1).Single();
            var b = global.GetTypeMembers("B", 0).Single();
            var d = b.GetTypeMembers("D", 0).Single();
            Assert.NotEqual(d, d.BaseType());
 
            var x_base = d.BaseType() as ErrorTypeSymbol;
            var er = x_base.ErrorInfo;
 
            Assert.Equal("error CS0146: Circular base type dependency involving 'A<int>.C' and 'B.D'",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
        }
 
        [WorkItem(4169, "DevDiv_Projects/Roslyn")]
        [Fact]
        public void CyclicBasesRegress4169()
        {
            var text =
@"
class A : object, A.IC
{
    protected interface IC { }
}
 
";
            var comp = CreateCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 0).Single();
            var ic = a.GetTypeMembers("IC", 0).Single();
            Assert.Equal(a.Interfaces()[0], ic);
 
            var diagnostics = comp.GetDeclarationDiagnostics();
            Assert.Equal(0, diagnostics.Count());
        }
 
        [WorkItem(527551, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/527551")]
        [Fact]
        public void CyclicBasesRegress4168()
        {
            var text =
@"
class A : object, A.B.B.IC
{
    public class B : A {
        public interface IC { }
    }
}
";
            var comp = CreateCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 0).Single();
            var b = a.GetTypeMembers("B", 0).Single();
            var ic = b.GetTypeMembers("IC", 0).Single();
            Assert.NotEqual(b, b.BaseType());
            Assert.NotEqual(a, b.BaseType());
            Assert.Equal(SymbolKind.ErrorType, a.Interfaces()[0].Kind);
            Assert.NotEqual(ic, a.Interfaces()[0]);
 
            var diagnostics = comp.GetDeclarationDiagnostics();
            Assert.Equal(2, diagnostics.Count());
        }
 
        [Fact]
        public void CyclicBases4()
        {
            var text =
@"
class A<T> : B<A<T>> { }
class B<T> : A<B<T>> {
    A<T> F() { return null; }
}
";
            var comp = CreateCompilation(text);
            comp.GetDeclarationDiagnostics().Verify(
    // (2,7): error CS0146: Circular base type dependency involving 'B<A<T>>' and 'A<T>'
    // class A<T> : B<A<T>> { }
    Diagnostic(ErrorCode.ERR_CircularBase, "A").WithArguments("B<A<T>>", "A<T>"),
    // (3,7): error CS0146: Circular base type dependency involving 'A<B<T>>' and 'B<T>'
    // class B<T> : A<B<T>> {
    Diagnostic(ErrorCode.ERR_CircularBase, "B").WithArguments("A<B<T>>", "B<T>")
                );
        }
 
        [Fact]
        public void CyclicBases5()
        {
            // bases are cyclic, but you can still find members when binding bases
            var text =
@"
class A : B {
  public class X { }
}
 
class B : A {
  public class Y { }
}
 
class Z : A.Y { }
class W : B.X { }
 
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var z = global.GetTypeMembers("Z", 0).Single();
            var w = global.GetTypeMembers("W", 0).Single();
            var zBase = z.BaseType();
            Assert.Equal("Y", zBase.Name);
            var wBase = w.BaseType();
            Assert.Equal("X", wBase.Name);
        }
 
        [Fact]
        public void CyclicBases6()
        {
            // bases are cyclic, but you can still search for members w/o infinite looping in binder
            var text =
@"
class A : B {
  public class X {}
}
 
class B : C {
  public class Y {}
}
 
class C : A {
  public class Z {}
}
 
";
            var comp = (Compilation)CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 0).Single();
 
            //var aBase = a.BaseType();
            //Assert.True(aBase.IsErrorType());
            //Assert.Equal("B", aBase.Name);
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var classA = (TypeDeclarationSyntax)tree.GetCompilationUnitRoot().Members[0];
            var someMemberInA = classA.Members[0];
            int positionInA = someMemberInA.SpanStart;
 
            var members = model.LookupSymbols(positionInA, a, "Z");
            Assert.Equal(1, members.Length);
            Assert.False(((ITypeSymbol)members[0]).IsErrorType());
            Assert.Equal("C.Z", members[0].ToTestDisplayString());
 
            var members2 = model.LookupSymbols(positionInA, a, "Q");
            Assert.Equal(0, members2.Length);
        }
 
        [Fact]
        public void CyclicBases7()
        {
            // bases are cyclic, but you can still search for members w/o infinite looping in binder
            var text =
@"
class A : B<A.Y> {
  public class X {}
}
 
class B<T> : A {
  public class Y {}
}
";
            var comp = (Compilation)CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 0).Single();
 
            //var aBase = a.BaseType();
            //Assert.True(aBase.IsErrorType());
            //Assert.Equal("B", aBase.Name);
 
            var tree = comp.SyntaxTrees.First();
            var model = comp.GetSemanticModel(tree);
            var classA = (TypeDeclarationSyntax)tree.GetCompilationUnitRoot().Members[0];
            var someMemberInA = classA.Members[0];
            int positionInA = someMemberInA.SpanStart;
 
            var members = model.LookupSymbols(positionInA, a, "Q");
            Assert.Equal(0, members.Length);
        }
 
        [Fact]
        public void CyclicBases8()
        {
            var text = @"
public class A
{
    protected class B
    {
        protected class C
        {
            public class X { }
        }
    }
}
internal class F : A
{
    private class D : B
    {
        public class E : C.X { }
    }
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (16,22): error CS0060: Inconsistent accessibility: base type 'A.B.C.X' is less accessible than class 'F.D.E'
                //         public class E : C.X { }
                Diagnostic(ErrorCode.ERR_BadVisBaseClass, "E").WithArguments("F.D.E", "A.B.C.X")
                );
        }
 
        [Fact, WorkItem(7878, "https://github.com/dotnet/roslyn/issues/7878")]
        public void BadVisibilityPartial()
        {
            var text = @"
internal class NV
{
}
 
public partial class C1
{
}
 
partial class C1 : NV
{
}
 
public partial class C1
{
}
";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (10,15): error CS0060: Inconsistent accessibility: base type 'NV' is less accessible than class 'C1'
                // partial class C1 : NV
                Diagnostic(ErrorCode.ERR_BadVisBaseClass, "C1").WithArguments("C1", "NV").WithLocation(10, 15));
        }
 
        [Fact, WorkItem(7878, "https://github.com/dotnet/roslyn/issues/7878")]
        public void StaticBasePartial()
        {
            var text = @"
static class NV
{
}
 
public partial class C1
{
}
 
partial class C1 : NV
{
}
 
public partial class C1
{
}
";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (10,15): error CS0709: 'C1': cannot derive from static class 'NV'
                // partial class C1 : NV
                Diagnostic(ErrorCode.ERR_StaticBaseClass, "C1").WithArguments("NV", "C1").WithLocation(10, 15),
                // (10,15): error CS0060: Inconsistent accessibility: base type 'NV' is less accessible than class 'C1'
                // partial class C1 : NV
                Diagnostic(ErrorCode.ERR_BadVisBaseClass, "C1").WithArguments("C1", "NV").WithLocation(10, 15));
        }
 
        [Fact, WorkItem(7878, "https://github.com/dotnet/roslyn/issues/7878")]
        public void BadVisInterfacePartial()
        {
            var text = @"
interface IGoo
{
    void Moo();
}
 
interface IBaz
{
    void Noo();
}
 
interface IBam
{
    void Zoo();
}
 
public partial interface IBar
{
}
 
partial interface IBar : IGoo, IBam
{
}
 
partial interface IBar : IBaz, IBaz
{
}
";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (25,32): error CS0528: 'IBaz' is already listed in interface list
                // partial interface IBar : IBaz, IBaz
                Diagnostic(ErrorCode.ERR_DuplicateInterfaceInBaseList, "IBaz").WithArguments("IBaz").WithLocation(25, 32),
                // (21,19): error CS0061: Inconsistent accessibility: base interface 'IGoo' is less accessible than interface 'IBar'
                // partial interface IBar : IGoo, IBam
                Diagnostic(ErrorCode.ERR_BadVisBaseInterface, "IBar").WithArguments("IBar", "IGoo").WithLocation(21, 19),
                // (21,19): error CS0061: Inconsistent accessibility: base interface 'IBam' is less accessible than interface 'IBar'
                // partial interface IBar : IGoo, IBam
                Diagnostic(ErrorCode.ERR_BadVisBaseInterface, "IBar").WithArguments("IBar", "IBam").WithLocation(21, 19),
                // (25,19): error CS0061: Inconsistent accessibility: base interface 'IBaz' is less accessible than interface 'IBar'
                // partial interface IBar : IBaz, IBaz
                Diagnostic(ErrorCode.ERR_BadVisBaseInterface, "IBar").WithArguments("IBar", "IBaz").WithLocation(25, 19));
        }
 
        [Fact]
        public void EricLiCase1()
        {
            // should not be cyclic
            var text =
@"
interface I<T> {}
class A {
    public class B {}
}
class C : A, I<C.B> {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var c = global.GetTypeMembers("C", 0).Single();
            var cBase = c.BaseType();
            Assert.False(cBase.IsErrorType());
            Assert.Equal("A", cBase.Name);
            Assert.True(c.Interfaces().Single().TypeArguments().Single().IsErrorType()); //can't see base of C while evaluating C.B
        }
 
        [Fact]
        public void EricLiCase2()
        {
            // should not be cyclic
            var text =
@"
interface I<T> {}
class E : I<E> {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var e = global.GetTypeMembers("E", 0).Single();
            Assert.Equal(1, e.Interfaces().Length);
            Assert.Equal("I<E>", e.Interfaces()[0].ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase3()
        {
            // should not be cyclic
            var text =
@"
interface I<T> {}
class G : I<G.H> {
    public class H {}
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var g = global.GetTypeMembers("G", 0).Single();
            Assert.Equal(1, g.Interfaces().Length);
            Assert.Equal("I<G.H>", g.Interfaces()[0].ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase4()
        {
            // should not be cyclic
            var text =
@"
interface I<T> {}
class J : I<J.K.L> {
    public class K {
        public class L {}
    }
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var j = global.GetTypeMembers("J", 0).Single();
            Assert.Equal(1, j.Interfaces().Length);
            Assert.Equal("I<J.K.L>", j.Interfaces()[0].ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase5()
        {
            // should be cyclic
            var text =
@"class M : M {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var m = global.GetTypeMembers("M", 0).Single();
            Assert.True(m.BaseType().IsErrorType());
        }
 
        [Fact]
        public void EricLiCase6()
        {
            // should not be cyclic
            var text =
@"
class N<T> {}
class O : N<O> {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var o = global.GetTypeMembers("O", 0).Single();
            Assert.False(o.BaseType().IsErrorType());
            Assert.Equal("N<O>", o.BaseType().ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase7()
        {
            // should not be cyclic
            var text =
@"
class N<T> {}
class P : N<P.Q> {
    public class Q {}
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var p = global.GetTypeMembers("P", 0).Single();
            Assert.False(p.BaseType().IsErrorType());
            Assert.Equal("N<P.Q>", p.BaseType().ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase8()
        {
            // should not be cyclic
            var text =
@"
class N<T> {}
class R : N<R.S.T>{
    public class S {
        public class T {}
    }
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var r = global.GetTypeMembers("R", 0).Single();
            var rBase = r.BaseType();
            Assert.False(rBase.IsErrorType());
            Assert.Equal("N<R.S.T>", rBase.ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase9()
        {
            // should not be cyclic, legal to implement an inner interface
            var text =
@"
class U : U.I
{
   public interface I {};
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var u = global.GetTypeMembers("U", 0).Single();
            var ifaces = u.Interfaces();
            Assert.Equal(1, ifaces.Length);
            Assert.False(ifaces[0].IsErrorType());
            Assert.Equal("U.I", ifaces[0].ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase10()
        {
            // should not be cyclic, legal to implement an inner interface
            var text =
@"
interface IX : C.IY {}
class C : IX {
    public interface IY {}
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var c = global.GetTypeMembers("C", 0).Single();
            var ifaces = c.Interfaces();
            Assert.Equal(1, ifaces.Length);
            Assert.False(ifaces[0].IsErrorType());
            Assert.Equal("IX", ifaces[0].ToTestDisplayString());
            var ix = ifaces[0];
            var ixFaces = ix.Interfaces();
            Assert.Equal(1, ixFaces.Length);
            Assert.False(ixFaces[0].IsErrorType());
            Assert.Equal("C.IY", ixFaces[0].ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase11()
        {
            // should not be cyclic, legal to implement an inner interface
            var text =
@"
class X : Y.I {}
class Y : X {
    public interface I {}
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var x = global.GetTypeMembers("X", 0).Single();
            var ifaces = x.Interfaces();
            Assert.Equal(1, ifaces.Length);
            Assert.False(ifaces[0].IsErrorType());
            Assert.Equal("Y.I", ifaces[0].ToTestDisplayString());
        }
 
        [Fact]
        public void EricLiCase12()
        {
            // G should not be in scope
            var text =
@"
class B : G { 
   public class G {} 
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var b = global.GetTypeMembers("B", 0).Single();
            Assert.True(b.BaseType().IsErrorType());
        }
 
        [Fact]
        public void EricLiCase14()
        {
            // this should be cyclic
            var text =
@"
   class B {}
   class D {}
   class Z<T> : E<B> {}
   class E<U> : Z<D> {}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var z = global.GetTypeMembers("Z", 1).Single();
            Assert.True(z.BaseType().IsErrorType());
        }
 
        [Fact]
        public void VladResCase01()
        {
            var text = @"
class A : A { } 
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (2,7): error CS0146: Circular base type dependency involving 'A' and 'A'
                Diagnostic(ErrorCode.ERR_CircularBase, "A").WithArguments("A", "A"));
        }
 
        [Fact]
        public void VladResCase02()
        {
            var text = @"
class A : B { }
class B : A { } 
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (2,7): error CS0146: Circular base type dependency involving 'B' and 'A'
                Diagnostic(ErrorCode.ERR_CircularBase, "A").WithArguments("B", "A"),
                // (3,7): error CS0146: Circular base type dependency involving 'A' and 'B'
                Diagnostic(ErrorCode.ERR_CircularBase, "B").WithArguments("A", "B"));
        }
 
        [Fact]
        public void VladResCase03()
        {
            var text = @"
class A : A.B
{
    public class B { }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (2,7): error CS0146: Circular base type dependency involving 'A.B' and 'A'
                Diagnostic(ErrorCode.ERR_CircularBase, "A").WithArguments("A.B", "A"));
        }
 
        [Fact]
        public void VladResCase04()
        {
            var text = @"
class A : A.I
{
    public interface I { }
}
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase05()
        {
            var text = @"
class A : A.I
{
    private interface I { }
}
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase06()
        {
            var text = @"
class A : A.B.I
{
    private class B : A
    {
        public interface I { }
    }
}
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase07()
        {
            var text = @"
class A : A.B.B.I
{
    private class B : A
    {
        public interface I { }
    }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_CircularBase, "A").WithArguments("A", "A.B"),
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "B").WithArguments("B", "A.B"));
        }
 
        [Fact]
        public void VladResCase08()
        {
            var text = @"
class A : C<A.B>
{
    public class B
    {
    }
}
 
class C<T> { }
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase09()
        {
            var text = @"
class A : C<A.B.D>
{
    public class B
    {
        public class D { }
    }
}
 
class C<T> { }
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase10()
        {
            var text = @"
class A : C<A.B.B>
{
    public class B : A { }
}
 
class C<T> { }
";
 
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_CircularBase, "A").WithArguments("A", "A.B"),
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "B").WithArguments("B", "A.B"));
        }
 
        [Fact]
        public void VladResCase11()
        {
            var text = @"
class A : C<E>
{
    public class B
    {
        public class D { }
    }
}
class C<T> { }
class E : A.B.D { }
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase12()
        {
            var text = @"
class A : C<E.F>
{
    public class B
    {
        public class D
        {
            public class F { }
        }
    }
}
class C<T> { }
class E : A.B.D { }
";
 
            CreateCompilation(text).VerifyDiagnostics();
        }
 
        [Fact]
        public void VladResCase13()
        {
            var text = @"
class A<T>
{
    public class B { }
}
 
class C : A<D.B> { }
 
class D : C { }
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (7,15): error CS0426: The type name 'B' does not exist in the type 'D'
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "B").WithArguments("B", "D"));
        }
 
        [Fact]
        public void VladResCase14()
        {
            var text = @"
class A<T>
{
    public class B { }
}
 
class C : A<C>, I<C.B> { }
 
interface I<T> { }
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (7,21): error CS0146: Circular base type dependency involving 'C' and 'C'
                Diagnostic(ErrorCode.ERR_CircularBase, "B").WithArguments("C", "C"));
        }
 
        [Fact]
        public void VladResCase15()
        {
            var text = @"
class X
{
    public interface Z { }
}
 
class A
{
    public class X
    {
        public class V { }
    }
}
 
class B : A, B.Y.Z
{
    public class Y : X { }
    public class C : B.Y.V { }
}
";
 
            CreateCompilation(text).VerifyDiagnostics(
                Diagnostic(ErrorCode.ERR_CircularBase, "X").WithArguments("B", "B.Y"),
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "Z").WithArguments("Z", "B.Y"),
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "V").WithArguments("V", "B.Y"));
        }
 
        [Fact]
        public void VladResCase16()
        {
            var text = @"
class X
{
    public interface Z { }
}
 
class A<T>
{
    public class X
    {
        public class V { }
    }
}
 
class B : A<B.Y.Z>
{
    public class Y : X { }
    public class C : B.Y.V { }
}
 
";
 
            CreateCompilation(text).VerifyDiagnostics(
                // (15,17): error CS0146: Circular base type dependency involving 'B.Y' and 'B'
                Diagnostic(ErrorCode.ERR_CircularBase, "X").WithArguments("B", "B.Y"),
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "Z").WithArguments("Z", "B.Y"),
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "V").WithArguments("V", "B.Y"));
        }
 
        [Fact]
        public void CyclicInterfaces3()
        {
            var C1 = TestReferences.SymbolsTests.CyclicInheritance.Class1;
            var C2 = TestReferences.SymbolsTests.CyclicInheritance.Class2;
 
            var text =
@"
interface I4 : I1 {}
";
            var comp = CreateCompilation(text, new[] { C1, C2 });
            var global = comp.GlobalNamespace;
            var x = global.GetTypeMembers("I4", 0).Single();
 
            var x_base_base = x.Interfaces().First().Interfaces().First() as ErrorTypeSymbol;
            var er = x_base_base.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'I2' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
        }
 
        [Fact]
        public void CyclicRetargeted4()
        {
            var ClassAv1 = TestReferences.SymbolsTests.RetargetingCycle.V1.ClassA.dll;
 
            var text =
@"
public class ClassB : ClassA {}
";
            var comp = CreateCompilation(text, new[] { ClassAv1 }, assemblyName: "ClassB");
 
            var global1 = comp.GlobalNamespace;
            var B1 = global1.GetTypeMembers("ClassB", 0).Single();
            var A1 = global1.GetTypeMembers("ClassA", 0).Single();
 
            var B_base = B1.BaseType();
            var A_base = A1.BaseType();
            Assert.True(B1.IsFromCompilation(comp));
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B_base);
            Assert.IsAssignableFrom<PENamedTypeSymbol>(A_base);
 
            var ClassAv2 = TestReferences.SymbolsTests.RetargetingCycle.V2.ClassA.dll;
            text =
@"
public class ClassC : ClassB {}
";
 
            var comp2 = CreateCompilation(text, new MetadataReference[] { ClassAv2, new CSharpCompilationReference(comp) });
 
            var global = comp2.GlobalNamespace;
            var B2 = global.GetTypeMembers("ClassB", 0).Single();
            var C = global.GetTypeMembers("ClassC", 0).Single();
 
            Assert.IsType<Retargeting.RetargetingNamedTypeSymbol>(B2);
            Assert.Same(B1, ((Retargeting.RetargetingNamedTypeSymbol)B2).UnderlyingNamedType);
            Assert.Same(C.BaseType(), B2);
            Assert.False(B2.IsSerializable);
 
            var errorBase = B2.BaseType() as ErrorTypeSymbol;
            var er = errorBase.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassA' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
 
            var A2 = global.GetTypeMembers("ClassA", 0).Single();
 
            var errorBase1 = A2.BaseType() as ErrorTypeSymbol;
            er = errorBase1.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassB' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
        }
 
        [Fact]
        public void CyclicRetargeted5()
        {
            var ClassAv1 = TestReferences.SymbolsTests.RetargetingCycle.V1.ClassA.dll;
            var ClassBv1 = TestReferences.SymbolsTests.RetargetingCycle.V1.ClassB.netmodule;
 
            var text = @"// hi";
            var comp = CreateCompilation(text, new[]
                {
                    ClassAv1,
                    ClassBv1
                },
                assemblyName: "ClassB");
 
            var global1 = comp.GlobalNamespace;
            var B1 = global1.GetTypeMembers("ClassB", 0).Distinct().Single();
            var A1 = global1.GetTypeMembers("ClassA", 0).Single();
 
            var B_base = B1.BaseType();
            var A_base = A1.BaseType();
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B1);
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B_base);
            Assert.IsAssignableFrom<PENamedTypeSymbol>(A_base);
 
            var ClassAv2 = TestReferences.SymbolsTests.RetargetingCycle.V2.ClassA.dll;
            text =
@"
public class ClassC : ClassB {}
";
 
            var comp2 = CreateCompilation(text, new MetadataReference[]
            {
                ClassAv2,
                new CSharpCompilationReference(comp)
            });
 
            var global = comp2.GlobalNamespace;
            var B2 = global.GetTypeMembers("ClassB", 0).Single();
            var C = global.GetTypeMembers("ClassC", 0).Single();
 
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B2);
            Assert.NotEqual(B1, B2);
            Assert.Same(((PEModuleSymbol)B1.ContainingModule).Module, ((PEModuleSymbol)B2.ContainingModule).Module);
            Assert.Equal(((PENamedTypeSymbol)B1).Handle, ((PENamedTypeSymbol)B2).Handle);
            Assert.Same(C.BaseType(), B2);
 
            var errorBase = B2.BaseType() as ErrorTypeSymbol;
            var er = errorBase.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassA' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
 
            var A2 = global.GetTypeMembers("ClassA", 0).Single();
 
            var errorBase1 = A2.BaseType() as ErrorTypeSymbol;
            er = errorBase1.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassB' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
        }
 
        [Fact]
        public void CyclicRetargeted6()
        {
            var ClassAv2 = TestReferences.SymbolsTests.RetargetingCycle.V2.ClassA.dll;
 
            var text =
@"
public class ClassB : ClassA {}
";
            var comp = CreateCompilation(text, new[] { ClassAv2 }, assemblyName: "ClassB");
 
            var global1 = comp.GlobalNamespace;
            var B1 = global1.GetTypeMembers("ClassB", 0).Single();
            var A1 = global1.GetTypeMembers("ClassA", 0).Single();
 
            var B_base = B1.BaseType();
            var A_base = A1.BaseType();
 
            Assert.True(B1.IsFromCompilation(comp));
 
            var errorBase = B_base as ErrorTypeSymbol;
            var er = errorBase.ErrorInfo;
 
            Assert.Equal("error CS0146: Circular base type dependency involving 'ClassA' and 'ClassB'",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
 
            var errorBase1 = A_base as ErrorTypeSymbol;
            er = errorBase1.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassB' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
 
            var ClassAv1 = TestReferences.SymbolsTests.RetargetingCycle.V1.ClassA.dll;
            text =
@"
public class ClassC : ClassB {}
";
 
            var comp2 = CreateCompilation(text, new MetadataReference[]
            {
                ClassAv1,
                new CSharpCompilationReference(comp),
            });
 
            var global = comp2.GlobalNamespace;
            var A2 = global.GetTypeMembers("ClassA", 0).Single();
            var B2 = global.GetTypeMembers("ClassB", 0).Single();
            var C = global.GetTypeMembers("ClassC", 0).Single();
 
            Assert.IsType<Retargeting.RetargetingNamedTypeSymbol>(B2);
            Assert.Same(B1, ((Retargeting.RetargetingNamedTypeSymbol)B2).UnderlyingNamedType);
            Assert.Same(C.BaseType(), B2);
            Assert.Same(B2.BaseType(), A2);
        }
 
        [Fact]
        public void CyclicRetargeted7()
        {
            var ClassAv2 = TestReferences.SymbolsTests.RetargetingCycle.V2.ClassA.dll;
            var ClassBv1 = TestReferences.SymbolsTests.RetargetingCycle.V1.ClassB.netmodule;
 
            var text = @"// hi";
            var comp = CreateCompilation(text, new MetadataReference[]
                {
                    ClassAv2,
                    ClassBv1,
                },
                assemblyName: "ClassB");
 
            var global1 = comp.GlobalNamespace;
            var B1 = global1.GetTypeMembers("ClassB", 0).Distinct().Single();
            var A1 = global1.GetTypeMembers("ClassA", 0).Single();
 
            var B_base = B1.BaseType();
            var A_base = A1.BaseType();
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B1);
 
            var errorBase = B_base as ErrorTypeSymbol;
            var er = errorBase.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassA' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
 
            var errorBase1 = A_base as ErrorTypeSymbol;
            er = errorBase1.ErrorInfo;
 
            Assert.Equal("error CS0268: Imported type 'ClassB' is invalid. It contains a circular base type dependency.",
                er.ToString(EnsureEnglishUICulture.PreferredOrNull));
 
            var ClassAv1 = TestReferences.SymbolsTests.RetargetingCycle.V1.ClassA.dll;
            text =
@"
public class ClassC : ClassB {}
";
 
            var comp2 = CreateCompilation(text, new MetadataReference[]
            {
                ClassAv1,
                new CSharpCompilationReference(comp)
            });
 
            var global = comp2.GlobalNamespace;
            var B2 = global.GetTypeMembers("ClassB", 0).Single();
            var C = global.GetTypeMembers("ClassC", 0).Single();
 
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B2);
            Assert.NotEqual(B1, B2);
            Assert.Same(((PEModuleSymbol)B1.ContainingModule).Module, ((PEModuleSymbol)B2.ContainingModule).Module);
            Assert.Equal(((PENamedTypeSymbol)B1).Handle, ((PENamedTypeSymbol)B2).Handle);
            Assert.Same(C.BaseType(), B2);
 
            var A2 = global.GetTypeMembers("ClassA", 0).Single();
 
            Assert.IsAssignableFrom<PENamedTypeSymbol>(A2.BaseType());
            Assert.IsAssignableFrom<PENamedTypeSymbol>(B2.BaseType());
        }
 
        [Theory, MemberData(nameof(FileScopedOrBracedNamespace))]
        public void NestedNames1(string ob, string cb)
        {
            var text =
@"
namespace N
" + ob + @"
    static class C
    {
        class A<T>
        {
            class B<U> : A<B<U>>.D { }
            private class D { }
        }
    }
" + cb + @"
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var n = global.GetMembers("N").OfType<NamespaceSymbol>().Single();
            var c = n.GetTypeMembers("C", 0).Single();
            var a = c.GetTypeMembers("A", 1).Single();
            var b = a.GetTypeMembers("B", 1).Single();
            var d = a.GetTypeMembers("D", 0).Single();
            Assert.Equal(Accessibility.Private, d.DeclaredAccessibility);
            Assert.Equal(d.OriginalDefinition, b.BaseType().OriginalDefinition);
            Assert.NotEqual(d, b.BaseType());
        }
 
        [Fact]
        public void Using1()
        {
            var text =
@"
namespace N1 {
  class A {}
}
namespace N2 {
  using N1; // bring N1.A into scope
  class B : A {}
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var n1 = global.GetMembers("N1").Single() as NamespaceSymbol;
            var n2 = global.GetMembers("N2").Single() as NamespaceSymbol;
            var a = n1.GetTypeMembers("A", 0).Single();
            var b = n2.GetTypeMembers("B", 0).Single();
            Assert.Equal(a, b.BaseType());
        }
 
        [Fact]
        public void Using2()
        {
            var text =
@"
namespace N1 {
  class A<T> {}
}
namespace N2 {
  using X = N1.A<B>; // bring N1.A into scope
  class B : X {}
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var n1 = global.GetMembers("N1").Single() as NamespaceSymbol;
            var n2 = global.GetMembers("N2").Single() as NamespaceSymbol;
            var a = n1.GetTypeMembers("A", 1).Single();
            var b = n2.GetTypeMembers("B", 0).Single();
            var bt = b.BaseType();
            Assert.Equal(a, b.BaseType().OriginalDefinition);
            Assert.Equal(b, (b.BaseType() as NamedTypeSymbol).TypeArguments()[0]);
        }
 
        [Fact]
        public void Using3()
        {
            var text =
@"
using @global = N;
namespace N { class C {} }
class D : global::N.C {}";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var d = global.GetMembers("D").Single() as NamedTypeSymbol;
            Assert.NotEqual(SymbolKind.ErrorType, d.BaseType().Kind);
        }
 
        [Fact]
        public void Arrays1()
        {
            var text =
@"
class G<T> { }
class C : G<C[,][]>
{
}
";
            var comp = CreateEmptyCompilation(text);
            var global = comp.GlobalNamespace;
            var g = global.GetTypeMembers("G", 1).Single();
            var c = global.GetTypeMembers("C", 0).Single();
            Assert.Equal(g, c.BaseType().OriginalDefinition);
            var garg = c.BaseType().TypeArguments()[0];
            Assert.Equal(SymbolKind.ArrayType, garg.Kind);
            var carr1 = garg as ArrayTypeSymbol;
            var carr2 = carr1.ElementType as ArrayTypeSymbol;
            Assert.Equal(c, carr2.ElementType);
            Assert.Equal(2, carr1.Rank);
            Assert.Equal(1, carr2.Rank);
            Assert.True(carr2.IsSZArray);
        }
 
        [Fact]
        public void MultiSource()
        {
            var text1 =
@"
using N2;
namespace N1 {
  class A {}
}
partial class X {
  class B1 : B {}
}
partial class Broken {
  class A2 : A {} // error: A not found
}
";
            var text2 =
@"
using N1;
namespace N2 {
  class B {}
}
partial class X {
  class A1 : A {}
}
partial class Broken {
  class B2 : B {} // error: B not found
}
";
            var comp = CreateEmptyCompilation(new[] { text1, text2 });
            var global = comp.GlobalNamespace;
            var n1 = global.GetMembers("N1").Single() as NamespaceSymbol;
            var n2 = global.GetMembers("N2").Single() as NamespaceSymbol;
            var a = n1.GetTypeMembers("A", 0).Single();
            var b = n2.GetTypeMembers("B", 0).Single();
            var x = global.GetTypeMembers("X", 0).Single();
            var a1 = x.GetTypeMembers("A1", 0).Single();
            Assert.Equal(a, a1.BaseType());
            var b1 = x.GetTypeMembers("B1", 0).Single();
            Assert.Equal(b, b1.BaseType());
            var broken = global.GetTypeMembers("Broken", 0).Single();
            var a2 = broken.GetTypeMembers("A2", 0).Single();
            Assert.NotEqual(a, a2.BaseType());
            Assert.Equal(SymbolKind.ErrorType, a2.BaseType().Kind);
            var b2 = broken.GetTypeMembers("B2", 0).Single();
            Assert.NotEqual(b, b2.BaseType());
            Assert.Equal(SymbolKind.ErrorType, b2.BaseType().Kind);
        }
 
        [Fact]
        public void CyclicUsing1()
        {
            var text =
@"
using M = B.X;
using N = A.Y;
public class A : M { }
public class B : N { }
";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
 
            var global = comp.GlobalNamespace;
            var a = global.GetTypeMembers("A", 0).Single();
            var b = global.GetTypeMembers("B", 0).Single();
            var abase = a.BaseType();
            Assert.Equal(SymbolKind.ErrorType, abase.Kind);
            var bbase = b.BaseType();
            Assert.Equal(SymbolKind.ErrorType, bbase.Kind);
        }
 
        [Fact]
        public void BaseError()
        {
            var text = "class C : Bar { }";
            var tree = Parse(text);
            var comp = CreateCompilation(tree);
            Assert.Equal(1, comp.GetDeclarationDiagnostics().Count());
        }
 
        [Fact, WorkItem(537401, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537401")]
        public void NamespaceClassInterfaceEscapedIdentifier1()
        {
            var text = @"
namespace @if
{
    public interface @break { }
    public class @int<@string> { }
    public class @float : @int<@break>, @if.@break { }
}";
            var comp = CreateCompilation(Parse(text));
            NamespaceSymbol nif = (NamespaceSymbol)comp.SourceModule.GlobalNamespace.GetMembers("if").Single();
            Assert.Equal("if", nif.Name);
            Assert.Equal("@if", nif.ToString());
            NamedTypeSymbol cfloat = (NamedTypeSymbol)nif.GetMembers("float").Single();
            Assert.Equal("float", cfloat.Name);
            Assert.Equal("@if.@float", cfloat.ToString());
            NamedTypeSymbol cint = cfloat.BaseType();
            Assert.Equal("int", cint.Name);
            Assert.Equal("@if.@int<@if.@break>", cint.ToString());
            NamedTypeSymbol ibreak = cfloat.Interfaces().Single();
            Assert.Equal("break", ibreak.Name);
            Assert.Equal("@if.@break", ibreak.ToString());
        }
 
        [Fact, WorkItem(537401, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/537401")]
        public void NamespaceClassInterfaceEscapedIdentifier2()
        {
            var text = @"
namespace @if
{
    public interface @break { }
    public class @int<@string> { }
    public class @float : @int<@break> : @if.@break { }
}";
            var comp = CreateCompilation(Parse(text));
            NamespaceSymbol nif = (NamespaceSymbol)comp.SourceModule.GlobalNamespace.GetMembers("if").Single();
            Assert.Equal("if", nif.Name);
            Assert.Equal("@if", nif.ToString());
            NamedTypeSymbol cfloat = (NamedTypeSymbol)nif.GetMembers("float").Single();
            Assert.Equal("float", cfloat.Name);
            Assert.Equal("@if.@float", cfloat.ToString());
            NamedTypeSymbol cint = cfloat.BaseType();
            Assert.Equal("int", cint.Name);
            Assert.Equal("@if.@int<@if.@break>", cint.ToString());
 
            // No interfaces as the above doesn't parse due to the errant : in the base list.
            Assert.Empty(cfloat.Interfaces());
        }
 
        [WorkItem(539328, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539328")]
        [WorkItem(539789, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539789")]
        [Fact]
        public void AccessInBaseClauseCheckedWithRespectToContainer()
        {
            var text = @"
class X
{
    protected class A { }
}
 
class Y : X
{
    private class C : X.A { }
    private class B { }
}";
            var comp = CreateCompilation(Parse(text));
            var diags = comp.GetDeclarationDiagnostics();
            Assert.Empty(diags);
        }
 
        /// <summary>
        /// The base type of a nested type should not change depending on
        /// whether or not the base type of the containing type has been
        /// evaluated.
        /// </summary>
        [WorkItem(539744, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/539744")]
        [Fact]
        public void BaseTypeEvaluationOrder()
        {
            var text = @"
class A<T>
{
    public class X { }
}
class B : A<B.Y.Error>
{
    public class Y : X { }
}
";
            //B.BaseType(), B.Y.BaseType
            {
                var comp = CreateCompilation(text);
 
                var classB = (NamedTypeSymbol)comp.SourceModule.GlobalNamespace.GetMembers("B")[0];
                var classY = (NamedTypeSymbol)classB.GetMembers("Y")[0];
 
                var baseB = classB.BaseType();
                Assert.Equal("A<B.Y.Error>", baseB.ToTestDisplayString());
                Assert.False(baseB.IsErrorType());
 
                var baseY = classY.BaseType();
                Assert.Equal("X", baseY.ToTestDisplayString());
                Assert.True(baseY.IsErrorType());
            }
 
            //B.Y.BaseType(), B.BaseType
            {
                var comp = CreateCompilation(text);
 
                var classB = (NamedTypeSymbol)comp.SourceModule.GlobalNamespace.GetMembers("B")[0];
                var classY = (NamedTypeSymbol)classB.GetMembers("Y")[0];
 
                var baseY = classY.BaseType();
                Assert.Equal("X", baseY.ToTestDisplayString());
                Assert.True(baseY.IsErrorType());
 
                var baseB = classB.BaseType();
                Assert.Equal("A<B.Y.Error>", baseB.ToTestDisplayString());
                Assert.False(baseB.IsErrorType());
            }
        }
 
        [Fact]
        public void BaseInterfacesInMetadata()
        {
            var text = @"
interface I1 { }
interface I2 : I1 { }
class C : I2 { }
";
            var comp = CreateCompilation(text);
            var global = comp.GlobalNamespace;
 
            var baseInterface = global.GetMember<NamedTypeSymbol>("I1");
            var derivedInterface = global.GetMember<NamedTypeSymbol>("I2");
            var @class = global.GetMember<NamedTypeSymbol>("C");
 
            var bothInterfaces = ImmutableArray.Create(baseInterface, derivedInterface);
 
            Assert.Equal(baseInterface, derivedInterface.AllInterfaces().Single());
            Assert.Equal(derivedInterface, @class.Interfaces().Single());
            Assert.True(@class.AllInterfaces().SetEquals(bothInterfaces, EqualityComparer<NamedTypeSymbol>.Default));
 
            var typeDef = (Cci.ITypeDefinition)@class.GetCciAdapter();
            var module = new PEAssemblyBuilder((SourceAssemblySymbol)@class.ContainingAssembly, EmitOptions.Default, OutputKind.DynamicallyLinkedLibrary,
                GetDefaultModulePropertiesForSerialization(), SpecializedCollections.EmptyEnumerable<ResourceDescription>());
            var context = new EmitContext(module, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true);
            var cciInterfaces = typeDef.Interfaces(context)
                .Select(impl => impl.TypeRef.GetInternalSymbol()).Cast<NamedTypeSymbol>().AsImmutable();
            Assert.True(cciInterfaces.SetEquals(bothInterfaces, EqualityComparer<NamedTypeSymbol>.Default));
            context.Diagnostics.Verify();
        }
 
        [Fact(), WorkItem(544454, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/544454")]
        public void InterfaceImplementedWithPrivateType()
        {
            var textA = @"
using System;
using System.Collections;
using System.Collections.Generic;
 
public class A: IEnumerable<A.MyPrivateType>
{
    private class MyPrivateType {}
 
    IEnumerator<MyPrivateType> IEnumerable<A.MyPrivateType>.GetEnumerator()
    { throw new NotImplementedException(); }
 
    IEnumerator IEnumerable.GetEnumerator()
    { throw new NotImplementedException(); }
}";
 
            var textB = @"
using System.Collections.Generic;
 
class Z
{
    public IEnumerable<object> goo(A a)
    { 
        return a;
    }
}";
 
            CSharpCompilation c1 = CreateCompilation(textA);
            CSharpCompilation c2 = CreateCompilation(textB, new[] { new CSharpCompilationReference(c1) });
 
            //Works this way, but doesn't when compilation is supplied as metadata
            Assert.Equal(0, c1.GetDiagnostics().Count());
            Assert.Equal(0, c2.GetDiagnostics().Count());
 
            var metadata1 = c1.EmitToArray(options: new EmitOptions(metadataOnly: true));
            c2 = CreateCompilation(textB, new[] { MetadataReference.CreateFromImage(metadata1) });
 
            Assert.Equal(0, c2.GetDiagnostics().Count());
        }
 
        [WorkItem(545365, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545365")]
        [Fact()]
        public void ProtectedInternalNestedBaseClass()
        {
            var source1 = @"
public class PublicClass
{
    protected internal class ProtectedInternalClass
    {
        public ProtectedInternalClass()
        {
        }
    }
}
";
 
            var source2 = @"
class C : PublicClass.ProtectedInternalClass
{
}
";
 
            var compilation1 = CreateCompilation(source1, assemblyName: "One");
            compilation1.VerifyDiagnostics();
 
            var compilation2 = CreateCompilation(source2, new[] { new CSharpCompilationReference(compilation1) }, assemblyName: "Two");
            compilation2.VerifyDiagnostics(
                // (2,23): error CS0122: 'PublicClass.ProtectedInternalClass' is inaccessible due to its protection level
                // class C : PublicClass.ProtectedInternalClass
                Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedInternalClass").WithArguments("PublicClass.ProtectedInternalClass").WithLocation(2, 23)
                );
        }
 
        [WorkItem(545365, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545365")]
        [ClrOnlyFact(ClrOnlyReason.Ilasm)]
        public void ProtectedAndInternalNestedBaseClass()
        {
            // Note: the problem was with the "protected" check so we use InternalsVisibleTo to make
            // the "internal" check succeed.
            var il = @"
.assembly extern mscorlib { .ver 4:0:0:0 .publickeytoken = (B7 7A 5C 56 19 34 E0 89) } 
 
.assembly '<<GeneratedFileName>>'
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.InternalsVisibleToAttribute::.ctor(string)
           = {string('Test')}
} 
 
.class public auto ansi beforefieldinit PublicClass
       extends [mscorlib]System.Object
{
  .class auto ansi nested famandassem beforefieldinit ProtectedAndInternalClass
         extends [mscorlib]System.Object
  {
    .method public hidebysig specialname rtspecialname 
            instance void  .ctor() cil managed
    {
      ldarg.0
      call       instance void [mscorlib]System.Object::.ctor()
      ret
    }
 
  } // end of class ProtectedAndInternalClass
 
  .method public hidebysig specialname rtspecialname 
          instance void  .ctor() cil managed
    {
      ldarg.0
      call       instance void [mscorlib]System.Object::.ctor()
      ret
    }
 
} // end of class PublicClass
";
 
            var csharp = @"
class C : PublicClass.ProtectedAndInternalClass
{
}
";
            CreateCompilationWithILAndMscorlib40(csharp, il, appendDefaultHeader: false).VerifyDiagnostics(
                // (2,23): error CS0122: 'PublicClass.ProtectedAndInternalClass' is inaccessible due to its protection level
                // class C : PublicClass.ProtectedAndInternalClass
                Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedAndInternalClass").WithArguments("PublicClass.ProtectedAndInternalClass").WithLocation(2, 23)
                );
        }
 
        [WorkItem(530144, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530144")]
        [Fact()]
        public void UnifyingBaseInterfaces01()
        {
            var il = @"
.assembly extern mscorlib
{
}
.assembly a
{
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module a.dll
 
 
.class interface public abstract auto ansi J`1<T>
{
}
 
.class interface public abstract auto ansi I`1<T>
       implements class J`1<int32>,
                  class J`1<!T>
{
}";
 
            var csharp =
@"public class C
{
    public static I<int> x;
    static void F(I<int> x)
    {
        I<int> t = C.x;
    }
}
 
public class D : I<int> {}
public interface I2 : I<int> {}";
            CreateCompilationWithILAndMscorlib40(csharp, il, appendDefaultHeader: false).VerifyDiagnostics(
                // (4,26): error CS0648: 'I<int>' is a type not supported by the language
                //     static void F(I<int> x)
                Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I<int>").WithLocation(4, 26),
                // (3,26): error CS0648: 'I<int>' is a type not supported by the language
                //     public static I<int> x;
                Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I<int>").WithLocation(3, 26),
                // (10,14): error CS0648: 'I<int>' is a type not supported by the language
                // public class D : I<int> {}
                Diagnostic(ErrorCode.ERR_BogusType, "D").WithArguments("I<int>").WithLocation(10, 14),
                // (11,18): error CS0648: 'I<int>' is a type not supported by the language
                // public interface I2 : I<int> {}
                Diagnostic(ErrorCode.ERR_BogusType, "I2").WithArguments("I<int>").WithLocation(11, 18),
                // (6,9): error CS0648: 'I<int>' is a type not supported by the language
                //         I<int> t = C.x;
                Diagnostic(ErrorCode.ERR_BogusType, "I<int>").WithArguments("I<int>").WithLocation(6, 9)
            );
        }
 
        [WorkItem(530144, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/530144")]
        [Fact()]
        public void UnifyingBaseInterfaces02()
        {
            var il = @"
.assembly extern mscorlib
{
}
.assembly a
{
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module a.dll
 
 
.class interface public abstract auto ansi J`1<T>
{
}
 
.class interface public abstract auto ansi I`1<T>
       implements class J`1<object>,
                  class J`1<!T>
{
}";
 
            var csharp =
@"public class C
{
    public static I<dynamic> x;
    static void F(I<dynamic> x)
    {
        I<dynamic> t = C.x;
    }
}";
            CreateCompilationWithILAndMscorlib40(csharp, il, appendDefaultHeader: false, targetFramework: TargetFramework.Standard).VerifyDiagnostics(
                // (4,30): error CS0648: 'I<dynamic>' is a type not supported by the language
                //     static void F(I<dynamic> x)
                Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I<dynamic>").WithLocation(4, 30),
                // (3,30): error CS0648: 'I<dynamic>' is a type not supported by the language
                //     public static I<dynamic> x;
                Diagnostic(ErrorCode.ERR_BogusType, "x").WithArguments("I<dynamic>").WithLocation(3, 30),
                // (6,9): error CS0648: 'I<dynamic>' is a type not supported by the language
                //         I<dynamic> t = C.x;
                Diagnostic(ErrorCode.ERR_BogusType, "I<dynamic>").WithArguments("I<dynamic>").WithLocation(6, 9)
            );
        }
 
        [WorkItem(545365, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545365")]
        [Fact()]
        public void ProtectedNestedBaseClass()
        {
            var source1 = @"
public class PublicClass
{
    protected class ProtectedClass
    {
        public ProtectedClass()
        {
        }
    }
}
";
 
            var source2 = @"
class C : PublicClass.ProtectedClass
{
}
";
 
            var compilation1 = CreateCompilation(source1, assemblyName: "One");
            compilation1.VerifyDiagnostics();
 
            var compilation2 = CreateCompilation(source2, new[] { new CSharpCompilationReference(compilation1) }, assemblyName: "Two");
            compilation2.VerifyDiagnostics(
                // (2,23): error CS0122: 'PublicClass.ProtectedClass' is inaccessible due to its protection level
                // class C : PublicClass.ProtectedClass
                Diagnostic(ErrorCode.ERR_BadAccess, "ProtectedClass").WithArguments("PublicClass.ProtectedClass"));
        }
 
        [WorkItem(545589, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545589")]
        [Fact]
        public void MissingTypeArgumentInBase()
        {
            var text =
@"interface I<out T> { }
 
class B : I<object>
{
    public static void Goo<T>(I<T> x)
    {
    }
 
    public static void Goo<T>() where T : I<>
    {
    }
 
    static void Main()
    {
        Goo(new B());
    }
}";
            var comp = CreateCompilation(Parse(text));
            comp.VerifyDiagnostics(
                // (9,43): error CS7003: Unexpected use of an unbound generic name
                //     public static void Goo<T>() where T : I<>
                Diagnostic(ErrorCode.ERR_UnexpectedUnboundGenericName, "I<>")
                );
        }
 
        [WorkItem(792711, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/792711")]
        [Fact]
        public void Repro792711()
        {
            var source = @"
public class Base<T>
{
}
 
public class Derived<T> : Base<Derived<T>>
{
}
";
 
            var metadataRef = CreateCompilation(source).EmitToImageReference(embedInteropTypes: true);
 
            var comp = CreateCompilation("", new[] { metadataRef });
            var derived = comp.GlobalNamespace.GetMember<NamedTypeSymbol>("Derived");
            Assert.Equal(TypeKind.Class, derived.TypeKind);
        }
 
        [WorkItem(872825, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/872825")]
        [Fact]
        public void InaccessibleStructInterface()
        {
            var source =
@"class C
{
    protected interface I
    {
    }
}
struct S : C.I
{
}";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                // (7,14): error CS0122: 'C.I' is inaccessible due to its protection level
                // struct S : C.I
                Diagnostic(ErrorCode.ERR_BadAccess, "I").WithArguments("C.I").WithLocation(7, 14));
        }
 
        [WorkItem(872948, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/872948")]
        [Fact]
        public void MissingNestedMemberInStructImplementsClause()
        {
            var source =
@"struct S : S.I
{
}";
            var compilation = CreateCompilation(source);
            // Ideally report "CS0426: The type name 'I' does not exist in the type 'S'"
            // instead. Bug #896959.
            compilation.VerifyDiagnostics(
                // (1,14): error CS0146: Circular base type dependency involving 'S' and 'S'
                // struct S : S.I
                Diagnostic(ErrorCode.ERR_CircularBase, "I").WithArguments("S", "S").WithLocation(1, 14));
        }
 
        [WorkItem(896959, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/896959")]
        [Fact(Skip = "896959")]
        public void MissingNestedMemberInClassImplementsClause()
        {
            var source =
@"class C : C.I
{
}";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                // (1,13): error CS0426: The type name 'I' does not exist in the type 'C'
                // class C : C.I
                Diagnostic(ErrorCode.ERR_DottedTypeNameNotFoundInAgg, "I").WithArguments("I", "C").WithLocation(1, 13));
        }
 
        [Fact, WorkItem(1085632, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1085632")]
        public void BaseLookupRecursionWithStaticImport01()
        {
            const string source =
@"using A<int>.B;
using D;
 
class A<T> : C
{
    public static class B { }
}
 
class D
{
    public class C { }
}";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                    // (4,14): error CS0246: The type or namespace name 'C' could not be found (are you missing a using directive or an assembly reference?)
                    // class A<T> : C
                    Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "C").WithArguments("C").WithLocation(4, 14),
                    // (1,7): error CS0138: A 'using namespace' directive can only be applied to namespaces; 'A<int>.B' is a type not a namespace. Consider a 'using static' directive instead
                    // using A<int>.B;
                    Diagnostic(ErrorCode.ERR_BadUsingNamespace, "A<int>.B").WithArguments("A<int>.B").WithLocation(1, 7),
                    // (2,7): error CS0138: A 'using namespace' directive can only be applied to namespaces; 'D' is a type not a namespace. Consider a 'using static' directive instead
                    // using D;
                    Diagnostic(ErrorCode.ERR_BadUsingNamespace, "D").WithArguments("D").WithLocation(2, 7),
                    // (2,1): hidden CS8019: Unnecessary using directive.
                    // using D;
                    Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using D;").WithLocation(2, 1),
                    // (1,1): hidden CS8019: Unnecessary using directive.
                    // using A<int>.B;
                    Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using A<int>.B;").WithLocation(1, 1)
                );
        }
 
        [Fact, WorkItem(1085632, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1085632")]
        public void BaseLookupRecursionWithStaticImport02()
        {
            const string source =
@"using static A<int>.B;
using static D;
 
class A<T> : C
{
    public static class B { }
}
 
class D
{
    public class C { }
}";
            var compilation = CreateCompilation(source);
            compilation.VerifyDiagnostics(
                    // (1,1): hidden CS8019: Unnecessary using directive.
                    // using static A<int>.B;
                    Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using static A<int>.B;").WithLocation(1, 1)
                );
        }
 
        [Fact]
        public void BindBases()
        {
            // Ensure good semantic model data even in error scenarios
            var text =
@"
class B {
  public B(long x) {}
}
 
class D : B {
  extern D(int x) : base(y) {}
  static int y;
}";
            var comp = CreateCompilationWithMscorlib461(text);
            var tree = comp.SyntaxTrees[0];
            var model = comp.GetSemanticModel(tree);
            var baseY = tree.GetRoot().DescendantNodes().Where(n => n.ToString() == "y").OfType<ExpressionSyntax>().First();
            var typeInfo = model.GetTypeInfo(baseY);
            Assert.Equal(SpecialType.System_Int32, typeInfo.Type.SpecialType);
            Assert.Equal(SpecialType.System_Int64, typeInfo.ConvertedType.SpecialType);
        }
 
        [Fact, WorkItem(5697, "https://github.com/dotnet/roslyn/issues/5697")]
        public void InheritThroughStaticImportOfGenericTypeWithConstraint_01()
        {
            var text =
@"
using static CrashTest.Crash<CrashTest.Class2>; 
 
namespace CrashTest 
{ 
    class Class2 : AbstractClass 
    { 
    } 
 
    public static class Crash<T> 
        where T: Crash<T>.AbstractClass 
    { 
        public abstract class AbstractClass 
        { 
            public int Id { get; set; } 
        } 
    } 
}";
            var comp = CreateCompilation(text);
            CompileAndVerify(comp);
        }
 
        [Fact, WorkItem(5697, "https://github.com/dotnet/roslyn/issues/5697")]
        public void InheritThroughStaticImportOfGenericTypeWithConstraint_02()
        {
            var text =
@"
using static CrashTest.Crash<object>; 
 
namespace CrashTest 
{ 
    class Class2 : AbstractClass 
    { 
    } 
 
    public static class Crash<T> 
        where T: Crash<T>.AbstractClass 
    { 
        public abstract class AbstractClass 
        { 
            public int Id { get; set; } 
        } 
    } 
 
    class Class3
    {
        AbstractClass Test()
        {
            return null;
        }
    }
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
    // (2,14): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'Crash<T>'. There is no implicit reference conversion from 'object' to 'CrashTest.Crash<object>.AbstractClass'.
    // using static CrashTest.Crash<object>;
    Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "CrashTest.Crash<object>").WithArguments("CrashTest.Crash<T>", "CrashTest.Crash<object>.AbstractClass", "T", "object").WithLocation(2, 14),
    // (6,11): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'Crash<T>'. There is no implicit reference conversion from 'object' to 'CrashTest.Crash<object>.AbstractClass'.
    //     class Class2 : AbstractClass
    Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "Class2").WithArguments("CrashTest.Crash<T>", "CrashTest.Crash<object>.AbstractClass", "T", "object").WithLocation(6, 11),
    // (21,23): error CS0311: The type 'object' cannot be used as type parameter 'T' in the generic type or method 'Crash<T>'. There is no implicit reference conversion from 'object' to 'CrashTest.Crash<object>.AbstractClass'.
    //         AbstractClass Test()
    Diagnostic(ErrorCode.ERR_GenericConstraintNotSatisfiedRefType, "Test").WithArguments("CrashTest.Crash<T>", "CrashTest.Crash<object>.AbstractClass", "T", "object").WithLocation(21, 23)
                );
        }
 
        [Fact, WorkItem(5697, "https://github.com/dotnet/roslyn/issues/5697")]
        public void InheritThroughStaticImportOfGenericTypeWithConstraint_03()
        {
            var text =
@"
using static CrashTest.Crash<CrashTest.Class2>; 
 
namespace CrashTest 
{ 
    [System.Obsolete]
    class Class2 : AbstractClass 
    { 
    } 
 
    [System.Obsolete]
    public static class Crash<T> 
        where T: Crash<T>.AbstractClass 
    { 
        public abstract class AbstractClass 
        { 
            public int Id { get; set; } 
        } 
    } 
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (2,30): warning CS0612: 'Class2' is obsolete
                // using static CrashTest.Crash<CrashTest.Class2>; 
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "CrashTest.Class2").WithArguments("CrashTest.Class2").WithLocation(2, 30),
                // (2,14): warning CS0612: 'Crash<Class2>' is obsolete
                // using static CrashTest.Crash<CrashTest.Class2>; 
                Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "CrashTest.Crash<CrashTest.Class2>").WithArguments("CrashTest.Crash<CrashTest.Class2>").WithLocation(2, 14));
        }
 
        [Fact, WorkItem(5697, "https://github.com/dotnet/roslyn/issues/5697")]
        public void InheritThroughStaticImportOfGenericTypeWithConstraint_04()
        {
            var text =
@"
using static CrashTest.Crash<CrashTest.Class2>; 
 
namespace CrashTest 
{ 
    class Class2 : AbstractClass 
    { 
    } 
 
    public static class Crash<T> 
        where T: Crash<T>.AbstractClass 
    { 
        [System.Obsolete]
        public abstract class AbstractClass 
        { 
            public int Id { get; set; } 
        } 
    } 
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
    // (11,18): warning CS0612: 'Crash<T>.AbstractClass' is obsolete
    //         where T: Crash<T>.AbstractClass 
    Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "Crash<T>.AbstractClass").WithArguments("CrashTest.Crash<T>.AbstractClass").WithLocation(11, 18),
    // (6,20): warning CS0612: 'Crash<Class2>.AbstractClass' is obsolete
    //     class Class2 : AbstractClass 
    Diagnostic(ErrorCode.WRN_DeprecatedSymbol, "AbstractClass").WithArguments("CrashTest.Crash<CrashTest.Class2>.AbstractClass").WithLocation(6, 20)
                );
        }
 
        [Fact, WorkItem(5697, "https://github.com/dotnet/roslyn/issues/5697")]
        public void InheritThroughStaticImportOfGenericTypeWithConstraint_05()
        {
            var text =
@"
using CrashTest.Crash<CrashTest.Class2>; 
 
namespace CrashTest 
{ 
    class Class2 : AbstractClass 
    { 
    } 
 
    public static class Crash<T> 
        where T: Crash<T>.AbstractClass 
    { 
        public abstract class AbstractClass 
        { 
            public int Id { get; set; } 
        } 
    } 
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
    // (2,7): error CS0138: A 'using namespace' directive can only be applied to namespaces; 'Crash<Class2>' is a type not a namespace. Consider a 'using static' directive instead
    // using CrashTest.Crash<CrashTest.Class2>; 
    Diagnostic(ErrorCode.ERR_BadUsingNamespace, "CrashTest.Crash<CrashTest.Class2>").WithArguments("CrashTest.Crash<CrashTest.Class2>").WithLocation(2, 7),
    // (6,20): error CS0246: The type or namespace name 'AbstractClass' could not be found (are you missing a using directive or an assembly reference?)
    //     class Class2 : AbstractClass 
    Diagnostic(ErrorCode.ERR_SingleTypeNameNotFound, "AbstractClass").WithArguments("AbstractClass").WithLocation(6, 20),
    // (2,1): hidden CS8019: Unnecessary using directive.
    // using CrashTest.Crash<CrashTest.Class2>; 
    Diagnostic(ErrorCode.HDN_UnusedUsingDirective, "using CrashTest.Crash<CrashTest.Class2>;").WithLocation(2, 1)
                );
        }
 
        [Fact]
        [WorkItem(174789, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?_a=edit&id=174789")]
        public void CycleTypeArgument()
        {
            var text =
@"class A<T>
{
    internal class B { }
}
class Base
{
    protected class C { }
    private class D { }
}
class Derived : Base
{
    class E : A<C>.B { }
    class F : A<D>.B { }
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (13,17): error CS0122: 'Base.D' is inaccessible due to its protection level
                //     class F : A<D>.B { }
                Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("Base.D").WithLocation(13, 17));
        }
 
        [Fact]
        [WorkItem(174789, "https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?_a=edit&id=174789")]
        public void CycleArray()
        {
            var text =
@"class A<T>
{
    internal class B { }
}
class Base
{
    protected class C { }
    private class D { }
}
class Derived : Base
{
    class E : A<C[]>.B { }
    class F : A<D[]>.B { }
}";
            var comp = CreateCompilation(text);
            comp.VerifyDiagnostics(
                // (13,17): error CS0122: 'Base.D' is inaccessible due to its protection level
                //     class F : A<D>.B { }
                Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("Base.D").WithLocation(13, 17));
        }
 
        [Fact, WorkItem("https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?_a=edit&id=174789")]
        public void CyclePointer()
        {
            var text =
@"class A<T>
{
    internal class B { }
}
class Base
{
    protected class C { }
    private class D { }
}
class Derived : Base
{
    class E : A<C*>.B { }
    class F : A<D*>.B { }
}";
            var comp = CreateCompilation(text, parseOptions: TestOptions.Regular11);
            comp.VerifyDiagnostics(
                // (13,17): error CS0122: 'Base.D' is inaccessible due to its protection level
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("Base.D").WithLocation(13, 17),
                // (13,11): error CS0306: The type 'Base.D*' may not be used as a type argument
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("Base.D*").WithLocation(13, 11),
                // (13,11): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Base.D')
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.WRN_ManagedAddr, "F").WithArguments("Base.D").WithLocation(13, 11),
                // (12,11): error CS0306: The type 'Base.C*' may not be used as a type argument
                //     class E : A<C*>.B { }
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "E").WithArguments("Base.C*").WithLocation(12, 11),
                // (12,11): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Base.C')
                //     class E : A<C*>.B { }
                Diagnostic(ErrorCode.WRN_ManagedAddr, "E").WithArguments("Base.C").WithLocation(12, 11));
        }
 
        [Fact, WorkItem("https://devdiv.visualstudio.com/DefaultCollection/DevDiv/_workitems?_a=edit&id=174789")]
        public void CyclePointer_UnsafeContext()
        {
            var text =
@"class A<T>
{
    internal class B { }
}
class Base
{
    protected class C { }
    private class D { }
}
unsafe class Derived : Base
{
    class E : A<C*>.B { }
    class F : A<D*>.B { }
}";
            var comp = CreateCompilation(text, parseOptions: TestOptions.Regular12);
            comp.VerifyDiagnostics(
                // (10,14): error CS0227: Unsafe code may only appear if compiling with /unsafe
                // unsafe class Derived : Base
                Diagnostic(ErrorCode.ERR_IllegalUnsafe, "Derived").WithLocation(10, 14),
                // (13,17): error CS0122: 'Base.D' is inaccessible due to its protection level
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("Base.D").WithLocation(13, 17),
                // (13,11): error CS0306: The type 'Base.D*' may not be used as a type argument
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("Base.D*").WithLocation(13, 11),
                // (13,11): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Base.D')
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.WRN_ManagedAddr, "F").WithArguments("Base.D").WithLocation(13, 11),
                // (12,11): error CS0306: The type 'Base.C*' may not be used as a type argument
                //     class E : A<C*>.B { }
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "E").WithArguments("Base.C*").WithLocation(12, 11),
                // (12,11): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Base.C')
                //     class E : A<C*>.B { }
                Diagnostic(ErrorCode.WRN_ManagedAddr, "E").WithArguments("Base.C").WithLocation(12, 11));
 
            comp = CreateCompilation(text, options: TestOptions.UnsafeDebugDll, parseOptions: TestOptions.Regular12);
            comp.VerifyDiagnostics(
                // (13,17): error CS0122: 'Base.D' is inaccessible due to its protection level
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.ERR_BadAccess, "D").WithArguments("Base.D").WithLocation(13, 17),
                // (13,11): error CS0306: The type 'Base.D*' may not be used as a type argument
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "F").WithArguments("Base.D*").WithLocation(13, 11),
                // (13,11): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Base.D')
                //     class F : A<D*>.B { }
                Diagnostic(ErrorCode.WRN_ManagedAddr, "F").WithArguments("Base.D").WithLocation(13, 11),
                // (12,11): error CS0306: The type 'Base.C*' may not be used as a type argument
                //     class E : A<C*>.B { }
                Diagnostic(ErrorCode.ERR_BadTypeArgument, "E").WithArguments("Base.C*").WithLocation(12, 11),
                // (12,11): warning CS8500: This takes the address of, gets the size of, or declares a pointer to a managed type ('Base.C')
                //     class E : A<C*>.B { }
                Diagnostic(ErrorCode.WRN_ManagedAddr, "E").WithArguments("Base.C").WithLocation(12, 11));
        }
 
        [Fact]
        [WorkItem(1107185, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1107185")]
        public void Tuple_MissingNestedTypeArgument_01()
        {
            var source =
@"interface I<T>
{
}
class A : I<(object, A.B)>
{
}";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (4,24): error CS0146: Circular base type dependency involving 'A' and 'A'
                // class A : I<(object, A.B)>
                Diagnostic(ErrorCode.ERR_CircularBase, "B").WithArguments("A", "A").WithLocation(4, 24));
        }
 
        [Fact]
        [WorkItem(1107185, "https://devdiv.visualstudio.com/DevDiv/_workitems/edit/1107185")]
        public void Tuple_MissingNestedTypeArgument_02()
        {
            var source =
@"class A<T>
{
}
class B : A<(object, B.C)>
{
}";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (4,24): error CS0146: Circular base type dependency involving 'B' and 'B'
                // class B : A<(object, B.C)>
                Diagnostic(ErrorCode.ERR_CircularBase, "C").WithArguments("B", "B").WithLocation(4, 24));
        }
 
        [Fact]
        public void Tuple_MissingNestedTypeArgument_03()
        {
            var source =
@"interface I<T>
{
}
class A : I<System.ValueTuple<object, A.B>>
{
}";
            var comp = CreateCompilation(source);
            comp.VerifyDiagnostics(
                // (4,41): error CS0146: Circular base type dependency involving 'A' and 'A'
                // class A : I<System.ValueTuple<object, A.B>>
                Diagnostic(ErrorCode.ERR_CircularBase, "B").WithArguments("A", "A").WithLocation(4, 41));
        }
    }
}