Thread overview
[Issue 10253] New: Switch and Final Switch do not work with subtyping
Jun 03, 2013
Andrej Mitrovic
Jun 03, 2013
Andrej Mitrovic
Jun 03, 2013
Andrej Mitrovic
Jun 03, 2013
Andrej Mitrovic
June 03, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10253

           Summary: Switch and Final Switch do not work with subtyping
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: andrej.mitrovich@gmail.com


--- Comment #0 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-06-03 07:00:42 PDT ---
-----
struct Wrapper(E) if (is(E == enum))
{
    E value;
    alias value this;
}

void main()
{
    enum E { a, b }

    alias Wrapper!E WE;
    WE we;

    switch (we)  // L14
    {
        case WE.a: break;
        case WE.b: break;
        default:
    }

    final switch (we)  // L21
    {
        case WE.a: break;
        case WE.b: break;
    }
}
-----

test.d(14): Error: 'we' must be of integral or string type, it is a Wrapper!(E)
test.d(16): Error: cannot implicitly convert expression (cast(E)0) of type E to
Wrapper!(E)
test.d(17): Error: cannot implicitly convert expression (cast(E)1) of type E to
Wrapper!(E)
test.d(21): Error: 'we' must be of integral or string type, it is a Wrapper!(E)
test.d(23): Error: cannot implicitly convert expression (cast(E)0) of type E to
Wrapper!(E)
test.d(24): Error: cannot implicitly convert expression (cast(E)1) of type E to
Wrapper!(E)

The use-case is the ability to define an enum wrapper which disables default-initialization of the enum and requires explicit initialization, for example:

-----
struct ExplicitEnum(E) if (is(E == enum))
{
    @disable this();
    this(E e) { value = e; }

    E value;
    alias value this;
}

///
unittest
{
    /**
        The library writer would typically disallow access to
        this enum so it can never be directly used in user-code.
    */
    /* private */ enum MachineEnum
    {
        X86,
        X86_64,
    }

    // the fake enum type
    alias Machine = ExplicitEnum!MachineEnum;

    static assert(!__traits(compiles,
    {
        Machine machine;  // compile-time error
    }()));

    Machine machine = Machine.X86;  // ok
}
-----

The only missing puzzle piece is the ability to use a switch/final switch on such a wrapper type.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 03, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10253



--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-06-03 07:06:49 PDT ---
Btw, if there is ever an ambiguity problem on whether to switch on the struct value or the 'alias this' value, then perhaps this feature should only be enabled if the struct has only one field which is the 'alias this' field?

Think of it as an "eponymous struct" (maybe that's a bad terminology..).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 03, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10253



--- Comment #2 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-06-03 07:16:11 PDT ---
(In reply to comment #1)
> Btw, if there is ever an ambiguity problem on whether to switch on the struct value or the 'alias this' value, then perhaps this feature should only be enabled if the struct has only one field which is the 'alias this' field?
> 
> Think of it as an "eponymous struct" (maybe that's a bad terminology..).

Forget this whole comment, I *thought* that switching on a struct was already possible. But it isn't, so there's no ambiguity here.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 03, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10253


bearophile_hugs@eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |bearophile_hugs@eml.cc


--- Comment #3 from bearophile_hugs@eml.cc 2013-06-03 09:45:02 PDT ---
(In reply to comment #2)

> I *thought* that switching on a struct was already possible. But it isn't, so there's no ambiguity here.

The enhancement request for structs in switches is Issue 596 (Issue 596 also
asks for a standard method named unapply() that's called by the switch).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
June 03, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=10253



--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-06-03 10:05:54 PDT ---
(In reply to comment #3)
> (In reply to comment #2)
> 
> > I *thought* that switching on a struct was already possible. But it isn't, so there's no ambiguity here.
> 
> The enhancement request for structs in switches is Issue 596 (Issue 596 also
> asks for a standard method named unapply() that's called by the switch).

I see. In that case the following would be an ambiguity:

-----
enum E { a, b }

struct S
{
    int x;
    E e;
    alias e this;
}

auto s = S(0, E.a);
switch (s)  // switch on 's' value or 's.e' value?
{
}
-----

In that case I propose the subtype switch would only work if the struct has only one member which is the alias this variable:

-----
struct S
{
    E e;
    alias e this;
}

auto s = S(E.a);
switch (s)  // ok: equivalent to switch on 's.e'
{
}
-----

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------