May 09, 2017
On 5/9/17 3:46 PM, Timon Gehr wrote:
> On 09.05.2017 08:17, rikki cattermole wrote:
>> On 09/05/2017 7:10 AM, Jack Stouffer wrote:
>>> On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:
>>>> ...
>>>
>>> I'm going to save you some time and tell you that Andrei and Walter are
>>> going to require a DIP for this.
>>
>> http://forum.dlang.org/thread/oenjmm$lds$1@digitalmars.com
> 
> Also, the DIP has existed for three years, it's just not very polished:
> https://wiki.dlang.org/DIP57

Cool! Now that you also have a proof of concept implementation, could you please flesh that up to make it solid and submit it as a PR? Thanks! -- Andrei
May 09, 2017
On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:
> If you are interested in static foreach making it into the language, please play with the implementation and tell me how to break it.

Code:

void main() {
	void f() { idonotexist(); }
	static foreach(j;0..0) {
		f();
	}
}


Output:

test_staticforeach.d(3): Error: undefined identifier 'idonotexist'
Statement::blockExit(0x7f38d5cd35e0)
static foreach (j; __error)
{
f();
}

core.exception.AssertError@ddmd/blockexit.d(90): Assertion failure
----------------
??:? _d_assertp [0x72e590]
??:? _ZN9blockExit9BlockExit5visitEP9Statement [0x637bd0]
??:? _ZN7Visitor5visitEP22StaticForeachStatement [0x625b45]
??:? _ZN22StaticForeachStatement6acceptEP7Visitor [0x61ebf8]
??:? int ddmd.blockexit.blockExit(ddmd.statement.Statement, ddmd.func.FuncDeclaration, bool) [0x637b69]
??:? _ZN9blockExit9BlockExit5visitEP17CompoundStatement [0x637ef9]
??:? _ZN17CompoundStatement6acceptEP7Visitor [0x61dc61]
??:? int ddmd.blockexit.blockExit(ddmd.statement.Statement, ddmd.func.FuncDeclaration, bool) [0x637b69]
??:? _ZN15FuncDeclaration9semantic3EP5Scope [0x5bba3d]
??:? _ZN6Module9semantic3EP5Scope [0x563f31]
??:? int ddmd.mars.tryMain(ulong, const(char)**) [0x5e2b46]
??:? _Dmain [0x5e3a12]
??:? _D2rt6dmain211_d_run_mainUiPPaPUAAaZiZ6runAllMFZ9__lambda1MFNlZv [0x7301da]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x730124]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).runAll() [0x730196]
??:? scope void rt.dmain2._d_run_main(int, char**, extern (C) int function(char[][])*).tryExec(scope void delegate()) [0x730124]
??:? _d_run_main [0x7300a2]
??:? main [0x5e411f]
??:? __libc_start_main [0xd4999510]

May 09, 2017
On 09.05.2017 23:39, Guillaume Boucher wrote:
> On Tuesday, 9 May 2017 at 03:06:37 UTC, Timon Gehr wrote:
>> If you are interested in static foreach making it into the language,
>> please play with the implementation and tell me how to break it.
>
> Code:
>
> void main() {
>     void f() { idonotexist(); }
>     static foreach(j;0..0) {
>         f();
>     }
> }
>
>
> Output:
>
> test_staticforeach.d(3): Error: undefined identifier 'idonotexist'
> Statement::blockExit(0x7f38d5cd35e0)
> static foreach (j; __error)
> {
> f();
> }
>
> core.exception.AssertError@ddmd/blockexit.d(90): Assertion failure
> ----------------
> ...

Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.)

I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)
May 10, 2017
On 5/10/17 12:56 AM, Timon Gehr wrote:
> Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.) 
> 
> 
> I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)

