Thread overview
SumType!(A,B) != SumType!(B,A) - a bug?
Dec 26, 2023
Andrey Zherikov
Dec 26, 2023
Paul Backus
Dec 26, 2023
Andrey Zherikov
Dec 26, 2023
Paul Backus
Dec 29, 2023
Nickolay Bukreyev
December 26, 2023

Here is the code:

struct A {}
struct B { int[] i; }

immutable s1 = SumType!(A,B)(B.init);    // (1) compiles
immutable s2 = SumType!(B,A)(B.init);    // (2) compilation error

Compilation error for (2):

>

onlineapp.d(9): Error: cannot implicitly convert expression SumType(Storage(B(null), ), cast(ubyte)0u).this(B(null)) of type SumType!(B, A) to immutable(SumType!(B, A))
onlineapp.d(9): s2 = SumType(Storage(B(null), ), cast(ubyte)0u).this(B(null)) is the first assignment of s2 therefore it represents its initialization
onlineapp.d(9): opAssign methods are not used for initialization, but for subsequent assignments

Questions:

  • Should (1) and (2) behave the same way?
  • Is there anything I can do with type A to make (1) fail to compile the same way as (2)?
December 26, 2023

On Tuesday, 26 December 2023 at 19:05:08 UTC, Andrey Zherikov wrote:

>

Here is the code:

struct A {}
struct B { int[] i; }

immutable s1 = SumType!(A,B)(B.init);    // (1) compiles
immutable s2 = SumType!(B,A)(B.init);    // (2) compilation error

[...]

>

Questions:

  • Should (1) and (2) behave the same way?
  • Is there anything I can do with type A to make (1) fail to compile the same way as (2)?

Yes, they should both behave the same way--either the conversion from mutable to immutable is valid, or it isn't.

I think this is probably a compiler bug, but it's hard to tell without a reduced example.

December 26, 2023

On Tuesday, 26 December 2023 at 19:19:08 UTC, Paul Backus wrote:

>

I think this is probably a compiler bug, but it's hard to tell without a reduced example.

Output from dustmite:

void main()
{
    import std;
    struct B { int[] i; }

    immutable s2 = SumType!B(B.init);    // compilation error
}

Error:

>

source.reduced/main.d(6): Error: cannot implicitly convert expression SumType(Storage(B(null)), cast(ubyte)0u).this(B(null)) of type SumType!(B) to immutable(SumType!(B))
source.reduced/main.d(6): s2 = SumType(Storage(B(null)), cast(ubyte)0u).this(B(null)) is the first assignment of s2 therefore it represents its initialization
source.reduced/main.d(6): opAssign methods are not used for initialization, but for subsequent assignments

December 26, 2023

On Tuesday, 26 December 2023 at 19:30:14 UTC, Andrey Zherikov wrote:

>

On Tuesday, 26 December 2023 at 19:19:08 UTC, Paul Backus wrote:

>

I think this is probably a compiler bug, but it's hard to tell without a reduced example.

Output from dustmite:

void main()
{
    import std;
    struct B { int[] i; }

    immutable s2 = SumType!B(B.init);    // compilation error
}

Needs to include std.sumtype in the reduction to be useful. I recommend copying sumtype.d from Phobos to a new directory to create a self-contained example.

December 29, 2023

On Tuesday, 26 December 2023 at 19:19:08 UTC, Paul Backus wrote:

>

I think this is probably a compiler bug, but it's hard to tell without a reduced example.

union A {
    int x;
    int[] arr;
}

union B {
    int[] arr;
    int x;
}

A createA() /+pure+/ { return A.init; }
B createB() /+pure+/ { return B.init; }

void main() {
    immutable a = createA(); // OK
    immutable b = createB(); // cannot implicitly convert expression `createB()` of type `B` to `immutable(B)`
}

If we mark createB pure, it will compile successfully. This behaviour is described in the spec: createB becomes a pure factory function.

I believe DMD should issue an error for A as well.