Bug 17486 – lazy parameters can be used to hijack the pure system

Status
NEW
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2017-06-09T19:26:15Z
Last change time
2024-12-13T18:52:31Z
Assigned to
No Owner
Creator
Eyal
See also
https://issues.dlang.org/show_bug.cgi?id=17487
Moved to GitHub: dmd#17797 →

Comments

Comment #0 by eyal — 2017-06-09T19:26:15Z
void f(lazy int x) @nogc { x; // Error: @nogc function 'f' cannot call non-@nogc delegate 'x' } void g(lazy int x) nothrow { x; // Error: 'x' is not nothrow } There's no way to annotate the implicit delegate is @nogc, nothrow, etc.
Comment #1 by eyal — 2017-06-09T19:33:48Z
This also breaks purity type checking: @safe: import std.stdio:writeln; void f(lazy int x) pure { x(); } unittest { int g() { writeln("impure func called by pure func!"); return 5; } auto xx = (() => g()); writeln("-> f"); f(xx()); writeln("<- f"); } outputs: -> f impure func called by pure func! <- f
Comment #2 by eyal — 2017-06-09T19:44:40Z
Better bug reproduction: @safe: void f(ref int counter, lazy int x) pure { x(); counter++; x(); } void main() { int counter; int g() { import std.stdio:writeln; writeln("counter: ", counter); return 5; } f(counter, g); } // prints: counter: 0 counter: 1 Making it clearer that we're being allowed to pass an impure delegate into a pure function that then calls it.
Comment #3 by greensunny12 — 2017-06-09T23:59:00Z
For @nogc and nothrow there's already an open issue: https://issues.dlang.org/show_bug.cgi?id=12647 The other looks like a recent regression (so I am changing the title).
Comment #4 by eyal — 2017-06-10T06:26:26Z
The solution, clearly is to treat "lazy" is mere syntactic sugar to passing delegates - thus adding syntactic support for @nogc/etc attribute annotation on "lazy" parameters - and specifying their attributes just like is done for delegates. The assumption that lazy parameters are all pure is wrong (thus this ticket). The assumption that lazy parameters are all gc/throw is wrong (thus the other ticket). It *cannot* be inferred unless lazy parameters make everything a template, which would be unfortunate. Just like delegate parameter attributes cannot be inferred - you have to manually specify them or templatize over the delegate type.
Comment #5 by robert.schadek — 2024-12-13T18:52:31Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17797 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB