Thread overview
[Issue 11051] New: Unmatched case in a final switch should throw in both release and non-release mode
Sep 16, 2013
Andrej Mitrovic
Sep 16, 2013
Andrej Mitrovic
Sep 16, 2013
Andrej Mitrovic
Sep 16, 2013
Maxim Fomin
Sep 16, 2013
Orvid King
September 16, 2013
http://d.puremagic.com/issues/show_bug.cgi?id=11051

           Summary: Unmatched case in a final switch should throw in both
                    release and non-release mode
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Severity: major
          Priority: P2
         Component: DMD
        AssignedTo: nobody@puremagic.com
        ReportedBy: andrej.mitrovich@gmail.com


--- Comment #0 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-16 07:14:09 PDT ---
-----
module test;

import std.stdio;

enum E { a }

string get()
{
    auto e = cast(E)123;
    final switch(e)
    {
        case E.a:
            return "foobar";
    }
}

void main()
{
    writeln(get());
}
-----

$ dmd -run test.d
> core.exception.SwitchError@test(10): No appropriate switch clause found

$ dmd -release -run test.d
> x ↑

The release switch ends up making get() return garbage.

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


bearophile_hugs@eml.cc changed:

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


--- Comment #1 from bearophile_hugs@eml.cc 2013-09-16 07:29:13 PDT ---
Letting it throw an error in non-release mode kills some of optimization you are supposed to have using a final switch, so I am not sure it's a good idea.

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



--- Comment #2 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-16 07:34:50 PDT ---
(In reply to comment #1)
> Letting it throw an error in non-release mode kills some of optimization you are supposed to have using a final switch, so I am not sure it's a good idea.

You mean *in release mode*, right? It currently throws in non-release mode, it doesn't throw in release mode.

But what is the above code supposed to do if not throw in both cases?

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



--- Comment #3 from bearophile_hugs@eml.cc 2013-09-16 07:42:32 PDT ---
(In reply to comment #2)
> You mean *in release mode*, right?

Right, sorry.


> It currently throws in non-release mode, it doesn't throw in release mode.

This seems good to me. If you want to convert an untrusted value to an enum safely you should use std.conv.to:


import std.stdio, std.conv;

enum E { a }

string get() {
    //immutable e = cast(E)123;
    immutable e = to!E(123);
    final switch(e) {
        case E.a: return "foobar";
    }
}
void main() {
    get.writeln;
}

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



--- Comment #4 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2013-09-16 07:56:31 PDT ---
(In reply to comment #3)
> This seems good to me.

No, returning garbage is not good. At the very least I expect a HALT instruction after the final switch for code which should not reach that point.

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


Maxim Fomin <maxim@maxim-fomin.ru> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |maxim@maxim-fomin.ru


--- Comment #5 from Maxim Fomin <maxim@maxim-fomin.ru> 2013-09-16 08:08:27 PDT ---
(In reply to comment #3)
> (In reply to comment #2)
> > You mean *in release mode*, right?
> 
> Right, sorry.
> 
> 
> > It currently throws in non-release mode, it doesn't throw in release mode.
> 
> This seems good to me. If you want to convert an untrusted value to an enum safely you should use std.conv.to:
> 
> 
> import std.stdio, std.conv;
> 
> enum E { a }
> 
> string get() {
>     //immutable e = cast(E)123;
>     immutable e = to!E(123);
>     final switch(e) {
>         case E.a: return "foobar";
>     }
> }
> void main() {
>     get.writeln;
> }

No, you will run into memory errors. Either dmd should still throw SwitchError or insert halt instruction.

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



--- Comment #6 from Orvid King <blah38621@gmail.com> 2013-09-16 09:03:51 PDT ---
(In reply to comment #1)
> Letting it throw an error in non-release mode kills some of optimization you are supposed to have using a final switch, so I am not sure it's a good idea.

But an error isn't covered by the nothrow contract, so you wouldn't be able to optimize that anyways.

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