Bug 14618 – can break immutable with inout and a delegate

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2015-05-23T19:42:44Z
Last change time
2024-12-13T18:42:59Z
Keywords
accepts-invalid, safe
Assigned to
No Owner
Creator
ag0aep6g
Moved to GitHub: dmd#18992 →

Comments

Comment #0 by ag0aep6g — 2015-05-23T19:42:44Z
struct S { immutable(int)* p; } inout(int)* f(inout S s) { inout(int)* result; auto dg = (inout(int)* p) {result = p;}; dg(s.p); return result; } void main() { immutable int x = 42; immutable int* p = &x; assert(*p == 42); /* passes */ scope(exit) assert(*p == 42); /* fails */ int* m = f(S(p)); /* uh-oh */ *m = 13; /* writing over immutable *p */ }
Comment #1 by ag0aep6g — 2017-07-25T10:04:05Z
Also possible in @safe code: ---- struct S { immutable(int)* p; } inout(int)* f(inout S s) @safe { inout(int)* result; auto dg = (inout(int)* p) {result = p;}; dg(s.p); return result; } void main() @safe { immutable int* p = new int(42); assert(*p == 42); /* passes */ scope(exit) assert(*p == 42); /* fails */ int* m = f(S(p)); /* uh-oh */ *m = 13; /* writing over immutable *p */ } ----
Comment #2 by bugzilla — 2018-03-04T01:54:26Z
If I prepend: @safe: to the code: (In reply to ag0aep6g from comment #0) > struct S > { > immutable(int)* p; > } > > inout(int)* f(inout S s) > { > inout(int)* result; > auto dg = (inout(int)* p) {result = p;}; > dg(s.p); > return result; > } > > void main() > { > immutable int x = 42; > immutable int* p = &x; Error: cannot take address of local x in @safe function main > assert(*p == 42); /* passes */ > scope(exit) assert(*p == 42); /* fails */ > int* m = f(S(p)); /* uh-oh */ > *m = 13; /* writing over immutable *p */ > }
Comment #3 by bugzilla — 2018-03-04T01:57:46Z
The second example is still a bug.
Comment #4 by ag0aep6g — 2018-03-04T11:50:12Z
(In reply to Walter Bright from comment #2) > If I prepend: > > @safe: > > to the code: [...] > Error: cannot take address of local x in @safe function main Compile with `-dip1000` and add `scope` to `f`'s parameter and it compiles again: ---- @safe: struct S { immutable(int)* p; } inout(int)* f(scope inout S s) { inout(int)* result; auto dg = (inout(int)* p) {result = p;}; dg(s.p); return result; } void main() { immutable int x = 42; immutable int* p = &x; assert(*p == 42); /* passes */ scope(exit) assert(*p == 42); /* fails */ int* m = f(S(p)); /* uh-oh */ *m = 13; /* writing over immutable *p */ } ---- The `scope` on the parameter is wrong here, of course, but the compiler doesn't catch it.
Comment #5 by robert.schadek — 2024-12-13T18:42:59Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18992 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB