Thread overview | |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 16, 2018 How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Hi, I previously had trouble trying to get print statements working while debugging in nogc. And that was hackishly solved [0], but I can't figure out how to do the same if I have @safe involved. Here's a cut down sample: // This is the function from the thread referenced auto assumeNoGC(T)(T t) { import std.traits; enum attrs = functionAttributes!T | FunctionAttribute.nogc; return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; } private struct Dispatcher { public template opDispatch(string name){ auto ref opDispatch(Args...)(auto ref Args args) { import std.stdio; // Print args here for debugging purposes assumeNoGC({ writeln(args); })(); return 3; } } } @safe @nogc void main() { auto i = Dispatcher().getI(3); } So, basically with the above, using: debug writeln(args); Causes "Error: @nogc function D main cannot call non-@nogc function" Using: debug assumeNoGC({ writeln(args); })(); Causes: Error: @safe function D main cannot call @system function Error: @nogc function D main cannot call non-@nogc function Changing attrs in assumeNoGC enum attrs = functionAttributes!T | FunctionAttribute.nogc | FunctionAttribute.safe Causes same as previous errors Adding @trusted to declaration of opDispatch gets rid of @safe error but I still get "Error: @nogc function D main cannot call non-@nogc function". And going through the codebase and figuring out where to add @trusted is *very* cumbersome. I can't figure out how to make this work. The ideal way would be just a debug_print() function that works in nogc and safe code. I.e. does not affect the attribute inference of templates. Cheers, - Ali [0] https://forum.dlang.org/post/pmf4dm$jmo$1@digitalmars.com |
November 16, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | debug { import std.stdio; writeln(args); } |
November 16, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Friday, 16 November 2018 at 12:59:22 UTC, aliak wrote: > Adding @trusted to declaration of opDispatch gets rid of @safe error but I still get "Error: @nogc function D main cannot call non-@nogc function". And going through the codebase and figuring out where to add @trusted is *very* cumbersome. > > I can't figure out how to make this work. The ideal way would be just a debug_print() function that works in nogc and safe code. I.e. does not affect the attribute inference of templates. As Zoadian points out, you can now (since 2.079: https://dlang.org/changelog/2.079.0.html#bugfix-list) shamelessly call @nogc inside debug blocks. To get at where the problematic areas were in the code in question though, it's as follows: > auto assumeNoGC(T)(T t) { // point 1 > import std.traits; > enum attrs = functionAttributes!T | FunctionAttribute.nogc; > // point 2: > return cast(SetFunctionAttributes!(T, functionLinkage!T, attrs)) t; > } At 'point 1', you just take by value. If `t` ends up being a closure, D will allocate. That's where it breaks the @nogc. Solution: auto assumeNoGC(T)(return scope T t) { /* ... */ } Now you take (and return) a `scope` t, in that case when `t` is a closure D won't allocate it on the GC heap. At 'point 2' you make an un-@safe cast, that's where it breaks @safe. Given that the whole deal is just a debugging hack, you could mark the whole function @trusted: auto assumeNoGC(T)(return scope T t) @trusted { /* ... */ } |
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Zoadian | On Friday, 16 November 2018 at 13:03:40 UTC, Zoadian wrote:
> debug {
> import std.stdio;
> writeln(args);
> }
As mentioned in the original post, that does not work.
|
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Friday, 16 November 2018 at 13:21:39 UTC, Stanislav Blinov wrote:
> At 'point 1', you just take by value. If `t` ends up being a closure, D will allocate. That's where it breaks the @nogc. Solution:
>
> auto assumeNoGC(T)(return scope T t) { /* ... */ }
>
> Now you take (and return) a `scope` t, in that case when `t` is a closure D won't allocate it on the GC heap.
>
> At 'point 2' you make an un-@safe cast, that's where it breaks @safe. Given that the whole deal is just a debugging hack, you could mark the whole function @trusted:
>
> auto assumeNoGC(T)(return scope T t) @trusted { /* ... */ }
Sawweet! Thanks, that made the printing possible!
"scope" is const from what I understand right? It works without scope as well. So just "return T".
Cheers,
- Ali
|
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Saturday, 17 November 2018 at 13:13:36 UTC, aliak wrote: > Sawweet! Thanks, that made the printing possible! You're welcome ;) Still, try a more recent compiler. This works fine: void foo() @nogc { debug { import std.stdio; writefln("%d", 42); } } > "scope" is const from what I understand right? It works without scope as well. So just "return T". No, "scope" means "does not escape scope", i.e. you can't assign that argument to some global. The only exception is through a return, in which case "return" also needed. Whether or not just "return" is sufficient, is a bit out there still (AFAIK), between DIP25, DIP1000 and current state of the language. "scope" was implemented for delegates for ages now, exactly to allow passing lambdas around without allocating their context on the GC heap. |
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Saturday, 17 November 2018 at 13:13:36 UTC, aliak wrote:
> On Friday, 16 November 2018 at 13:21:39 UTC, Stanislav Blinov wrote:
>> auto assumeNoGC(T)(return scope T t) @trusted { /* ... */ }
>
> Sawweet! Thanks, that made the printing possible!
>
> "scope" is const from what I understand right? It works without scope as well. So just "return T".
No, `in` used to mean const scope.
scope means roughly "this thing does not escape this function" e.g. assigning to global variables.
|
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Stanislav Blinov | On Saturday, 17 November 2018 at 13:43:20 UTC, Stanislav Blinov wrote: > On Saturday, 17 November 2018 at 13:13:36 UTC, aliak wrote: > >> Sawweet! Thanks, that made the printing possible! > > You're welcome ;) Still, try a more recent compiler. This works fine: > > void foo() @nogc { > debug { > import std.stdio; > writefln("%d", 42); > } > } Yeah that does, but not the code I posted -> https://run.dlang.io/is/vH3cFa You can use "debug blah" to hide inside functions that are attributed, but when you have an attributed function that calls a template, attribtues of which are supposed to be inferred, it seems to fail. Maybe a bug if it's supposed to work? > >> "scope" is const from what I understand right? It works without scope as well. So just "return T". > > No, "scope" means "does not escape scope", i.e. you can't assign that argument to some global. The only exception is through a return, in which case "return" also needed. Whether or not just "return" is sufficient, is a bit out there still (AFAIK), between DIP25, DIP1000 and current state of the language. > "scope" was implemented for delegates for ages now, exactly to allow passing lambdas around without allocating their context on the GC heap. Aha, cool. Thanks! |
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to Nicholas Wilson | On Saturday, 17 November 2018 at 13:46:00 UTC, Nicholas Wilson wrote:
> On Saturday, 17 November 2018 at 13:13:36 UTC, aliak wrote:
>> On Friday, 16 November 2018 at 13:21:39 UTC, Stanislav Blinov wrote:
>>> auto assumeNoGC(T)(return scope T t) @trusted { /* ... */ }
>>
>> Sawweet! Thanks, that made the printing possible!
>>
>> "scope" is const from what I understand right? It works without scope as well. So just "return T".
>
> No, `in` used to mean const scope.
>
> scope means roughly "this thing does not escape this function" e.g. assigning to global variables.
Righto! Thanks!
|
November 17, 2018 Re: How do you debug @safe @nogc code? Can't figure out how to print. | ||||
---|---|---|---|---|
| ||||
Posted in reply to aliak | On Saturday, 17 November 2018 at 13:55:24 UTC, aliak wrote:
> You can use "debug blah" to hide inside functions that are attributed, but when you have an attributed function that calls a template, attribtues of which are supposed to be inferred, it seems to fail.
>
> Maybe a bug if it's supposed to work?
Indeed that fails, and I would say that's a bug. If it's allowed in @nogc, it shouldn't then infer to non-@nogc when not explicitly attributed. Maybe debug blocks should outright be skipped when inferring?..
|
Copyright © 1999-2021 by the D Language Foundation