Thread overview
CT foreaches
Aug 01
monkyyy
Aug 01
monkyyy
August 01
import std;
void foo(int i:0)()=>"foo".writeln;
void foo(int i:1)()=>"bar".writeln;
void foo(int i:2)()=>"foobar".writeln;
void main(){
	foreach(i,alias b; AliasSeq!("foo","bar")){
		pragma(msg, b.stringof);
	        break;
	}
	pragma(msg,"---");
	foreach(i,enum b; AliasSeq!("foo","bar")){
		pragma(msg, b.stringof);
		break;
	}
	pragma(msg,"---");
	static foreach(i;0..3){
		pragma(msg, i.stringof);
		//break; //the scope error
	}
	pragma(msg,"---");
	foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
		pragma(msg, i.stringof);
		//foo!i; //doesnt compile
		break;
	}
}

Theres bugs and unintended features here :D ; alias foreach is undocumented even in the template book; the dip 1010 code block that may be why this behavior exists doesnt actaully work, the docs were wrong a week ago

etc. etc.

currently I believe:

a) static makes it a block, makes enum or alias infered
b) enum or alias of aliasSeq, whoever made thought there be an upgrade to fully generalize the syntax
c) the dip 1010 section was ambiguous if it was real causing enum to be ignored

anyone got any code blocks?

August 01

On Friday, 1 August 2025 at 13:51:43 UTC, monkyyy wrote:

>
import std;
void foo(int i:0)()=>"foo".writeln;
void foo(int i:1)()=>"bar".writeln;
void foo(int i:2)()=>"foobar".writeln;
void main(){
	foreach(i,alias b; AliasSeq!("foo","bar")){
		pragma(msg, b.stringof);
	        break;
	}
	pragma(msg,"---");
	foreach(i,enum b; AliasSeq!("foo","bar")){
		pragma(msg, b.stringof);
		break;
	}
	pragma(msg,"---");
	static foreach(i;0..3){
		pragma(msg, i.stringof);
		//break; //the scope error
	}

Up to here is all as expected, right?

>

pragma(msg,"---");
foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
pragma(msg, i.stringof);
//foo!i; //doesnt compile

You're using runtime foreach here. It's only expanded at compile-time when the aggregate is a sequence - as the spec says.

The confusing thing is that enum there is silently ignored. I think we could add an error for that.

>
  break;

}
}


Theres bugs and unintended features here :D ; alias foreach is undocumented even in the template book;

That hasn't been updated in 8 years.

>

the dip 1010 code block that may be why this behavior exists doesnt actaully work, the docs were wrong a week ago

etc. etc.

currently I believe:

a) static makes it a block, makes enum or alias infered
b) enum or alias of aliasSeq, whoever made thought there be an upgrade to fully generalize the syntax

Not sure what you mean for (b).

>

c) the dip 1010 section was ambiguous if it was real causing enum to be ignored

anyone got any code blocks?

August 01

On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:

>

Up to here is all as expected, right?

