Thread overview
SumType!(A,B) != SumType!(B,A) - a bug?
December 26

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

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

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

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

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.