DMD 2.102.1:
---
struct S{
int x;
int opApply(scope int delegate(ref int x) dg){
return dg(x);
}
}
ref int foo(ref S s){
foreach(x;s)
return x;
assert(0);
}
void main(){
auto s=new S;
assert(&foo(*s) is &s.x); // fail
}
---
The assertion should pass.
Comment #1 by timon.gehr — 2023-02-25T00:47:20Z
This bug can cause memory corruption in @safe code:
---
struct S{
int* x;
int opApply(scope int delegate(ref int* x)@safe dg)@safe{
return dg(x);
}
}
ref int* foo(ref S s)@safe{
foreach(x;s)
return x;
assert(0);
}
void main()@safe{
auto s=new S;
*foo(*s)=2; // segfault
}
---
Comment #2 by kinke — 2023-02-25T14:28:28Z
The 1st testcase just requires a `foreach (ref x; s)`, which I think is consistent.
The 2nd one never sets `S.x` before dereferencing it, so adding `ref` there still causes a segfault.
Comment #3 by timon.gehr — 2023-02-27T19:47:58Z
(In reply to kinke from comment #2)
> The 1st testcase just requires a `foreach (ref x; s)`, which I think is
> consistent.
>
> The 2nd one never sets `S.x` before dereferencing it, so adding `ref` there
> still causes a segfault.
Oops. Indeed I screwed up when trying to create a reduced test case... My bad. Thanks!
Comment #4 by timon.gehr — 2023-02-27T23:58:17Z
(In reply to kinke from comment #2)
> The 1st testcase just requires a `foreach (ref x; s)`, which I think is
> consistent.
>
> The 2nd one never sets `S.x` before dereferencing it, so adding `ref` there
> still causes a segfault.
Oops. Indeed I screwed up when trying to create a reduced test case... My bad. Thanks!(In reply to timon.gehr from comment #3)
> (In reply to kinke from comment #2)
> > The 1st testcase just requires a `foreach (ref x; s)`, which I think is
> > consistent.
> >
> > The 2nd one never sets `S.x` before dereferencing it, so adding `ref` there
> > still causes a segfault.
>
> Oops. Indeed I screwed up when trying to create a reduced test case... My
> bad. Thanks!
See Issue 23751.