Ignorant thought: guard the static foreach with a static if? -- Andrei
May 10, 2017
On 5/10/17 1:00 AM, Andrei Alexandrescu wrote:
> On 5/10/17 12:56 AM, Timon Gehr wrote:
>> Thanks! (It's a known issue though: https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.) 
>>
>>
>> I guess the problem is that I do not propagate the error condition properly, but I'm not sure how to do it. (In my frontend, error handling control flow is automated almost completely.)
> 
> Ignorant thought: guard the static foreach with a static if? -- Andrei

(as a lowering that is)

May 10, 2017
On 09.05.2017 23:56, Timon Gehr wrote:
>>
>> core.exception.AssertError@ddmd/blockexit.d(90): Assertion failure
>> ----------------
>> ...
>
> Thanks! (It's a known issue though:
> https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.)
>
>
> I guess the problem is that I do not propagate the error condition
> properly, but I'm not sure how to do it. (In my frontend, error handling
> control flow is automated almost completely.)

https://github.com/dlang/dmd/pull/6760/commits/0ac9556cb3a0e1ea1de02e97e7f05e866584de84
May 10, 2017
On 09.05.2017 23:56, Timon Gehr wrote:
>>
>> core.exception.AssertError@ddmd/blockexit.d(90): Assertion failure
>> ----------------
>> ...
>
> Thanks! (It's a known issue though:
> https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.)
>

Actually, yours is a different case with the same outcome (f and idonotexist do not matter at all, the issue exists even for static foreach(j;0..0){}).
All static foreach loops over empty (non-AliasSeq) aggregates failed that assertion. The reason was that CTFE can return a null literal from a function that returns T[], but the constant folder cannot actually evaluate null.length for some reason.
May 10, 2017
On Wednesday, 10 May 2017 at 09:42:53 UTC, Timon Gehr wrote:
> On 09.05.2017 23:56, Timon Gehr wrote:
>>>
>>> core.exception.AssertError@ddmd/blockexit.d(90): Assertion failure
>>> ----------------
>>> ...
>>
>> Thanks! (It's a known issue though:
>> https://github.com/tgehr/dmd/blob/static-foreach/test_staticforeach.d#L330.)
>>
>
> Actually, yours is a different case with the same outcome (f and idonotexist do not matter at all, the issue exists even for static foreach(j;0..0){}).
> All static foreach loops over empty (non-AliasSeq) aggregates failed that assertion. The reason was that CTFE can return a null literal from a function that returns T[], but the constant folder cannot actually evaluate null.length for some reason.

So here is the difference between null and []:

null :

() { Slice* s; s = null; return s; }

[] :
() { Slice* s; s = alloca(sizeof(*s)); s.base = null; s.length = 0; return s; }

Therefore

null.length => (cast(Slice*)null).length; which results in a segfault.

and

[].length => (cast(Slice*)somevalidSliceDiscriptor).length;
May 10, 2017
On Wednesday, 10 May 2017 at 11:12:06 UTC, Stefan Koch wrote:
> On Wednesday, 10 May 2017 at 09:42:53 UTC, Timon Gehr wrote:
>> [...]
>
> So here is the difference between null and []:
>
> null :
>
> () { Slice* s; s = null; return s; }
>
> [] :
> () { Slice* s; s = alloca(sizeof(*s)); s.base = null; s.length = 0; return s; }
>
> Therefore
>
> null.length => (cast(Slice*)null).length; which results in a segfault.
>
> and
>
> [].length => (cast(Slice*)somevalidSliceDiscriptor).length;

That's not how "regular" D works though.

Atila
May 10, 2017
On Wednesday, 10 May 2017 at 13:11:46 UTC, Atila Neves wrote:
> On Wednesday, 10 May 2017 at 11:12:06 UTC, Stefan Koch wrote:
>> null :
>>
>> () { Slice* s; s = null; return s; }
>>
>> [] :
>> () { Slice* s; s = alloca(sizeof(*s)); s.base = null; s.length = 0; return s; }
>>
>> Therefore
>>
>> null.length => (cast(Slice*)null).length; which results in a segfault.
>>
>> and
>>
>> [].length => (cast(Slice*)somevalidSliceDiscriptor).length;
>
> That's not how "regular" D works though.
>
> Atila

What do you mean ?
Hmm this should be how it works ....
They reason why assert([] == null) holds.
is because base is implicitly alias thised.

if you try assert([] is null), it should fail.