Bug 5730 – __traits(compiles) does not handle "variable has scoped destruction, cannot build closure" error correctly

Status
REOPENED
Severity
normal
Priority
P3
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2011-03-11T10:22:17Z
Last change time
2024-12-13T17:55:04Z
Assigned to
No Owner
Creator
Max Samukha
Moved to GitHub: dmd#18335 →

Comments

Comment #0 by samukha — 2011-03-11T10:22:17Z
The below should compile without errors: struct S { ~this() { } } void main() { S s; enum error = __traits(compiles, { auto s1 = s; })); static assert(!error); // line 1 } ---- Error: static assert (!true) is false Comment out "line 1" to get the error that explains the problem: Error: variable test.main.s has scoped destruction, cannot build closure
Comment #1 by bugzilla — 2011-03-12T00:50:04Z
Right. {auto s1=s;} is a delegate literal. Delegate literals need to be able to survive the end of the function they are defined inside. Since s is destroyed upon the exit from main(), then this will not work, hence the error message. This is expected behavior, not a bug.
Comment #2 by samukha — 2011-03-12T01:53:09Z
No, no. The bug is not about the impossibility to build a closure. It is about __traits(compiles) not handling the compilation error properly. It should suppress the error and evaluate to false. Another example: struct S { ~this() { } } void main() { S s; static if (__traits(compiles, { auto s1 = s; })) pragma(msg, "Can build closure"); else pragma(msg, "Cannot build closure"); } ---- The compiler outputs: Can build closure Error: variable test.main.s has scoped destruction, cannot build closure Instead, the above should compile successfully, printing "Cannot build closure" at compile time.
Comment #3 by samukha — 2011-03-12T02:37:00Z
Changed the title
Comment #4 by clugdbug — 2011-03-12T11:48:11Z
This is happening because the "has scoped destruction" error is generated in the glue layer, not in the front-end. The same issue applies to any error message generated in e2ir.c, toir.c, or s2ir.c.
Comment #5 by k.hara.pg — 2015-07-07T17:08:57Z
(In reply to Max Samukha from comment #2) > No, no. The bug is not about the impossibility to build a closure. It is > about __traits(compiles) not handling the compilation error properly. It > should suppress the error and evaluate to false. Today, a delegate literal in __traits(compiles) does not make the outer function closure, because the delegate is just a thing only in compile time. I'd provide better example code: struct S { ~this() {} } void main() { enum r = __traits(compiles, { auto madeClosure() { S s; auto dg = { auto s1 = s; }; return dg; } }); static assert(!r); // line 1 } The madeClosure function will be made a closure, because the dg that refers local variable s will escape from that. Then the "has scoped destruction..." error needs to be captured by the __traits(compile) and r should be false.
Comment #6 by razvan.nitu1305 — 2021-03-16T08:30:56Z
Today this code compiles succesfully and prints "destructor": struct S { ~this() { import std.stdio; writeln("destructor"); } } void main() { S s; enum error = __traits(compiles, { auto s1 = s; }); //static assert(!error); // line 1 } It seems that the compiler is able to allocate the closure and also track it with the gc. Closing as fixed.
Comment #7 by ibuclaw — 2022-03-28T13:06:20Z
Related test still fails though. struct S10666 { int val; ~this() {} } void foo10666(S10666 s1) { // Error: s1 has scoped destruction, cannot build closure. auto f1 = (){ return () => s1.val; }(); enum r1 = __traits(compiles, { auto f1 = (){ return () => s1.val; }(); }); static assert(!r1); // Error: static assert: `!r1` is false }
Comment #8 by robert.schadek — 2024-12-13T17:55:04Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/18335 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB