This transfers the constancy from the object to the result. Is that what
you want? For arrays, dup means "return mutable", no matter what
constancy it is called on.

I'm using the latter. Basically all I need is to copy any object:
const, immut-, or mutable.

BTW, here is what the compiler is complaining about:
immutable B dup();
This is a member function, with the attribute immutable. What this does
is specify that the hidden 'this' pointer is immutable. It's equivalent
to this:
B dup(immutable(B) this);
So what the compiler is saying is that you can't call dup with arguments
(), you must call it with arguments '() immutable', meaning you must call
it on an immutable B, not a mutable B.
-Steve

So what the compiler is saying is that you can't call dup
with arguments (), you must call it with arguments '()
immutable', meaning you must call it on an immutable B, not a
mutable B.

Any space for compiler error message improvements here?

+1, spent two hours with a similar problem

+2. I wasted a little time on this too. Not much, but
frustratingly more than necessary.
Why someone would write that error message makes SOME sense when
explained, but the error message itself is still non-sensical ;)

So what the compiler is saying is that you can't call dup with
arguments (), you must call it with arguments '() immutable',
meaning you must call it on an immutable B, not a mutable B.

Any space for compiler error message improvements here?

+1, spent two hours with a similar problem

+2. I wasted a little time on this too. Not much, but frustratingly
more than necessary.
Why someone would write that error message makes SOME sense when
explained, but the error message itself is still non-sensical ;)

I am writing a D compiler front end, and currently the following message
is displayed for the example:
A.d:22:9: error: receiver for member function 'dup' is unqualified, but
'immutable' is required
f = g.dup;
^~~~~
Is this what you'd want?