diff --git a/phobos/std/algorithm.d b/phobos/std/algorithm.d
index 1793e0f..55d938f 100644
--- a/phobos/std/algorithm.d
+++ b/phobos/std/algorithm.d
@@ -1030,6 +1030,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)
@@ -1041,6 +1042,7 @@ if (isMutable!T && !is(typeof(T.init.proxySwap(T.init))))
         t[] = a[];
         a[] = b[];
         b[] = t[];
+      }
     }
     else
     {
@@ -1104,6 +1106,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
     {
@@ -1115,6 +1121,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)));