No, foreach(alias is functionally undocumented (dip 1010 is not exactly common reading material for current year, and if you did read it, it would have errors or misunderstanding for what eventually happened) and extremely rare

> >

pragma(msg,"---");
foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
pragma(msg, i.stringof);
//foo!i; //doesnt compile

You're using runtime foreach here. It's only expanded at compile-time when the aggregate is a sequence - as the spec says.

foreach(enum i;0..3){ is directly from the dip 1010 its unclear from the responce if it was accepted or rejected

> >

b) enum or alias of aliasSeq, whoever made thought there be an upgrade to fully generalize the syntax

Not sure what you mean for (b).

dip 1010 was optimistic about near term upgrades to static foreach; static break and continue


>

The confusing thing is that enum there is silently ignored. I think we could add an error for that.

That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it

August 01

On Friday, 1 August 2025 at 15:47:47 UTC, monkyyy wrote:

>

On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:

>

Up to here is all as expected, right?

No, foreach(alias is functionally undocumented

Thanks, fix:
https://github.com/dlang/dlang.org/pull/4279

> > >
pragma(msg,"---");
foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
	pragma(msg, i.stringof);
	//foo!i; //doesnt compile

You're using runtime foreach here. It's only expanded at compile-time when the aggregate is a sequence - as the spec says.

foreach(enum i;0..3){ is directly from the dip 1010 its

That's under the 'Limitations of this DIP / possible future improvements' section:
https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#allowing-alias-and-enum-on-regular-foreach-loop-variables

>

unclear from the responce if it was accepted or rejected

That DIP says 'Status: Accepted' at the top.

> > >

b) enum or alias of aliasSeq, whoever made thought there be an upgrade to fully generalize the syntax

Not sure what you mean for (b).

dip 1010 was optimistic about near term upgrades to static foreach; static break and continue


>

The confusing thing is that enum there is silently ignored. I think we could add an error for that.

That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it

Not really, no one should have used enum/alias with a non-static ForeachRangeStatement because (as you pointed out), it wasn't in the spec. If they did use it, they'd probably realize that those storage classes had no effect.

August 01
On Friday, 1 August 2025 at 16:45:04 UTC, Nick Treleaven wrote:
> On Friday, 1 August 2025 at 15:47:47 UTC, monkyyy wrote:
>> On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:
>>> The confusing thing is that enum there is silently ignored. I think we could add an error for that.
>>
>> That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it
>
> Not really, no one should have used enum/alias with a non-static ForeachRangeStatement because (as you pointed out), it wasn't in the spec. If they did use it, they'd probably realize that those storage classes had no effect.

Making non-static `foreach (enum x; l .. u)` an error would be fairly easy. It’s just a parser issue. The error message could say: Use `static foreach`. I’ll have a go on this.
August 02
On 8/1/25 20:06, Quirin Schroll wrote:
> On Friday, 1 August 2025 at 16:45:04 UTC, Nick Treleaven wrote:
>> On Friday, 1 August 2025 at 15:47:47 UTC, monkyyy wrote:
>>> On Friday, 1 August 2025 at 15:15:35 UTC, Nick Treleaven wrote:
>>>> The confusing thing is that enum there is silently ignored. I think we could add an error for that.
>>>
>>> That would be a breaking change now, most code swapped from runtime to ct should continue working tho, better to just implement it
>>
>> Not really, no one should have used enum/alias with a non-static ForeachRangeStatement because (as you pointed out), it wasn't in the spec. If they did use it, they'd probably realize that those storage classes had no effect.
> 
> Making non-static `foreach (enum x; l .. u)` an error would be fairly easy. It’s just a parser issue. The error message could say: Use `static foreach`. I’ll have a go on this.

For reference:

https://github.com/dlang/dmd/issues/21630
https://github.com/dlang/dmd/pull/21631
https://github.com/dlang/dmd/pull/21633

My PR is currently blocked on a weird CI failure, not sure where it is coming from.
August 02
On 8/1/25 15:51, monkyyy wrote:
> ```d
> import std;
> void foo(int i:0)()=>"foo".writeln;
> void foo(int i:1)()=>"bar".writeln;
> void foo(int i:2)()=>"foobar".writeln;
> void main(){
>      foreach(i,alias b; AliasSeq!("foo","bar")){
>          pragma(msg, b.stringof);
>              break;
>      }
>      pragma(msg,"---");
>      foreach(i,enum b; AliasSeq!("foo","bar")){
>          pragma(msg, b.stringof);
>          break;
>      }


These behave like lined out in Proposal 1 of DIP 1010.

Code snippets from the DIP:

```d
foreach (enum v; AliasSeq!(x,y,z)) { ... }
```

```d
foreach (alias v; AliasSeq!(x,y,z)) { }
```

https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#proposal-1-allow-enum-and-alias-variables-for-unrolled-foreach-statements

>      pragma(msg,"---");
>      static foreach(i;0..3){
>          pragma(msg, i.stringof);
>          //break; //the scope error
>      }
>      pragma(msg,"---");

This is just a standard `static foreach`.

>      foreach(enum i;0..3){// ERROR ISNT CT. ISNT AN ENUM
>          pragma(msg, i.stringof);
>          //foo!i; //doesnt compile
>          break;
>      }
> }
> ```
> ...

This one is a bug, quote from DIP1010:

> Currently, it is an error to use alias or enum on a regular foreach loop:
>
> ```d
> foreach (enum i; 0 .. 3){ ... } // error
> ```
>
> It has been suggested that this should instead unroll the loop, such that it becomes equivalent to:
>
> ```d
> foreach (enum i; AliasSeq!(0,1,2)) { ... }
> ```

https://github.com/dlang/DIPs/blob/master/DIPs/accepted/DIP1010.md#allowing-alias-and-enum-on-regular-foreach-loop-variables

https://github.com/dlang/dmd/issues/21630
https://github.com/dlang/dmd/pull/21631