Review of DIP49
Andrei Alexandrescu
SeeWebsiteForEmail at erdani.org
Sun Feb 2 15:54:38 PST 2014
Here are a few questions and comments:
* Why is there an immutable postblit? I wonder if there are cases in
which that's needed. Most of the time it's fine to just memcpy() the
data - it's immutable anyway so nothing will change! In fact there is
one use case for immutable postblit, and that's refcounting (when
copying data the reference count must be incremented). But that would be
increment via a pointer, which is not allowed in your proposal. (I think
it is ok for the postblit proposal to not cover refcounting - we can
make it built in the language.)
* The inout case looks good, but again we need to have some good
examples on when it would be necessary.
* What happens if an object defines both the mutable and the inout
version of postblit? I assume the mutable has priority when duplicating
mutable object. The DIP should clarify that.
* Const postblit is spelled "this(this) const" but that's misleading
because it's really "this(whatever1 this) whatever2" with whatever1 and
whatever2 being arbitrary qualifiers. We should probably find a more
descriptive syntax for that. "this(this) auto" comes to mind. We can
even add a contextual keyword such that the compiler recognizes
"this(this) unique" without otherwise giving "unique" any special meaning.
* My main beef is with this constructor. I'll refer to it henceforth as
"the unique constructor".
* Qualifiers obey a hierarchy, i.e. const(T) is a supertype of both T
and immutable(T) as shown below with ASCII art.
const(T)
/\
/ \
T immutable(T)
That imparts structure over the mixed-qualifier constructors. However,
that structure is missing from the unique constructor; all
mixed-qualifier constructors are heaped into one. This makes the rules
forced for certain constructors (e.g. constructing a const(T) from a T
should be much less restricted than constructing a T from a const(T)).
The proposed unique constructor is not sensitive to such distinctions.
* The "unique expression" definition is quite strong and we should
refine it and reuse in other contexts as well.
* The section "Overloading of qualified postblits" is great because it
brings back the subtyping structure! It says: "If mutable postblit is
defined, it is alwasy used for the copies: (a) mutable to mutable; (b)
mutable to const". Indeed that is correct because mutable to const is a
copy to a supertype. To respect subtyping, we should also add (c)
immutable to const; (d) const to const; (e) immutable to immutable. That
way we have a simple rule: "this(this) is invoked for all upcasts
obtained by qualifiers". Wonderful!
* If we go forward with the idea above, we only need to treat the
remaining cases of downcasts and cross-casts across the subtyping
hierarchy:
(a) downcasts: const(T) -> T and const(T) -> immutable(T)
(b) cross-casts: immutable(T) -> T and T -> immutable(T)
* The use of subtyping above would replace the elaborate rules in
section "Overloading of qualified postblits". In fact they seem to agree
95% of the time. By the way there are some confusing negations e.g. "if
mutable postblit is not defined, it will be used for the copies". I
assume the "not" should be removed?
* So we're left with the following postblitting rules as the maximum:
struct T {
this(this); // all upcasts including identity
this(const this); // construct T from const(T)
this(const this) immutable; // construct immutable(T) from const(T)
this(immutable this); // construct T from immutable(T)
this(this) immutable; // construct immutable(T) from T
}
Some could be missing, some could be deduced, but this is the total set.
* Consider a conversion like "this(this) immutable" which constructs an
immutable(T) from a T. This is tricky to typecheck because fields of T
have a mutable type when first read and immutable type after having been
written to. That raises the question whether the entire notion of
postblitting is too complicated for its own good. Should we leave it as
is and go with classic C++-style copy construction in which source and
destination are distinct objects? I think that would simplify both the
language definition and its implementation.
* The section "Why 'const' postblit will called to copy arbitrary
qualified object?" alludes to the subtyping relationship among
qualifiers without stating it.
Andrei
More information about the Digitalmars-d
mailing list