diff --git a/std/variant.d b/std/variant.d index 22c996fda..a094aeb34 100644 --- a/std/variant.d +++ b/std/variant.d @@ -850,7 +850,14 @@ public: */ @property inout(T) get(T)() inout { - inout(T) result = void; + static union SupressDestructor { + T val; + } + + /* If this function fails and it throws, copy elision will not run and the destructor might be called. + * But since this value is void initialized, this is undesireable. + */ + inout(SupressDestructor) result = void; static if (is(T == shared)) alias R = shared Unqual!T; else @@ -861,7 +868,7 @@ public: { throw new VariantException(type, typeid(T)); } - return result; + return result.val; } /// Ditto @@ -3256,7 +3263,7 @@ if (isAlgebraic!VariantType && Handler.length > 0) auto v = Variant(aa); // compile error } -// https://issues.dlang.org/show_bug.cgi?id=8195 +// https://github.com/dlang/phobos/issues/9585 // Verify that alignment is respected @safe unittest { @@ -3268,3 +3275,31 @@ if (isAlgebraic!VariantType && Handler.length > 0) enum FP_SIZE = (int function()).sizeof; static assert(AFoo1.sizeof >= double.sizeof + FP_SIZE); } + +// https://github.com/dlang/phobos/issues/10518 +@system unittest +{ + import std.exception : assertThrown; + + struct Huge { + real a, b, c, d, e, f, g; + } + Huge h = {1,1,1,1,1,1,1}; + Variant variant = Variant([ + "one": Variant(1), + ]); + // Testing that this doesn't segfault. Future work might make enable this + assertThrown!VariantException(variant["three"] = 3); + assertThrown!VariantException(variant["four"] = Variant(4)); + /* Storing huge works too, value will moved to the heap + * Testing this as a regression test here as the AA handling code is still somewhat brittle and might add changes + * that depend payload size in the future + */ + assertThrown!VariantException(variant["huge"] = Variant(h)); + /+ + assert(variant["one"] == Variant(1)); + assert(variant["three"] == Variant(3)); + assert(variant["three"] == 3); + assert(variant["huge"] == Variant(h)); + +/ +}