From 7022304c0ec10050aedaa007069d88750046e6ba Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Mon, 13 Jun 2022 17:59:18 -0400 Subject: [PATCH] Fix Issue 23182 - Can't assign struct with opAssign to SumType in CTFE SumType.opAssign now avoids calling core.lifetime.move or core.lifetime.forward during CTFE whenever possible. --- std/sumtype.d | 50 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 4 deletions(-) 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...);