diff --git a/std/sumtype.d b/std/sumtype.d index f3d3152b347..1d375ef4d7e 100644 --- a/std/sumtype.d +++ b/std/sumtype.d @@ -635,9 +635,19 @@ public: this.match!destroyIfOwner; - mixin("Storage newStorage = { ", - Storage.memberName!T, ": forward!rhs", - " };"); + static if (isCopyable!T) + { + // Workaround for https://issues.dlang.org/show_bug.cgi?id=21542 + mixin("Storage newStorage = { ", + Storage.memberName!T, ": __ctfe ? rhs : forward!rhs", + " };"); + } + else + { + mixin("Storage newStorage = { ", + Storage.memberName!T, ": forward!rhs", + " };"); + } storage = newStorage; tag = tid; @@ -678,7 +688,17 @@ public: { import core.lifetime : move; - rhs.match!((ref value) { this = move(value); }); + rhs.match!((ref value) { + static if (isCopyable!(typeof(value))) + { + // Workaround for https://issues.dlang.org/show_bug.cgi?id=21542 + this = __ctfe ? value : move(value); + } + else + { + this = move(value); + } + }); return this; } } @@ -1569,6 +1589,28 @@ version (D_BetterC) {} else } } +// Assignment of struct with overloaded opAssign in CTFE +// https://issues.dlang.org/show_bug.cgi?id=23182 +@safe unittest +{ + static struct HasOpAssign + { + void opAssign(HasOpAssign rhs) {} + } + + static SumType!HasOpAssign test() + { + SumType!HasOpAssign s; + // Test both overloads + s = HasOpAssign(); + s = SumType!HasOpAssign(); + return s; + } + + // Force CTFE + enum result = test(); +} + /// True if `T` is an instance of the `SumType` template, otherwise false. private enum bool isSumTypeInstance(T) = is(T == SumType!Args, Args...);