Bug 18587 – Context pointer not set for delegate template parameter when declared in struct body

Status
RESOLVED
Resolution
WONTFIX
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86
OS
Windows
Creation time
2018-03-10T16:45:28Z
Last change time
2018-03-12T07:07:34Z
Assigned to
No Owner
Creator
Simen Kjaeraas

Comments

Comment #0 by simen.kjaras — 2018-03-10T16:45:28Z
struct S { int n; R!(() => n) a; } struct R(alias fn) { int get() { return fn(); } } unittest { auto s = S(3); assert(s.a.get() == 3); } The above code fails with 'Error: need 'this' for 'n' of type 'int''. It is clear that the intended semantics of the above code is similar to this: struct S { int n; auto a() { return R!(() => n)(); } } struct R(alias fn) { int get() { return fn(); } } unittest { auto s = S(3); assert(s.a.get() == 3); } However, the latter example works, while the former doesn't. This leads to unnecessary boilerplate and unreadable code.
Comment #1 by simen.kjaras — 2018-03-12T07:07:34Z
Since structs in D are movable by simple blitting with no cleanup step, this is impossible. If we consider this code again: struct S { int n; R!(() => n) a; } struct R(alias fn) { int get() { return fn(); } } The layout of R would essentially be this: struct R(alias fn) { S* context; } Thus, the layout of S would essentially be this: struct S { int n; S* a.context; } That's an internal pointer, and runs afoul of this section of the GC spec[0]: > Do not have pointers in a struct instance that point back to the same instance. The trouble with this is if the instance gets moved in memory, the pointer will point back to where it came from, with likely disastrous results. [0]: https://dlang.org/spec/garbage.html