Skip to content

Commit

Permalink
Merge pull request #2202 from monarchdodra/swapPointsTo
Browse files Browse the repository at this point in the history
reinsert doesPointTo in swap/move
  • Loading branch information
DmitryOlshansky committed May 31, 2014
2 parents c496463 + b974846 commit fdf5307
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 24 deletions.
51 changes: 29 additions & 22 deletions std/algorithm.d
Expand Up @@ -1885,6 +1885,12 @@ void move(T)(ref T source, ref T target)
{
import core.stdc.string : memcpy;

static if (hasAliasing!T) if (!__ctfe)
{
import std.exception : doesPointTo;
assert(!doesPointTo(source, source), "Cannot move object with internal pointer.");
}

static if (is(T == struct))
{
if (&source == &target) return;
Expand Down Expand Up @@ -1979,7 +1985,11 @@ T move(T)(ref T source)
{
import core.stdc.string : memcpy;

// Can avoid to check aliasing.
static if (hasAliasing!T) if (!__ctfe)
{
import std.exception : doesPointTo;
assert(!doesPointTo(source, source), "Cannot move object with internal pointer.");
}

T result = void;
static if (is(T == struct))
Expand Down Expand Up @@ -2217,10 +2227,19 @@ If $(D lhs) and $(D rhs) reference the same instance, then nothing is done.
$(D lhs) and $(D rhs) must be mutable. If $(D T) is a struct or union, then
its fields must also all be (recursivelly) mutable.
*/
*/
void swap(T)(ref T lhs, ref T rhs) @trusted pure nothrow
if (isBlitAssignable!T && !is(typeof(lhs.proxySwap(rhs))))
{
static if (hasAliasing!T) if (!__ctfe)
{
import std.exception : doesPointTo;
assert(!doesPointTo(lhs, lhs), "Swap: lhs internal pointer.");
assert(!doesPointTo(rhs, rhs), "Swap: rhs internal pointer.");
assert(!doesPointTo(lhs, rhs), "Swap: lhs points to rhs.");
assert(!doesPointTo(rhs, lhs), "Swap: rhs points to lhs.");
}

static if (hasElaborateAssign!T || !isAssignable!T)
{
if (&lhs != &rhs)
Expand Down Expand Up @@ -2367,26 +2386,6 @@ unittest
// 12024
import std.datetime;
SysTime a, b;

//Verify swap is callable even with
//internal pointers
static struct S
{
S[] someRange;
void opAssign(S other)
{
assert(0);
}
}

S[2] arr;
foreach(ref e; arr)
//The elements are themselves part of arr
//this means there is some aliasing
e.someRange = arr[];

//verify this calls still works
swap(arr[0], arr[1]);
}

unittest // 9975
Expand All @@ -2405,6 +2404,14 @@ unittest // 9975
assert(!doesPointTo(a, b));
assert( mayPointTo(a, b));
swap(a, b);

//Note: we can catch an error here, because there is no RAII in this test
import std.exception : assertThrown;
void* p, pp;
p = &p;
assertThrown!Error(move(p));
assertThrown!Error(move(p, pp));
assertThrown!Error(swap(p, pp));
}

void swapFront(R1, R2)(R1 r1, R2 r2)
Expand Down
4 changes: 2 additions & 2 deletions std/exception.d
Expand Up @@ -929,7 +929,7 @@ bool doesPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target)
if (__traits(isRef, source) || isDynamicArray!S ||
isPointer!S || is(S == class))
{
static if (isPointer!S || is(S == class))
static if (isPointer!S || is(S == class) || is(S == interface))
{
const m = cast(void*) source,
b = cast(void*) &target, e = b + target.sizeof;
Expand Down Expand Up @@ -962,7 +962,7 @@ bool mayPointTo(S, T, Tdummy=void)(auto ref const S source, ref const T target)
if (__traits(isRef, source) || isDynamicArray!S ||
isPointer!S || is(S == class))
{
static if (isPointer!S || is(S == class))
static if (isPointer!S || is(S == class) || is(S == interface))
{
const m = cast(void*) source,
b = cast(void*) &target, e = b + target.sizeof;
Expand Down

0 comments on commit fdf5307

Please sign in to comment.