D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 1245 - static foreach shouldn't define new scope and introduce new variables
Summary: static foreach shouldn't define new scope and introduce new variables
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D1 (retired)
Hardware: x86 Linux
: P2 enhancement
Assignee: No Owner
URL:
Keywords: rejects-valid
Depends on:
Blocks:
 
Reported: 2007-05-23 15:37 UTC by Witold Baryluk
Modified: 2014-02-16 15:23 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Witold Baryluk 2007-05-23 15:37:59 UTC
import std.stdio;

void Code(x...)() {
        foreach (i, xi; x) {
                static if (xi != 0) { // dosn't works, see below
              //static if (x[i] != 0) { // workaround
                        writefln(xi);
                }
        }
}


void main() {
        alias Code!(1, 6, 0, 2, 5) c;
        c();
}

// staticforeachif.d(5): Error: expression xi != 0 is not constant 
// or does not evaluate to a bool

with workaround, it works, and display:
1
6
2
5
as needed

Imho foreach over tupple shouldn't introduce new scope and variables xi,
but as static if be in the same scope (if needed you always can add { .. }
and xi (second parameter in foreach), should be actually alias to x[i]

I'm using this in optimalisation of general code generators.
Comment 1 Stewart Gordon 2007-05-25 04:48:06 UTC
Huh?  What is a "static foreach"?  If there's any reference to it in the spec, it isn't obvious.
Comment 2 Witold Baryluk 2007-05-25 08:05:09 UTC
http://www.digitalmars.com/d/tuple.html Looping section.
Foreach over tuple works like static foreach, and it is unrolled in compile time.
Comment 3 Stewart Gordon 2007-05-25 11:49:05 UTC
I see.

But I'm not sure I see how it would work to make foreach not define a scope in such circumstances.  OTOH, I agree that xi should be recognised as constant.
Comment 4 BCS 2007-05-25 12:17:17 UTC
The issue I have is that int the foreach loop the value of i gets pushed onto the stack. (I was looking at the ASM dump from DMD linux)

foreach(i, j; T!(1,2,3)
{
   asm{nop;};
} 

should compeile to
nop;
nop;
nop;
Comment 5 Witold Baryluk 2007-05-29 00:27:31 UTC
Another example:

module staticforeach_switch;

import std.stdio;

template Tuple(E...) { alias E Tuple; }
alias Tuple!(101.0, 102.0, 103.0, 104.0) coef;

double f(int l, double x) {
   switch (l) {
     foreach (i, a_i; coef) {
        case i:
            //return x*a_i; // compiles and gives garbage
            return x*coef[i]; // works
      }
        default:
            assert(0);
   }
   assert(0);
}

void main() {
        writefln(f(3, 2.0)); // 2*104 = 208
}
Comment 6 Witold Baryluk 2009-11-18 21:41:58 UTC
I just tested this both my codes (from "Description" and "Comment 5") in DMD 2.032, and they works correctly! (only switch isn't full optimal in asm, but this not conected with this bug).

BCS's example with nop's is also not optimal, there are some operations on EBP register:
		mov	dword ptr -034h[EBP],1
		nop
		mov	dword ptr -02Ch[EBP],2
		nop
		mov	dword ptr -024h[EBP],3
		nop
		mov	dword ptr -01Ch[EBP],5
		nop
		mov	dword ptr -014h[EBP],6
		nop
		mov	dword ptr -0Ch[EBP],7
		nop


I don't remember any changelog entry mentioning anything about foreach over tuples... Anyone want to enlighten me? :) And what about DMD 1.x?
Comment 7 bearophile_hugs 2010-04-12 17:52:10 UTC
This is now fixed in DMD 1.058 and 2.043.