Search code examples
c#expression-treescompiler-bugwriteonly

C# compiler bug? Object initializer syntax used for write-only property in Expression makes csc crash


You may consider this a bug report, however I'm curious if I am terribly wrong here, or if there is an explanation from Eric or someone else at Microsoft.

Update

This is now posted as a bug on Microsoft Connect.

Description

Consider the following class:

class A 
{
    public object B {
        set { }
    }
}

Here, A.B is a write-only but otherwise fine property.
Now, imagine we assign it inside of expression:

Expression<Func<A>> expr = 
    () => new A {
        B = new object { }
    };

This code makes C# compiler (both 3.5.30729.4926 and 4.0.30319.1) spit out

Internal Compiler Error (0xc0000005 at address 013E213F): likely culprit is 'BIND'.

and crash.

However, merely replacing object initializer syntax ({ }) with a constructor (( )) compiles just fine.

Full code for reproduction:

using System;
using System.Linq.Expressions;

class Test {
    public static void Main()
    {
        Expression<Func<A>> expr = 
            () => new A {
                B = new object { }
            };
    }
}

class A {
    public object B { set { } }
}

(And yes, I did hit it working on a real project.)


Solution

  • I'm afraid I'm not Eric Lippert (Oh, but could I be so dashing...), but as a former Visual Studio languages guy who can still search the sources, I can say two things about this:

    1. Any time you see something that starts with "Internal Compiler Error" you have most definitely found a bug. That's what that error exists for, whether it's the C#, VB or C++ compiler. It's the "Oh, s**t, something just went really unexpectedly wrong!" throw-up-our-hands-and-bail-out error.

    2. Beyond that, this is definitely a bug in the C# compiler that should be reported. The code that's crashing is assuming that when you're doing an initializer on a property that there's a getter it can look at and, hey, guess what? In this case, there isn't. Oddly enough, if I change the type being constructed to some type "C" instead of "object", I don't get the crash, so I'm guessing it's a failure further up the stack (i.e. the code never should have gotten down to the point where it was looking for the property getter).

    Hope this helps.