Bug 23739 – Can't return by ref from opApply iteration

Status
RESOLVED
Resolution
INVALID
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2023-02-25T00:44:00Z
Last change time
2023-02-27T23:58:17Z
Keywords
safe, wrong-code
Assigned to
No Owner
Creator
timon.gehr
See also
https://issues.dlang.org/show_bug.cgi?id=23751

Comments

Comment #0 by timon.gehr — 2023-02-25T00:44:00Z
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.