Maybe a C# Compiler Bug in Visual Studio 2015

Maybe a C# compiler bug in Visual Studio 2015

This is not a bug in 2015 but a possibly a C# language bug. The discussion below relates to why instance members cannot introduce loops, and why a Nullable<T> will cause this error, but should not apply to static members.

I would submit it as a language bug, not a compiler bug.


Compiling this code in VS2013 gives the following compile error:

Struct member 'ConsoleApplication1.Program.MyStruct.Empty' of type 'System.Nullable' causes a cycle in the struct layout

A quick search turns up this answer which states:

It's not legal to have a struct that contains itself as a member.

Unfortunately the System.Nullable<T> type which is used for nullable instances of value types is also a value type and must therefore have a fixed size. It's tempting to think of MyStruct? as a reference type, but it really isn't. The size of MyStruct? is based on the size of MyStruct... which apparently introduces a loop in the compiler.

Take for instance:

public struct Struct1
{
public int a;
public int b;
public int c;
}

public struct Struct2
{
public Struct1? s;
}

Using System.Runtime.InteropServices.Marshal.SizeOf() you'll find that Struct2 is 16 bytes long, indicating that Struct1? is not a reference but a struct that is 4 bytes (standard padding size) longer than Struct1.


What's not happening here

In response to Julius Depulla's answer and comments, here is what is actually happening when you access a static Nullable<T> field. From this code:

public struct foo
{
public static int? Empty = null;
}

public void Main()
{
Console.WriteLine(foo.Empty == null);
}

Here is the generated IL from LINQPad:

IL_0000:  ldsflda     UserQuery+foo.Empty
IL_0005: call System.Nullable<System.Int32>.get_HasValue
IL_000A: ldc.i4.0
IL_000B: ceq
IL_000D: call System.Console.WriteLine
IL_0012: ret

The first instruction gets the address of the static field foo.Empty and pushes it on the stack. This address is guaranteed to be non-null as Nullable<Int32> is a structure and not a reference type.

Next the Nullable<Int32> hidden member function get_HasValue is called to retrieve the HasValue property value. This cannot result in a null reference since, as mentioned previously, the address of a value type field must be non-null, regardless of the value contained at the address.

The rest is just comparing the result to 0 and sending the result to the console.

At no point in this process is it possible to 'invoke a null on a type' whatever that means. Value types do not have null addresses, so method invocation on value types cannot directly result in a null object reference error. That's why we don't call them reference types.

Would installing Visual Studio 2015 change the compiler used by VS 2013?

No. Installing Visual Studio 2015 doesn't change the compiler used by VS 2013. At the command line, you can choose between by running the corresponding msbuild.exe

The test failures were due to .NET Framework 4.6 , rather than a change in compiler.

Fixed the problem by setting the 'use legacy JIT' environment COMPLUS_useLegacyJit variable per https://github.com/Microsoft/dotnet/blob/master/docs/testing-with-ryujit.md

Does it look like a C# bug for you?

This is known implementation limitation in CoreCLR - both the instance and static field layout is done together that results into this error. It is not easy to fix.

Source : Static fields should not contribute to cyclic struct layout #4049

Why does this code crash Visual Studio 2015?

This is a known bug in Roslyn. This bug will affect any version of Visual Studio that uses Roslyn.

If I am interpreting VersionOf.net correctly, the first version of Visual Studio with Roslyn built-in is 2015. Before then, I think it was available only as an extension. So, Visual Studio 2013 and prior should be unaffected.

It's due to be fixed in the milestone 16 release. At this time, that release is not scheduled.

Because this is a bug in Roslyn, you can "get around" it by editing and compiling the code containing the unsafe struct in an older version of Visual Studio, one that predates Roslyn. Visual Studio 2012 should work. You can then use the resultant .DLL in your current software.

An unverified fix is available if you build Roslyn yourself from this branch. The fix was made in this commit.

Does it look like a C# bug for you?

This is known implementation limitation in CoreCLR - both the instance and static field layout is done together that results into this error. It is not easy to fix.

Source : Static fields should not contribute to cyclic struct layout #4049



Related Topics



Leave a reply



Submit