www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.bugs - [Issue 5713] New: Broken final switch on ints

reply d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713

           Summary: Broken final switch on ints
           Product: D
           Version: D2
          Platform: All
        OS/Version: All
            Status: NEW
          Keywords: accepts-invalid
          Severity: enhancement
          Priority: P2
         Component: DMD
        AssignedTo: nobody puremagic.com
        ReportedBy: bearophile_hugs eml.cc



The purpose of "final switch" is to increase code safety compared to normal
switches on enums. This D2 program compiles and runs with no errors (dmd
2.052):


void main() {
    int x = 100;
    final switch (x % 3) {
        case 0: break;
        case 1: break;
    }
}


Two possible ways for the D compiler to manage this code:
- Disallow it, not allowing final switches on int values;
- Manage it correctly and require the case "case 2:" too.
- (A third possibility: ignore the limited range of the switching value and
requiring coverage of the whole integer range, but this is not a good
solution).

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 07 2011
next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


Stewart Gordon <smjg iname.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |spec, wrong-code
                 CC|                            |smjg iname.com



At first I thought maybe it was ignoring the error out of knowledge that x % 3
== 1 in this instance.  But no - it still accepts (and runs without even a
SwitchError) if I change x to 101.

But you'd need to cover -1 and -2 as well for this to make sense.

The spec doesn't actually disallow it:
http://www.digitalmars.com/d/2.0/statement.html#FinalSwitchStatement

"A final switch statement is just like a switch statement, except that:

    * No DefaultStatement is allowed.
    * No CaseRangeStatements are allowed.
    * If the switch Expression is of enum type, all the enum members must
appear in the CaseStatements.
    * The case expressions cannot evaluate to a run time initialized value."

But this seems to be a mistake, and that no SwitchError is thrown strikes me as
a bug.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 07 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




See also bug 5714

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Mar 07 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




See also bug 6060

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
May 26 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




This code is a reduction of real code, with small changes. It shows why this
final switch brokeness makes final switch not as safe as advertised:


void main() {
    enum Foo { A, B }
    enum Bar { C = 5, D = 6 }
    int fe; // first mistake, fe is not Foo
    bool someCondition = true;
    if (someCondition)
        fe = Bar.C; // second mistake, fe is not assigned to a Foo
    final switch (fe) {
        case Foo.A: break;
        case Foo.B: break;
    }
}


The code contains two mistakes, the first is giving fe int type instead of Foo.
The second mistake is assigning  to fe an invalid enum value. The final switch
doesn't catch the wrong enum value of fe, and it asks for no default case
because it's supposed to be complete. The final switch spec need to be
improved.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 20 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




An example from Timon Gehr, this gives no compilation errors, and prints
nothing:


import std.stdio;
enum Mode { nothing, read, write }
void main() {
    final switch (Mode.read | Mode.write) {
        case Mode.nothing: writeln(0); break;
        case Mode.read:    writeln(1); break;
        case Mode.write:   writeln(2); break;
    }
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Sep 07 2011
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




Commit pushed to https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/11738ba260ced4d522d2334c5e99059a2517035d
fix Issue 5713 - Broken final switch on ints

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


Walter Bright <bugzilla digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |RESOLVED
                 CC|                            |bugzilla digitalmars.com
         Resolution|                            |FIXED


-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Jan 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


Denis <verylonglogin.reg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |verylonglogin.reg gmail.com



---

 An example from Timon Gehr, this gives no compilation errors, and prints
 nothing:
 
 
 import std.stdio;
 enum Mode { nothing, read, write }
 void main() {
     final switch (Mode.read | Mode.write) {
         case Mode.nothing: writeln(0); break;
         case Mode.read:    writeln(1); break;
         case Mode.write:   writeln(2); break;
     }
 }
Created issue 7358 inspired by this (inspired but different because this code can be statically rejected). -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


Denis <verylonglogin.reg gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|FIXED                       |



---
As bearophile wrote in issue 6060 description:
in 5713 I don't like an error message (and I'd like the compiler to enforce the
presence of the cases for 0,1, and 2)
So this issue requires the following function be compilable _iff_ every `case` is present: --- void f(int x) { final switch (x % 3) { case -2: case -1: case 0: case 1: case 2: } } --- -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Jan 24 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




Turning bugs into enhancement requests is a good way to reduce bug count, but
it doesn't address the problems. 

"enhancement" sounds like something that someone wants to add, like switching
on structs. But this is not the case. Given a sane definition of final switch,
asking the compiler to refuse code like this at compile-time is not an
enhancement:


void main() {
    int x = 100;
    final switch (x % 3) {
        case 0: break;
        case 1: break;
    }
}


Then maybe we need a "wrong_specs" tag in Bugzilla, for the situations where
the compiler is working as the spec say, but where the spec themselves look
wrong.

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Feb 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


yebblies <yebblies gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |yebblies gmail.com




 Then maybe we need a "wrong_specs" tag in Bugzilla, for the situations where
 the compiler is working as the spec say, but where the spec themselves look
 wrong.
The problem with this is that it is completely subjective. The line between 'I wish D had this' and 'It is a design error that D doesn't have this' varies from person to person, and without hard rules having a keyword to distinguish between them is useless. I don't have a solution for this, but the people fixing bugs and implementing features are well aware that enhancement means 'not a priority' not 'won't happen'. -- Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email ------- You are receiving this mail because: -------
Feb 05 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


Rene <reneduani yahoo.com.br> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |reneduani yahoo.com.br



Ok, this change broke my code that I wrote *following the spec*. And it only
breaks on runtime! The fix was simple (adding a case 0: break;), but still the
spec needs to be updated if you guys are changing it. 

And breaking changes that don't give compiler errors on now-wrong-code are
quite nasty...

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Aug 31 2012
prev sibling next sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713


bearophile_hugs eml.cc changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Severity|enhancement                 |major



This issue was definitively mislabelled, this is clearly a bug, and even
significant. Bumped to major.



void main() {
    bool b;
    final switch (b) {
        case true:
            break;
    }
}

It compiles without errors.

At runtime gives:


core.exception.SwitchError test(3): No appropriate switch clause found

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
Dec 23 2012
prev sibling parent d-bugmail puremagic.com writes:
http://d.puremagic.com/issues/show_bug.cgi?id=5713




See also this thread:
http://forum.dlang.org/thread/hoczugrnzfbtvpnwjevd forum.dlang.org


I think this code should be supported, because here the compiler is able to
statically enforce that every possible ushort value is covered by exactly one
of the final switch cases:


void main () {
    ushort x;
    final switch (x) {
        case 0: .. case 1000:
            break;
        case 1001: .. case ushort.max:
            break;
    }
}


See also issue 5714

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