From c45e8bc0c0bc7d21771d0a9462c9aef764ab96df Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Mon, 20 Jun 2022 20:45:47 -0400 Subject: [PATCH] Fix CTFE failure for members with opAssign SumType.opAssign now avoids calling core.lifetime.move or core.lifetime.forward during CTFE whenever possible. Dlang issue: https://issues.dlang.org/show_bug.cgi?id=23182 Phobos PR: https://github.com/dlang/phobos/pull/8474 --- src/sumtype.d | 40 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 36 insertions(+), 4 deletions(-) diff --git a/src/sumtype.d b/src/sumtype.d index c7b88d2..5b8f116 100644 --- a/src/sumtype.d +++ b/src/sumtype.d @@ -548,9 +548,15 @@ public: this.match!destroyIfOwner; - mixin("Storage newStorage = { ", - Storage.memberName!T, ": forward!rhs", - " };"); + static if (isCopyable!T) { + mixin("Storage newStorage = { ", + Storage.memberName!T, ": __ctfe ? rhs : forward!rhs", + " };"); + } else { + mixin("Storage newStorage = { ", + Storage.memberName!T, ": forward!rhs", + " };"); + } storage = newStorage; tag = tid; @@ -587,7 +593,14 @@ public: { import core.lifetime: move; - rhs.match!((ref value) { this = move(value); }); + rhs.match!((ref value) { + static if (isCopyable!(typeof(value))) { + // Workaround for dlang issue 21542 + this = __ctfe ? value : move(value); + } else { + this = move(value); + } + }); return this; } } @@ -1461,6 +1474,25 @@ version (D_BetterC) {} else } } +// Assignment of struct with overloaded opAssign in CTFE +@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; + } + + 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...);