Monday, April 16, 2007

Oh Captain My Forms

Today I finally committed support for one of the last remaining features in vbnc: the My namespace.

It was easier than expected, hadn't it been for one little problem I had with a little close friend of mine: Reflection.Emit. I stumbled upon the single worst issue I had during last year's SoC, an issue it took me four days to work around. Note: work around, not fix.

At that time I was able to work around it, since it was happening with the compiler, now this wasn't an option anymore, since it was the generated My code that was causing this.

The problem is quite simple: anytime you have a generic type parameter on a method with a constraint, some other generic type parameter (on a completely unrelated type, not method) might fail emission (with a nice TypeLoadException, claiming that the constraint isn't met).

The workaround I used last year is quite simple: remove all constraints, but as mentioned, that isn't an option anymore, so I started investigating. Unfortunately I lost the test case I cooked up last year, but it didn't take me long to recreate one this time. (Last year I had to start with the entire compiler and comment it out piece by piece...)

Namespace OhCaptainIMixedUpTheTypeParameters
    Class C1(Of Y)
    End Class
    Class C2(Of Z)
        Inherits C1(Of Z)
    End Class
    Class C3
        Sub M1(Of A As New)()
        End Sub
        Sub M2(Of B)()
        End Sub
    End Class
End Namespace


Looks quite innocuous, doesn't it?

On MS this fails with: TypeLoadException: GenericArguments[0], 'B', on 'TypeParameter1.C1`1[A]' violates the constraint of type parameter 'A'.

Now read the exception again and try to relate the A and B to the Z and Y.

Of things you can try to make this compile includes changing the order (for example make C3 the first class in the file), or moving the methods to either C1 or C2.

With this test case in hand I was quite certain it was a bug in Reflection.Emit, but I wasn't entirely sure either. So I added code to vbnc that dumps out how it emits everything in VB code, and got a nice 90-line source file that when compiled and run nicely reproduces the problem.

The conclusion is that it's not a bug in vbnc, which is quite bad (I can't fix it). So everybody that wants to compile any VB code with generic type method parameters, be warned: if the compiler quits with a weird TypeLoadException, you know who to blame.

The best part is that it Mono does not suffer from this bug, so if you want your project to compile no matter what, you'll have to use Mono :)

PD: Already filed a bug with MS (link), and they seem to have confirmed it's a bug in Reflection.Emit.

Update 01/07/2007: Fixed bug-link.
Update 21/09/2011: Fixed html for VB code.

6 comments:

  1. Will Mono/ASP.NET work with Dot Net Nuke now?

    ReplyDelete
  2. I don't think it works out-of-the-box right now, but there are plans make it do so soon.

    ReplyDelete
  3. You are perfect, and i like u.
    we are waiting for you to finish this project.
    thank u for ur job;)

    ReplyDelete
  4. I am writing a compiler using Emit and run into the same bug. Could you give me a more specific link to your bug report or the right keywords to search in MS Connect website because I couldn't seem to find it. I wanted to know if there is any update on the status of the bug. Is MS going to fix it or is there a workaround?

    ReplyDelete
  5. I just updated the bug-link. MS doesn't seem to have a solution yet though.

    ReplyDelete
  6. Why can't I see the stuff you put above "Looks quite innocuous, doesn't it?"

    ReplyDelete