Niels Sascha Reedijk 92b3138b83 Import GCC 13.1.0 and dependencies
Updated dependencies:
 * GMP 6.2.1
 * ISL 0.24
 * MPL 1.2.1
 * MPFR 4.1.0

The dependencies were pulled in by running the ./contrib/download_prerequisites script and then
manually removing the symbolic links and archives, and renaming the directories (i.e mv isl-0.24 to isl)
2023-06-18 01:43:18 +01:00

148 lines
3.5 KiB
D

/**
This module contains the implementation of move semantics of DIP 1014
Copyright: Copyright Digital Mars 2000 - 2019.
License: Distributed under the
$(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0).
(See accompanying file LICENSE)
Source: $(DRUNTIMESRC core/_internal/_moving.d)
*/
module core.internal.moving;
/**
Recursively calls the `opPostMove` callbacks of a struct and its members if
they're defined.
When moving a struct instance, the compiler emits a call to this function
after blitting the instance and before releasing the original instance's
memory.
Params:
newLocation = reference to struct instance being moved into
oldLocation = reference to the original instance
Note:
This function is tentatively defined as `nothrow` to prevent
`opPostMove` from being defined without `nothrow`, which would allow
for possibly confusing changes in program flow.
*/
void __move_post_blt(S)(ref S newLocation, ref S oldLocation) nothrow
if (is(S == struct))
{
import core.internal.traits : hasElaborateMove;
static foreach (i, M; typeof(S.tupleof))
{
static if (hasElaborateMove!M)
{
__move_post_blt(newLocation.tupleof[i], oldLocation.tupleof[i]);
}
}
static if (__traits(hasMember, S, "opPostMove"))
{
import core.internal.traits : lvalueOf, rvalueOf;
static assert( is(typeof(S.init.opPostMove(lvalueOf!S))) &&
!is(typeof(S.init.opPostMove(rvalueOf!S))),
"`" ~ S.stringof ~ ".opPostMove` must take exactly one argument of type `" ~ S.stringof ~ "` by reference");
newLocation.opPostMove(oldLocation);
}
}
void __move_post_blt(S)(ref S newLocation, ref S oldLocation) nothrow
if (__traits(isStaticArray, S))
{
import core.internal.traits : hasElaborateMove;
static if (S.length && hasElaborateMove!(typeof(newLocation[0])))
{
foreach (i; 0 .. S.length)
__move_post_blt(newLocation[i], oldLocation[i]);
}
}
@safe nothrow unittest
{
struct A
{
bool movedInto;
void opPostMove(const ref A oldLocation)
{
movedInto = true;
}
}
A src, dest;
__move_post_blt(dest, src);
assert(dest.movedInto);
}
@safe nothrow unittest
{
struct A
{
bool movedInto;
void opPostMove(const ref A oldLocation)
{
movedInto = true;
}
}
struct B
{
A a;
bool movedInto;
void opPostMove(const ref B oldLocation)
{
movedInto = true;
}
}
B src, dest;
__move_post_blt(dest, src);
assert(dest.movedInto && dest.a.movedInto);
}
@safe nothrow unittest
{
static struct DoNotMove
{
bool movedInto;
void opPostMove(const ref DoNotMove oldLocation)
{
movedInto = true;
}
}
static DoNotMove doNotMove;
struct A
{
@property ref DoNotMove member()
{
return doNotMove;
}
}
A src, dest;
__move_post_blt(dest, src);
assert(!doNotMove.movedInto);
}
@safe nothrow unittest
{
static struct A
{
bool movedInto;
void opPostMove(const ref A oldLocation)
{
movedInto = true;
}
}
static struct B
{
A[2] a;
}
B src, dest;
__move_post_blt(dest, src);
foreach (ref a; src.a)
assert(!a.movedInto);
foreach (ref a; dest.a)
assert(a.movedInto);
}