QtD is suspended

Andrei Alexandrescu SeeWebsiteForEmail at erdani.org
Fri Sep 17 09:39:06 PDT 2010


On 09/17/2010 09:02 AM, Max Samukha wrote:
> On 09/17/2010 11:15 AM, Andrei Alexandrescu wrote:
> Nice to hear that the problem is being worked on. What kind of
> typechecking will be performed in const/immutable postblit?

The tricky part in that constructor is that you must be able to assign 
the fields, so they are effectively non-const, but you must NOT escape 
outside the constructor as modifiable lvalues. Consider:

int * global;

void foo(ref int x) { global  = &x; }

struct S {
     int a;
     this(this) immutable {
         a = 5;
         foo(a);
     }
}

The program should not compile. If it did, global would be a backdoor 
for modifying an immutable object. Replacing const with immutable seems 
to make things less stringent, but not in reality. The same typechecking 
must be applied to const postblit because const is a subtype of immutable.

>> On a funny note, we figured that for a number of reasons it would help
>> to allow C++-style constructors that offer access to the source; it just
>> turns out some idioms need to modify the source as well as the
>> destination.
>
> Funny. We seem to be in the opposite situation. We originally thought
> that postblit won't be enough for QtD but it looks like copying most (or
> all, not sure) value types in Qt do not need access to the source object.

Yah, it's a relatively rare situation. I enjoy the robustness of 
this(this), but see my most recent post.

> The thing is that D's const looked well suited for our purpose. Postblit
> and const were discussed in TDPL so we concluded that their design and
> implementation were more or less complete and harmonized. We took the
> effort to change the generator to properly generate const qualifiers and
> only after that discovered the postblit issues.

I understand. Were it not for that particular issue, it's not impossible 
you would have run into some others. D's immutability subsystem is not 
new, but it's one of the first deployed in a practical language. Just 
like with other features (exceptions, templates, lambdas, AOP...), some 
time is needed for the appropriate idioms to emerge. QtD was the first 
large-scale deployment of const, and it was expected to run into 
practical as well as theoretical matters. We haven't deployed const into 
Phobos yet for the same reason, and there is ongoing discussion on how 
to best go about it.

Bottom line, I have a few thoughts on the matter. First, at this point 
in const's maturity, it's easier to convert a working codebase to using 
const than to design one from scratch for const. This is 
counter-intuitive, but it's dictated by const's immaturity. I'm sure the 
trend will reverse in a couple of years.

(Come to think of this: it took over 15 years for C++'s exceptions to 
achieve any sign of idiomatic usage, and even now very few people know 
e.g. how to transport one exception from a thread to another. Java has 
made obvious-in-hindsight errors in designing its exception subsystem, 
even though it already had a large body of experience with C++ at its 
disposal.)

Second thought is, I am sure the use of D's const, even after it 
matures, will be less pervasive than the use of const in C++. This 
inescapably follows from the fact that D const guarantees more and is 
more restrictive than C++'s const. In C++ I slap const on anything that 
comes in sight: function parameters, stack variables, member 
functions... At the same time, I fully realize that the assurance I get 
in return is quite weak. In D, I afford only a subset of uses of const, 
but the payout is much more powerful.

Third thought is, we did not find the design for immutable and const as 
much as the design found us. What we wanted was a guarantee that you get 
to share immutable data, which we always believed is fundamental. 
Everything else was aftermath.

>> I wouldn't go back from a Lexus to
>> a Yugo because the Lexus doesn't have a butt warmer :o).
>
> :) The Lexus doesn't start and has an obscenity scratched on its hood. A
> butt warmer would double its resale price.

And a tank full of gas would triple it :o).

>> I understand. Let me ask you this - if your bugs had #1 priority, would
>> that have helped? I mean, is the slow response time to bug submissions a
>> large annoyance factor?
>
> Definitely. The notorious one
> (http://d.puremagic.com/issues/show_bug.cgi?id=424), which hindered QtD
> development on Windows, drove a couple of good users away from D and
> became a powerful FUD generator, was submitted 4 years ago.

That bug comes often in my chats with Walter. The fact of the matter is 
that that is a difficult bug to find and fix in an assembly program. 
Walter is working slowly on translating the linker into C, which should 
simplify a lot of things. I'll also add that he did fix two comparably 
pernicious linker bugs, one recently.

> I think one of the big factors causing annoyances is miscommunication.
> While you have immediate access to Walter, most of us have to settle for
> this NG and #d IRC channel (the latter has become a source of nothing
> but discouragement).

Yah :o). I occasionally lurk there. It's amusing but hardly productive.

> We carefully follow discussions (at least we try to) in the mail-lists
> and NG but often do not know what is the final decision on a problem
> having been discussed.

I understand. At the same time, only this post took me quite a long 
time. Just like you all, most of my time of day is already spoken for. 
Doing my best.

> One example is the semantics of clear() and scoped(). As I understood
> from one of your posts, you agree that resurrecting the destroyed object
> by calling its default constructor is objectionable. However, no further
> action followed. So we are at a loss whether you have a better solution,
> are still thinking about one, don't have time to change the
> implementation or don't want to change the thing because it is engraved
> in TDPL. The same applies to 'scoped' moving the object.

Good point. Also, clear() has been a favorite topic on #d because it's 
good evidence of my incompetence.

The intent of clear(obj) is rather simple. It's supposed to put obj in a 
well-defined, destroyable state that does not allocate resources. It's 
the type system's last-ditch effort to preserve safety while at the same 
time releasing all object state.

Currently, clear() works incorrectly for classes, where it invokes the 
default constructor. SVN doesn't assign the blame to me, but the 
decision does originate in discussions I took part in. clear() shouldn't 
call the default constructor of the class because then the class object 
is free to allocate resources once again. What it should do is to blast 
the default initializer for each field in the class. That's a 
well-defined state that doesn't allocate resources - great.

There are two problems with that state. One, the state might fail the 
invariant of the object, but that's expected - once you called clear(), 
you leave an empty shell behind that's unusable unless you reseat 
something into it.

Second, calling the destructor again from that state is problematic 
(because of failing the invariant) and the GC calls the destructor. This 
is also solvable: the GC might memcmp() the state of the object against 
its default state. If comparison comes positive, the destructor is not 
invoked. We need to be careful that doesn't impact collection times.

> Another example is half-implemented 'inout'. Is a correct implementation
> fundamentally impossible or Walter haven't had time for it?

A correct implementation is possible and we have a good understanding of 
what it takes. Walter didn't get around to it yet.

> Such unterminated discussions tend to stack up in our minds creating a
> possibly very exaggerated image of instability.

I understand. Oddly enough, we only now have such a productive 
discussion, after the destructor has been called :o).


Andrei


More information about the Digitalmars-d-announce mailing list