Bug 22154 – Pure functions should be able to use only the address of a global

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2021-07-28T15:50:19Z
Last change time
2024-12-13T19:17:41Z
Assigned to
No Owner
Creator
Andrei Alexandrescu
Moved to GitHub: dmd#19962 →

Comments

Comment #0 by andrei — 2021-07-28T15:50:19Z
Consider: __gshared int a; pure int fun(int* x) { if (x == &a) return 1; return 42; } This does not compile. However, it does not depend on global modifiable state because the address of a global is a runtime invariant.
Comment #1 by pro.mathias.lang — 2021-07-28T16:01:54Z
If we allow it, what prevents the function from then passing it down to another pure function that will read / write to it ?
Comment #2 by andrei — 2021-07-28T17:45:07Z
(In reply to Mathias LANG from comment #1) > If we allow it, what prevents the function from then passing it down to > another pure function that will read / write to it ? Good point. There'd need to be appropriate restrictions, e.g. the address is read but not passed around. This issue prevents the application of the Null Object Pattern (https://en.wikipedia.org/wiki/Null_object_pattern) to Appender in Phobos. I started modifying the code around https://github.com/dlang/phobos/blob/master/std/array.d#L3264 like this: private static __gshared Data nullData = { 0, null, false }; private Data* _data = &nullData; It worked really nice because subsequently I could eliminate most tests comparing _data against null - they just worked with the empty data. The one place I had to test was at https://github.com/dlang/phobos/blob/master/std/array.d#L3356, where I replaced `if (!_data)` with `if (_data != &nullData)`. That made the function impure and caused a bunch of compile-time errors for no good reason.
Comment #3 by n8sh.secondary — 2021-07-29T00:40:28Z
Putting the address in an enum appears to work: --- __gshared int a; pure int fun(int* x) { enum int* addr = &a; if (x == addr) return 1; return 42; } ---
Comment #4 by kinke — 2021-07-29T04:37:51Z
> Putting the address in an enum appears to work: As does making the global immutable: pure int fun(int* x) { static immutable int a; if (x == &a) return 1; return 42; }
Comment #5 by kinke — 2021-07-29T04:48:54Z
(In reply to Nathan S. from comment #3) > Putting the address in an enum appears to work: Seems like a great way to violate purity: pure int fun(int* x) { enum int* addr = &a; *addr = *x; // boom return 42; }
Comment #6 by robert.schadek — 2024-12-13T19:17:41Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/19962 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB