[dmd-beta] dmd 2.064 beta take 2

Михаил Страшун m.strashun at gmail.com
Thu May 16 02:26:11 PDT 2013


Wall of text incoming.

First. I'd like to remind to several important properties of D structs:

* They have both compile-time initialization and run-time one. First
is T.init, second is T(...). Needing both is a perfectly valid need
from the programmer, especially with generic code in question.

* structs always have constructors. So this snippet is wrong:
>   struct S
>   {
>       immutable int c = 123; // This should be static, compiler issues error
>       // No constructor
>   }
In fact, S has constructor. All structs have constructor with
parameter count that matches member field count. And judging only by S
definition you can't ever possibly say if "c" will be the same in all
S instances or not.

Second. Having parts of a struct essentially immutable is a common
technique used in, for example, packet template generation in C. C
does not have immutability and a convention is used, but principle is
the same - struct defines packet frame layout, different instances of
struct define different pre-computed packet templates, mutable fields
define data that may differ in actual sent packets within one
template. I am sure there are other valid usages in areas I am not so
familiar with.

Third. Consistency is very important. Design based on use cases is
good only within a reasonable limits. If user can't guess behavior of
a type system based on previous experience, it causes frustration.
There can be a simple and robust approach:

struct S
{
    int x1;                     // mutable data of int size, separate instances
    const int x2;           // const data of int size, separate instances
    static const int x3; // const data of int size, single instance
for all S instances. But still exists in memory.
    enum int x4 = 42;  // named integer literal. No size, no actual
place in memory.
}

Such approach is good because of two reasons. It is orthogonal in a
sense that every type qualifier / storage class adds certain
well-defined property to a type which does not depends on any special
case. Second, it is consistent because it stays the same both for
struct members and local variables. This is much more important than
prohibiting something based on use case approach.

Third. While new behavior is correct and Don's code relied on
long-standing bug DMD still absolutely must provide easy tool to make
required changes. It does not matter if code was correct or not - it
is a difficult breaking change and all words about D stability being a
goal are essentially a nonsense until such attitude is not a default.
Compiler flag added by Kenji is a good solution, but it should not be
_special_ solution, it needs to become a default way to go.

Best regards,
Dicebot


More information about the dmd-beta mailing list