Shachar, as I don't see a better place of discussing that DIP at the moment, I'll pour some observations and thoughts in here if you don't mind, will add some comments on GitHub later. As I see it right now, it's a case of over-engineering of a quite simple concept.

1. A new function, called __move_post_blt, will be added to DRuntime.

That's unnecessary, if not downright harmful for the language. We should strive to remove things from DRuntime, not add to it. The core language should deal with type memory, not a .so or dll. And it's extraneous, because...

2 and 3. onPostMove and __move_post_blt:

They're unnecessary as well. All that's required is to allow a by-value constructor, e.g:

struct S {
    this(S rhs);
}

Any function in D that has a signature of the form

ReturnType foo(Type x);

in C++ would have an equivalent signature of

ReturnType foo(Type&& x); // NOT ReturnType foo(Type x);

because passing by value in D always implies a possible move. The 'x' in such functions can be safely cannibalized without any repercussions, as it is either a temporary on the call site, or, which is especially pertaining to the original bugzilla discussion, constructed in place via copy elision.

Thus in effect this(S) would be an equivalent of C++'s move constructor. We already have a de-facto move-assignment in the form of opAssign(S), this(S) would be a natural extension to that.

Note, per above, that it is NOT a copy constructor, although user code may want to create a copy *before* calling it, to create the temporary.

Such approach reduces added complexity. The only potential problem with it would be a need to "special-case" initialization from .init, although at the moment, I think even that may be unnecessary: this is a hook after all.

Your example from the DIP would become:

struct Tracker {
    static uint globalCounter;
    uint localCounter;
    uint* counter;

    @disable this(this);

    this(bool local) {
        localCounter = 0;
        if( local )
            counter = &localCounter;
        else
            counter = &globalCounter;
    }

    this(Tracker oldLocation) {
        if( counter is &oldLocation.localCounter )
            counter = &localCounter;
    }

    void increment() {
        (*counter)++;
    }

}

Usage:

auto old = Tracker(true);
// ...
auto new = move(old); // calls Tracker.this(Tracker);

...this avoids any need to inject special postblits into user code.

As I see it, in addition to the above, what would be really desirable is for move() and emplace() family of calls to become compiler intrinsics instead of library constructs. Those at the moment are complete poison: being templates they infect user code with dependencies on libc (moveEmplace calls memset and memcpy of all things) and unnecessary calls to DRuntime (typeid), and they of course blow up the amount of generated code in the form of template instantiations. That's despite the fact that the compiler possesses ALL the necessary knowledge at the time of those calls.

Reply via email to