diff --git a/changelog.dd b/changelog.dd index fa289b967..89dfede4c 100644 --- a/changelog.dd +++ b/changelog.dd @@ -19,5 +19,6 @@ $(VERSION 054, ddd mm, 2011, =================================================, $(LI $(BUGZILLA 5857): std.regex (...){n,m} is bogus when (...) contains repetitions) $(LI $(BUGZILLA 6076): regression, std.regex: "c.*|d" matches "mm") $(LI $(BUGZILLA 6113): singletons in std.datetime are not created early enough) + $(LI $(BUGZILLA 5705): Swapping identical struct with hasElaborateAssign causes "overlapping array copy" exception) ) ) diff --git a/std/algorithm.d b/std/algorithm.d index 75309b38f..6f45d1ff0 100644 --- a/std/algorithm.d +++ b/std/algorithm.d @@ -1479,6 +1479,7 @@ if (isMutable!T && !is(typeof(T.init.proxySwap(T.init)))) { static if (hasElaborateAssign!T) { + if (lhs !is rhs) { // For structs with non-trivial assignment, move memory directly // First check for undue aliasing assert(!pointsTo(lhs, rhs) && !pointsTo(rhs, lhs) @@ -1490,6 +1491,7 @@ if (isMutable!T && !is(typeof(T.init.proxySwap(T.init)))) t[] = a[]; a[] = b[]; b[] = t[]; + } } else { @@ -1553,6 +1555,10 @@ unittest swap(nc1, nc2); assert(nc1.n == 513 && nc1.s == "uvwxyz"); assert(nc2.n == 127 && nc2.s == "abc"); + swap(nc1, nc1); + swap(nc2, nc2); + assert(nc1.n == 513 && nc1.s == "uvwxyz"); + assert(nc2.n == 127 && nc2.s == "abc"); struct NoCopyHolder { @@ -1564,6 +1570,10 @@ unittest swap(h1, h2); assert(h1.noCopy.n == 65 && h1.noCopy.s == null); assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc"); + swap(h1, h1); + swap(h2, h2); + assert(h1.noCopy.n == 65 && h1.noCopy.s == null); + assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc"); const NoCopy const1, const2; static assert(!__traits(compiles, swap(const1, const2)));