On Friday, 2 February 2018 at 14:29:34 UTC, H. S. Teoh wrote:
Its semantics are not broken; it's just harder to use. Due to
const transitivity, it's an all-or-nothing deal. .tailConst
gives us the middle ground.
If the semantics of const means that users will have to write
.tailConst all over the place, it's broken. If it means that
users can't use const(T) because they actually want TailConst!T,
TailConst seems like the logical solution to the problem, but it
isn't. It directly impacts user code and it leads to lots of
boilerplate. In addition to .tailConst, we also need
.tailImmutable. And to top it off, it just doesn't mix with const
at all - if you pass it as a const parameter, it's broken. If
it's part of a struct or class with const methods, it's broken.
It infects every part of your codebase that touches it, it forces
you to basically implement your own const system in templates,
and it makes const even harder to use than it currently is.
Tail-const is the more intuitive way to think of it, so if I'm
wrong, please show me.
Once we've defined immutable(RefCounted!T) to be undefined
suddenly casting from const(RefCounted!T) to
The problem with this is that we're now relying on convention
rather than something that can be statically verified by the
compiler. Once you allow casting away const, there's no longer
a guarantee that somebody didn't pass in an immutable, whether
by mistake or otherwise. We know from C/C++ where programming
by convention leads us. :-P
True. Sadly, there's no way to tell the type system 'this type
should never be immutable'. Maybe such a thing should be in the
language. Meanwhile, if RefCounted!T implements .headMutable, it
can check at runtime that the refcount is in writable memory.
Though the above currently doesn't compile, it seems because
the compiler doesn't know how to resolve Wrapper!(const(T))
given a Wrapper!T despite the alias this.
Yeah, I found the same bug when playing with .headMutable: