Bug 22572 – Cannot define SumType over immutable struct with Nullable
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-12-06T12:24:06Z
Last change time
2022-02-09T22:50:16Z
Keywords
industry, pull
Assigned to
No Owner
Creator
FeepingCreature
Comments
Comment #0 by default_357-line — 2021-12-06T12:24:06Z
Not sure if Phobos or DMD issue.
Consider this code:
import std;
immutable struct Value
{
Nullable!string n;
}
void main() {
SumType!Value value;
}
This gets /dlang/dmd-nightly/linux/bin64/../../src/phobos/std/sumtype.d(1985): Error: static assert: "`handlers[0]` of type `template` never matches"
If we replace Nullable with a simpler struct:
struct CopyConstruct
{
this(ref CopyConstruct other) { }
}
immutable struct Value
{
CopyConstruct c;
}
void main() {
SumType!Value value;
}
Then we get the revealing error:
Error: Generating an `inout` copy constructor for `struct onlineapp.Value` failed, therefore instances of it are uncopyable
It looks like Nullable's copy constructor does not play well with immutable structs.
The strange `handler never matches` error above seems to only arise because DMD manages to defer this error until the SumType handler. But this is not the primary issue.
Comment #1 by snarwin+bugzilla — 2022-02-09T14:46:36Z
There's definitely a SumType issue here:
---
import std.sumtype;
struct CopyConstruct
{
this(ref inout CopyConstruct other) inout { }
}
immutable struct Value
{
CopyConstruct c;
}
alias _ = SumType!Value;
---
The example above produces the following error message, as of DMD/Phobos 2.098.1:
---
/dlang/dmd/linux/bin64/../../src/phobos/std/sumtype.d(1998): Error: static assert: "`handlers[0]` of type `template` never matches"
/dlang/dmd/linux/bin64/../../src/phobos/std/sumtype.d(1590): instantiated from here: `matchImpl!(inout(SumType!(immutable(Value))))`
/dlang/dmd/linux/bin64/../../src/phobos/std/sumtype.d(452): instantiated from here: `match!(inout(SumType!(immutable(Value))))`
onlineapp.d(13): instantiated from here: `SumType!(immutable(Value))`
---
The source of the error is this line:
https://github.com/dlang/phobos/blob/v2.098.1/std/sumtype.d#L452
Compiling with -verrors=spec reveals the following gagged error, which is ultimately responsible for the failure:
---
(spec:1) src/sumtype.d(389): Error: `inout` on `return` means `inout` must be on a parameter as well for `pure nothrow @nogc @safe inout(Storage)(ref immutable(Value) value)`
---
SumType's copy constructor incorrectly assumes that, when copying from an `inout(SumType) other`, the value stored in `other` will also be inout-qualified. However, this is not the case when one of other's members is an immutable struct, because the qualifier combination `immutable inout` collapses to just `immutable`.
Comment #2 by snarwin+bugzilla — 2022-02-09T16:00:00Z
@pbackus created dlang/phobos pull request #8377 "Fix Issue 22572 - Cannot define SumType over immutable struct with Nu…" fixing this issue:
- 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)`
https://github.com/dlang/phobos/pull/8377
Comment #4 by dlang-bot — 2022-02-09T22:50:16Z
dlang/phobos pull request #8377 "Fix Issue 22572 - Cannot define SumType over immutable struct with Nu…" was merged into master:
- 32924e3fc34676bb4e89efcbcbd202e6e9af911f by Paul Backus:
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)`
https://github.com/dlang/phobos/pull/8377