DLR Namespace Change Fire Drill

Update: This approach doesn’t work. Please see the followup article for the gory details.

[Ed. Note – This long post is about changes we made in the DLR to avoid type collisions with System.Core. The short version of this post is “You can safely ignore the CS1685 warning you’ll get if you embed IPy 2.0 Beta 5 or later in your C# 3.0 application”. The long version below has the gory details of what we did, why we did it, a little about how extension methods work and why you can ignore warning CS1685.]

[Author note – I don’t really have an editor.]

Between Beta 3 and Beta 4 of IronPython 2.0, the DLR team made a very significant change to Microsoft.Scripting.Core.dll. As JB noticed, the DLR expression trees have merged with the LINQ expression trees. As part of this effort, they moved the newly merged expression tree types in Microsoft.Scripting.Core.dll into the System.Linq.Expressions namespace – the same namespace where those types live in System.Core.dll in .NET Framework 3.5.

This change caused quite a few issues with our users. Basically, because of the expression tree merge and the namespace change, the beta 4 version of Microsoft.Scripting.Core.dll had type collisions with System.Core.dll all over the place, making it hard or impossible to use them together. If you’re using C# you could get around these type collisions by using an assembly reference alias. However, assembly reference aliases aren’t supported for Web Sites projects or in Visual Basic.

To fix this, we’re changing the top level namespace in Microsoft.Scripting.Core.dll from System to Microsoft. We’re not going back to the namespaces as they were in Beta 3 – for example, DLR expression trees were originally in the Microsoft.Scripting.Ast namespace but now they’ll be in Microsoft.Linq.Expressions. We don’t think this change will be much of an issue because most people don’t use types from Microsoft.Scripting.Core.dll directly. Unless you’re building your own DLR language, this namespace change shouldn’t affect you at all except to solve the type collision problem.

However, we did hit a small snag.

The LINQ expression tree code, having been written for .NET 3.5, is a heavy user of extension methods. This means IronPython is now also a heavy user of extension methods. However, unlike LINQ, IronPython has to run against .NET 2.0 SP1. That means we can’t reference System.Core.dll in IPy or DLR. If you try to compile C# code with extension methods but without a reference System.Core.dll, you get a compiler error complaining that it can’t find the required ExtensionAttribute type, which is defined in System.Core.dll.

This might appear to be an unsolvable problem, but it turns out the C# compiler doesn’t actually care where the ExtensionAttribute type comes from. You can actually define your own copy of ExtensionAttribute (in the right namespace) and C# will happily compile extension methods without complaint. Furthermore, ExtensionAttribute is only used as a marker – there’s no real code in it – so implementing your own copy is trivial. In the DLR source, you’ll find they have defined their own copy of ExtensionAttribute so they can use extension methods and remain .NET 2.0 SP1 compatible. Since we were using them in Microsoft.Scripting.Core.dll, we started using extension methods in Microsoft.Scripting.dll and IronPython.dll as well.

If you’ll recall back to the start of this post, we’re changing namespaces in order to eliminate type collisions. The snag we hit was that we couldn’t change the ExtensionAttribute namespace without breaking all the extension methods. But we couldn’t leave it the same without having a type collision with the ExtensionAttribute defined in System.Core.dll. If you had a project including both copies of ExtensionAttribute, C# would generate a multiple type definition warning and VB would generate a multiple type definition error.

We’ve looked at a several possible solutions to this. One idea was to ship two completely different sets of binaries – one for .NET 2.0 and one for .NET 3.5. But the upgrade story for that stinks – you want to upgrade your app to .NET 3.5 you have to swap out all your IPy and DLR dlls. Yuck. We considered having separate copies of just Microsoft.Scripting.Core.dll – one defining ExtensionAttribute and the other linked to System.Core.dll and using TypeForwardedTo – but since the assemblies are strongly typed they’d have to same exact version number in order to be swappable. Double yuck.

In the end, we decided to put an internal copy of ExtensionAttribute in each assembly that needs it. As previously indicated, that’s IronPython.dll and Microsoft.Scripting.dll as well as making the copy already in Microsoft.Scripting.Core.dll internal. For IronRuby fans reading this, we also added a copy of ExtensionAttribute to IronRuby.dll and IronRuby.Libraries.Scanner.dll as well.

It seems counterintuitive, doesn’t it? To solve a multiple type definition problem, we defined even more copies of the type in question.

The key thing is that all these copies of ExtensionAttribute (except the one in System.Core.dll) are internal rather than public types. If you build a VB app that references System.Core.dll and Microsoft.Scripting.Core.dll (beta 4), you end up with multiple public copies of ExtensionAttribute and are rewarded with a VB compiler error. However, as long as there’s only one public copy of ExtensionAttribute – regardless of the number of internal copies of that type – VB is happy. So if you’re building a VB app against Microsoft.Scripting.Core.dll (beta 5) and System.Core, you should be golden.

In C# 3.0, on the other hand, continues to throw a warning. If ExtensionAttribute was a user-defined type, we’d be fine. However, since Extension attribute is a “predefined system type”, you get C# warning 1685 even though the copies of ExtensionAttribute are all internal. Furthermore, since there are multiple internal copies of ExtensionAttribute in the IPy dlls, you’ll get this warning even if you’re not referencing System.Core. It seems here that C# 3.0 considers ExtensionAttribute a predefined system type while VB doesn’t.

I realize that always having a warning in C# 3.0 – even if you’re not referencing System.Core.dll – doesn’t feel particularly clean. Given our desire to support both .NET v2 and v3.5 with the same binaries, it was the only choice. Remember that ExtensionAttribute has literally no code and is only used to signal the compiler for extension methods, so we decided it was fairly ignorable as warnings go.

If you’re willing to compile from source yourself, it’s fairly easy to build a set of binaries for a specific version .NET that doesn’t have the warning. If you’re building for v3.5, you need to remove Extension.cs from the three projects that have a copy of it (Microsoft.Scripting.Core, Microsoft.Scripting, IronPython) and add a reference to System.Core.dll. If you’re building for v2.0, remove the Extension.cs from Microsoft.Scripting and IronPython then change the visibility in the Microsoft.Scripting.Core version from internal to public. Note, we treat warnings as errors in IPy, but we did add CS1685 to the list of WarningsNotAsErrors so the code still compiles. Of course, if you’re defining a framework specific version, you won’t get the warning anyway.

As usual, we appreciate all feedback from our community so hammer on this build as much as you can – esp. if you’ve been having type conflict errors with Beta 4. As I said in an earlier post, this is our last planned beta, so now’s the time put it thru the paces to make sure there’s nothing blocking you before we get to 2.0.

Finally, major props to Curt…aka IRON CURT…for driving these dev changes and putting up with the constant barrage of “where are we now?” status requests from yours truly. I’m sure he now regrets sitting across the hall within easy earshot.

IronPython Beta 5

Dave just posted the announcement to the IPy mailing list, Beta 5 has been released. You can download the release from CodePlex. Like Beta 4, this release is available in MSI or ZIP format, with the MSI including the Python Standard Library as an option.

As per the release notes, this is our last planned beta for 2.0 – our next planned release is RC1. So if you’ve been holding off on upgrading to the latest betas or to 2.0 in general, now is the time to upgrade if you want us to fix your bug before we ship 2.0.

Webdev Script and KillWebDevServer

I was updating my webdev powershell script today. I wanted to add support for a -browser switch that would automatically launch a browser window the way chiron from the Silverlight Dynamic Languages SDK. does. I also set the script to serve up the current directory by default. I posted the new version up on my SkyDrive.

While I was working on the script, I thought about how one might shutdown the WebDev server from the command line. That turned out to be much harder. Basically, you have to look thru all the top level windows for one that has “ASP.NET Development Server” in the window text, then you send that window two messages – WM_QUERYENDSESSION and WM_QUIT. Not sure why the WebDev server uses WM_QUERYENDSESSION to shut down it’s tray icon, but if you look at WebDev.WebServer.exe in Reflector, you’ll see the tray icon form overrides WinProc in order to look for message 0×11, i.e. WM_QUERYENDSESSION.

I threw together a quick little C# console app to shutdown the WebDev server and stuck it up on my SkyDrive as well. Source code is up there too. I had to use a bunch of P/Invokes to make it work, or I would have written it in Powershell or IronPython.

Enjoy.

Afternoon Coffee 174

You know, this gets pretty long when I go a week between morning coffee posts.

Dynamic Language Stuff

Other Stuff

  • Don Syme blogs about an update to the F# CTP, a mere week after the original release. One week? That’s more often than even IPy releases. I can’t wait to see what they ship in next week’s release! 😄 Seriously, I hope they can keep the release sprints short, but every week would be a bit crazy!
  • Speaking of F#, Matt Podwysocki updates FsTest for the F# CTP and posts about Extension Everything in F#. Unlike C#, which only supports extension methods, F# also supports extensions properties, static methods and events, though like Matt I can’t think of a good use for extension events.
  • Still speaking about F#, Andrew Kennedy has a three part series on the new units of measure feature of F#. If you were going to use F# to build the physics engine of a game, I would suspect UoM would be extremely useful. (via Don Syme)
  • Oh look, Chris Smith built an F# version of artillery game that uses Units of Measure for the physics code. I’ll bet UoM was extremely useful. 😄
  • Talking about Live Mesh at TechEd Australia – where much to my surprise frankly they were demoing Live Mesh Apps – I pointed out to Scott Hanselman that Mesh is running an embedded CoreCLR (aka the same CLR from Silverlight 2). Scott went poking around and posted what he discovered. Looking forward to finding out what he digs up on using CoreCLR outside the browser.
  • Speaking of Scott, I need to set up a family video conference solution like Scott’s before my next trip.
  • Congrats to Glenn Block and the MEF team for their initial CodePlex source drop! I’ve been hearing about this possibility since Glenn joined the team, so I’m really excited to see it happen. I need to take a look at it in detail (in my copious spare time) because I want to find out how to make it work with IPy.
  • Bart de Smet has a whole series (starting here) on Dynamic Expression Trees. However, given that he specifically writes “This blog series is not about DLR itself” makes it seem pretty conceptual to me. Why not talk about DLR expression trees instead Bart?
  • I’m sure you noticed ASP.NET MVC preview 5 dropped last week. I really liked Brad Wilson’s discussion of the new view engine design.
  • Tomas Restrepo has started publishing his source code on GitHub. Personally, I haven’t published any source code lately but I am using Git for all of my non IPy core work (which is stored in TFS). Like Tomas, I’m still getting the hang of Git but I’m really digging it’s speed, it’s branching and the fact that there’s zero infrastructure requirements. SVN provides the lightweight svnserve, but Git is even lighter weight than that.
  • I liked Steve Yegge’s post on typing. I am a touch typer, but I doubt I type 70 words a minutes. I do know where the number keys are without looking though, so I guess that’s pretty good. I remember seeing Chris Anderson demo Avalon WPF long before it was public and being impressed at how fast he could type.