runtime: System.TypeLoadException thrown by the Runtime when using structs and generics

The following snippet of code, when compiled and run as a standalone program, will compile just fine but throw a runtime exception:

struct A
{
    B<A> b;

    static void Main(string[] args)
    {
        A a = new A();
    }
}

struct B<T>
{
    C<T> c;
}

class C<T>
{
    T t;
}

Exception thrown: Unhandled Exception: System.TypeLoadException: Could not load type 'A' from assembly 'dotnet, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

I have tested this with the newest public release of .NET Core I could find - 2.2.100-preview2-009404.

The same issue also occurs when building a standard .NET Framework project; I have tested targeting versions 4.5.2 and 4.7.2. Running the executable produced for .NET with mono (Mono JIT compiler version 5.14.0 (Visual Studio built mono)) works just fine - the program prints nothing and exits with code 0.

The same problem occurs if similar code is compiled into a DLL that’s later loaded as a library. However, this is the minimum repro case I could come up with. Should I separately file a bug for .NET Framework? This page suggests I should do so, but points to a “retired” web page.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 4
  • Comments: 16 (10 by maintainers)

Most upvoted comments

@gafter

Why does nobody seem particularly interested in addressing this very fundamental bug - the current inability of the C# compiler to correctly process legal source code? I would have thought that these kinds of bugs would be given a high priority since this is quite legal source code.

Your declaration is infinitely recursive. If every instance of struct A should contain B<A> which contains C<A> which contains A, then the struct would have to be infinitely big, that is obviously not possible (in this case it is otherwise empty, but empty structs in .net takes 1 byte anyways).

You could question whether Roslyn should detect this and fail with CS0523, but note that it can only do so if all the types are declared in the same assembly.

Sorry, I didn’t notice C being a class.

For the record, the repro from the top can be simplified to:

struct A
{
    B<A> b;

    static void Main(string[] args)
    {
        A a = new A();
    }
}

struct B<T>
{
    object c;
}

@svick - That’s OK, it easy to misconstrue someone’s intentions here sometimes! NP.