Implement Phobos side of DIP1014

This commit is contained in:
Les De Ridder 2019-06-10 21:07:29 +02:00
parent 6010a7ccde
commit 4be9b5f59f
2 changed files with 68 additions and 3 deletions

View file

@ -1046,8 +1046,8 @@ to its `.init` value after it is moved into target, otherwise it is
left unchanged.
Preconditions:
If source has internal pointers that point to itself, it cannot be moved, and
will trigger an assertion failure.
If source has internal pointers that point to itself and doesn't define
opPostMove, it cannot be moved, and will trigger an assertion failure.
Params:
source = Data to copy.
@ -1198,6 +1198,24 @@ pure nothrow @safe @nogc unittest
assert(s2.a == 2);
}
/// `opPostMove` will be called if defined:
pure nothrow @safe @nogc unittest
{
struct S
{
int a;
void opPostMove(const ref S old)
{
assert(a == old.a);
a++;
}
}
S s1;
s1.a = 41;
S s2 = move(s1);
assert(s2.a == 42);
}
private void trustedMoveImpl(T)(ref T source, ref T target) @trusted
{
moveImpl(source, target);
@ -1379,12 +1397,14 @@ void moveEmplace(T)(ref T source, ref T target) @system
import core.stdc.string : memcpy, memset;
import std.traits : hasAliasing, hasElaborateAssign,
hasElaborateCopyConstructor, hasElaborateDestructor,
hasElaborateMove,
isAssignable, isStaticArray;
static if (!is(T == class) && hasAliasing!T) if (!__ctfe)
{
import std.exception : doesPointTo;
assert(!doesPointTo(source, source), "Cannot move object with internal pointer.");
assert(!(doesPointTo(source, source) && !hasElaborateMove!T),
"Cannot move object with internal pointer unless `opPostMove` is defined.");
}
static if (is(T == struct))
@ -1396,6 +1416,9 @@ void moveEmplace(T)(ref T source, ref T target) @system
else
target = source;
static if (hasElaborateMove!T)
__move_post_blt(target, source);
// If the source defines a destructor or a postblit hook, we must obliterate the
// object in order to avoid double freeing and undue aliasing
static if (hasElaborateDestructor!T || hasElaborateCopyConstructor!T)