diff --git a/std/algorithm/mutation.d b/std/algorithm/mutation.d index fbef28e5d56..e434d248edb 100644 --- a/std/algorithm/mutation.d +++ b/std/algorithm/mutation.d @@ -1071,10 +1071,20 @@ Params: copy is performed. */ void move(T)(ref T source, ref T target) +if (__traits(compiles, target = T.init)) { moveImpl(target, source); } +/// ditto +template move(T) +if (!__traits(compiles, imported!"std.traits".lvalueOf!T = T.init)) +{ + /// + deprecated("Can't move into `target` as `" ~ T.stringof ~ "` can't be assigned") + void move(ref T source, ref T target) => moveImpl(target, source); +} + /// For non-struct types, `move` just performs `target = source`: @safe unittest { @@ -1184,6 +1194,19 @@ pure nothrow @safe @nogc unittest assert(s53 is s51); } +@system unittest +{ + static struct S + { + immutable int i; + ~this() @safe {} + } + alias ol = __traits(getOverloads, std.algorithm.mutation, "move", true)[1]; + static assert(__traits(isDeprecated, ol!S)); + // uncomment after deprecation + //static assert(!__traits(compiles, { S a, b; move(a, b); })); +} + /// Ditto T move(T)(return scope ref T source) { diff --git a/std/typecons.d b/std/typecons.d index 3c425c7d7de..0a378a732e4 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -10928,19 +10928,22 @@ struct RefCounted(T, RefCountedAutoInitialize autoInit = swap(_refCounted._store, rhs._refCounted._store); } - void opAssign(T rhs) + static if (__traits(compiles, lvalueOf!T = T.init)) { - import std.algorithm.mutation : move; - - static if (autoInit == RefCountedAutoInitialize.yes) - { - _refCounted.ensureInitialized(); - } - else + void opAssign(T rhs) { - assert(_refCounted.isInitialized); + import std.algorithm.mutation : move; + + static if (autoInit == RefCountedAutoInitialize.yes) + { + _refCounted.ensureInitialized(); + } + else + { + assert(_refCounted.isInitialized); + } + move(rhs, _refCounted._store._payload); } - move(rhs, _refCounted._store._payload); } static if (autoInit == RefCountedAutoInitialize.yes)