I've gained a crapton of insight while working on collections. It's amazing.
One interesting aspect is the interaction of mutable and functional collections with the type qualifiers "const" and "immutable". I managed to navigate around issues quite nicely, with two exceptions:
1. Reference counting: it's mutation underneath an immutable appearance. For a good while I'd been uncomfortable about that, until I figured that this is the "systems" part of D. Other languages do use reference counting, but at the compiler level which allows cheating the type system. It is somewhat fresh to attempt a principled implementation of both reference counting and safe functional collections, simultaneously and at library level.
My conclusion is that changing the reference count in an otherwise immutable structure is an entirely reasonable thing to want do. We need a way to explain the type system "even though the payload is const or immutable, I'll change this particular uint so please don't do any optimizations that would invalidate the cast". The user is responsible for e.g. atomic reference counting in immutable data etc.
2. Allocation: functional containers carry with them a reference to an IAllocator interface, which tells them how to do memory allocation. Somewhat paradoxically, it is sometimes necessary to allocate memory even for immutable objects. For example, in the concatenation "value ~ list", the list's allocator must be used.
Again, the reference to IAllocator must be unqualified even inside an otherwise qualified object.
These are matters of implementation internals and I'm perfectly comfortable that it's necessary to overstep the boundaries of the type system. The only matter is finding a way to inform the type system that it must make legal certain casts.
Andrei
