From 5ca44b74a5afb44b1d5ccc45917fd08d35e3de8a Mon Sep 17 00:00:00 2001 From: Paul Backus Date: Wed, 9 Feb 2022 11:00:20 -0500 Subject: [PATCH] Fix Issue 22572 - Cannot define SumType over immutable struct with Nullable Previously, SumType incorrectly assumed that all members of an inout(SumType) must themselves be inout-qualified. However, this is not the case when one of those member types is declared as immutable, since the qualifier combination `immutable inout` collapses to just `immutable`. Attempting to copy an immutable member type as though it were inout caused matching to fail in SumType's copy constructor, due to the following (gagged) error: Error: `inout` on `return` means `inout` must be on a parameter as well for `pure nothrow @nogc @safe inout(Storage)(ref immutable(Value) value)` --- std/sumtype.d | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/std/sumtype.d b/std/sumtype.d index 658fd3847..5e35a6b9c 100644 --- a/std/sumtype.d +++ b/std/sumtype.d @@ -262,6 +262,8 @@ private enum isHashable(T) = __traits(compiles, private enum hasPostblit(T) = __traits(hasPostblit, T); +private enum isInout(T) = is(T == inout); + /** * A [tagged union](https://en.wikipedia.org/wiki/Tagged_union) that can hold a * single value from any of a specified set of types. @@ -419,6 +421,7 @@ public: ( allSatisfy!(isCopyable, Map!(InoutOf, Types)) && !anySatisfy!(hasPostblit, Map!(InoutOf, Types)) + && allSatisfy!(isInout, Map!(InoutOf, Types)) ) { /// Constructs a `SumType` that's a copy of another `SumType`. @@ -1492,6 +1495,23 @@ version (D_BetterC) {} else immutable SumType!(int*) si = ∋ } +// Immutable member type with copy constructor +// https://issues.dlang.org/show_bug.cgi?id=22572 +@safe unittest +{ + static struct CopyConstruct + { + this(ref inout CopyConstruct other) inout {} + } + + static immutable struct Value + { + CopyConstruct c; + } + + SumType!Value s; +} + /// True if `T` is an instance of the `SumType` template, otherwise false. private enum bool isSumTypeInstance(T) = is(T == SumType!Args, Args...);