Thread overview
[Issue 1878] New: foreach does not handle integral types appropriately
Feb 28, 2008
d-bugmail
Oct 28, 2012
Andrej Mitrovic
Sep 08, 2013
Lionello Lunesu
Sep 08, 2013
Lionello Lunesu
February 28, 2008
http://d.puremagic.com/issues/show_bug.cgi?id=1878

           Summary: foreach does not handle integral types appropriately
           Product: D
           Version: unspecified
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: DMD
        AssignedTo: bugzilla@digitalmars.com
        ReportedBy: andrei@metalanguage.com


ubyte limit = whatever();
ubyte x;
foreach (e; 0 .. limit)
   x = e;

does not compile with warnings enabled. The compiler should recognize that a
compile-time constant (in this case 0) is passed in and choose the tightest
type (in this case ubyte) for iteration.


-- 

October 28, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1878


Andrej Mitrovic <andrej.mitrovich@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |andrej.mitrovich@gmail.com


--- Comment #1 from Andrej Mitrovic <andrej.mitrovich@gmail.com> 2012-10-28 16:06:36 PDT ---
I think a language change might end up breaking code which assumes the index variable is always size_t.

The simplest workaround is to type the index variable:
    foreach (ubyte e; 0 .. limit)
        writeln(e);

Otherwise if we want type inference we could implement a library function:

import std.stdio;

struct Walk(T)
{
    T idx;
    T max;

    @property T front() { return idx; }
    @property void popFront() { ++idx; }
    @property bool empty() { return !(idx < max); }
}

auto walk(L, U)(L lwr, U upr)
{
    assert(lwr <= U.max);
    return Walk!U(cast(U)lwr, upr);
}

void main()
{
    ubyte limit = 10;
    ubyte x;

    foreach (e; walk(0, limit))
    {
        writefln("%s %s", typeid(e), e);  // type is ubyte
    }
}

-- 
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
October 28, 2012
http://d.puremagic.com/issues/show_bug.cgi?id=1878


bearophile_hugs@eml.cc changed:

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


--- Comment #2 from bearophile_hugs@eml.cc 2012-10-28 16:32:52 PDT ---
A wider benchmark:


import std.typetuple: TypeTuple;
import std.range: iota;
void main() {
    foreach (T; TypeTuple!(byte, ubyte, short, ushort,
                           int, uint, long, ulong))
        foreach (i; 0 .. cast(T)10)
            pragma(msg, T, "  ", typeof(i));
    pragma(msg, "");
    foreach (T; TypeTuple!(byte, ubyte, short, ushort,
                           int, uint, long, ulong))
        foreach (i; iota(0, cast(T)10))
            pragma(msg, T, "  ", typeof(i));
}


byte  int
ubyte  int
short  int
ushort  int
int  int
uint  uint
long  long
ulong  ulong

byte  int
ubyte  int
short  int
ushort  int
int  int
uint  uint
long  long
ulong  ulong

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


Lionello Lunesu <lio+bugzilla@lunesu.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |lio+bugzilla@lunesu.com


--- Comment #3 from Lionello Lunesu <lio+bugzilla@lunesu.com> 2013-09-08 01:42:44 PDT ---
This bug is also the source of many false positives when bug 259 gets fixed.

The problem is that ForeachRangeStatement is using typeCombine, which does the C style integer promotion. It should probably use the ?: combine logic instead.

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



--- Comment #4 from Lionello Lunesu <lio+bugzilla@lunesu.com> 2013-09-08 02:14:15 PDT ---
I checked the difference between CondExp (?:) and ForeachRangeStatement. The former only has a special case when the types of the two expressions are equal. It would fix foreach(i;ubyte..ubyte) and similar, but would not address the issue raised by the OP.

It's still worth merging the logic of CondExp with ForeachRangeStatement, though, if only for predictability. In fact, a?0:ubyte should similarly not evaluate to 'int' but to 'ubyte', for the exact same reasons.

https://github.com/D-Programming-Language/dmd/pull/2538

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



--- Comment #5 from github-bugzilla@puremagic.com 2013-09-12 22:03:13 PDT ---
Commit pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/565caec167fa303cb2320a2c6d8f957f06d07008 Merge pull request #2538 from lionello/bug1878

foreach range uses same logic as ?: for type deduction

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