Martin Baulig, super hacker

by Miguel de Icaza

Martin has been working for the past couple of weeks on fixing a bug in the Mono C# compiler: how to properly compile an anonymous method inside a generic method.

The problem started with an innocent looking program:

	
        delegate void Foo ();

        class X
        {
                static void Hello<U> (U u)
                { }

                static void Test<T> (T t)
                {
                        Foo foo = delegate {
                                Hello (t);
                        };
                }
        }
	
	

The issue is that when we generated the anonymous method for "foo", we had to turn the "T" generic method parameter into a generic *class* parameter:

	
  .class nested private auto ansi sealed beforefieldinit 'AnonHelp<0>'
    extends [mscorlib]System.Object
  {
     .field  assembly  !0 'p:t'
  }
	

The code to cope with this in the compiler was fairly ugly, and Martin embarked on fixing the design internals at the end of July. We originally thought that there were two solutions: an elegant solution that required some refactoring and an ugly hack that basically accessed System.Reflection.Emit directly and poked at these internals from the anonymous method code path.

I have never quite liked what I did with the implementation of anonymous methods; I have tried to bounce the ideas off a few people to try to get their feeling on how to redo this code. I explained the design to Federico and Gonzalo hoping to get some feedback on the bugs and to clarify my own thoughts.

So to make a long story short, I did not like what was going on in the internals of the compiler; and in addition there are some annoying side effects and various constructs that crash the compiler when nested anonymous methods are used or when iterators and anonymous are mixed.

On Friday, Martin sent his weekly status report where he officially has removed my design mistakes. He has eliminated CaptureContext's from the compiler, and has eliminated the special-cases that coped with captured variables in the compiler --another part piece of code that worked, but was far from elegant--.

The new code that Martin has written replaced chunks of code that has bugged me for more than a year, so these are great news.

The patch is available here

In addition, cleaning up this code is essential as C# 3.0 will make extensive use of this infrastructure as part of the new lambda function support (This is because in C# 3.0 it is very natural for developers to create nested lambdas and anonymous methods, something that was more of a curiosity with the C# 2.0 syntax).

Btw, Martin just had a birthday, and he likes chocolates ;-)

Posted on 02 Sep 2006