diff --git a/std/typecons.d b/std/typecons.d index 67a1ede8148..13ae2941296 100644 --- a/std/typecons.d +++ b/std/typecons.d @@ -3256,11 +3256,19 @@ struct Nullable(T) * Params: * value = The value to initialize this `Nullable` with. */ - this(inout T value) inout - { - _value.payload = value; - _isNull = false; - } + static if (isCopyable!T) + this(inout T value) inout + { + _value.payload = value; + _isNull = false; + } + else + this(T value) inout + { + import std.algorithm.mutation : move; + _value.payload = move(value); + _isNull = false; + } static if (hasElaborateDestructor!T) { @@ -3273,6 +3281,9 @@ struct Nullable(T) } } + static if (!isCopyable!T) + @disable this(this); + else static if (__traits(hasPostblit, T)) { this(this) @@ -3511,22 +3522,18 @@ struct Nullable(T) * Params: * value = A value of type `T` to assign to this `Nullable`. */ - Nullable opAssign()(T value) + ref Nullable opAssign()(T value) return { import std.algorithm.mutation : moveEmplace, move; - // the lifetime of the value in copy shall be managed by - // this Nullable, so we must avoid calling its destructor. - auto copy = DontCallDestructorT(value); - if (_isNull) { // trusted since payload is known to be uninitialized. - () @trusted { moveEmplace(copy.payload, _value.payload); }(); + () @trusted { moveEmplace(value, _value.payload); }(); } else { - move(copy.payload, _value.payload); + move(value, _value.payload); } _isNull = false; return this; @@ -3604,12 +3611,14 @@ struct Nullable(T) alias back = front; /// ditto + static if (isCopyable!T) @property inout(typeof(this)) save() inout { return this; } /// ditto + static if (isCopyable!T) inout(typeof(this)) opIndex(size_t[2] dim) inout in (dim[0] <= length && dim[1] <= length && dim[1] >= dim[0]) { @@ -4088,16 +4097,12 @@ auto nullable(T)(T t) struct Test { - bool b; - - nothrow invariant { assert(b == true); } - SysTime _st; static bool destroyed; @disable this(); - this(bool b) { this.b = b; } + this(int _dummy) {} ~this() @safe { destroyed = true; } // mustn't call opAssign on Test.init in Nullable!Test, because the invariant @@ -4109,7 +4114,7 @@ auto nullable(T)(T t) { Nullable!Test nt; - nt = Test(true); + nt = Test(1); // destroy value Test.destroyed = false; @@ -10676,6 +10681,21 @@ unittest assert(s2.get().b == 3); } +// https://issues.dlang.org/show_bug.cgi?id=24318 +@system unittest +{ + static struct S + { + @disable this(this); + int i; + } + + Nullable!S s = S(1); + assert(s.get().i == 1); + s = S(2); + assert(s.get().i == 2); +} + /// The old version of $(LREF SafeRefCounted), before $(LREF borrow) existed. /// Old code may be relying on `@safe`ty of some of the member functions which /// cannot be safe in the new scheme, and