digitalmars.D.learn - How can I tell D that function args are nogc etc.
- John Dougan (47/47) Apr 09 Below is a example program that illustrates my issue.
- Richard (Rikki) Andrew Cattermole (38/38) Apr 10 Place your attributes on the right hand side of the function, not the
- Steven Schveighoffer (28/32) Apr 10 Just a word of warning, this explanation suggests putting
- John Dougan (23/33) Apr 10 Interesting. Thank you to both of you.
- Steven Schveighoffer (26/56) Apr 11 So D can provide a nice mechanism to show what is happening --
- John Dougan (21/37) Apr 11 `pragma(msg,...)` is very useful. Thanks.
- Steven Schveighoffer (5/8) Apr 12 https://issues.dlang.org
- John Dougan (30/39) Apr 12 The typical problem with issue/bug database searches is you have
- Monkyyy (7/9) Apr 13 D is uniquely: hacky, expressive and buggy.
Below is a example program that illustrates my issue. When compiled at run.dlang I get: ``` onlineapp.d(18): Error: ` safe` function `onlineapp.processSafely!(1, 4).processSafely` cannot call ` system` function pointer `shouldDo` onlineapp.d(28): Error: template instance `onlineapp.processSafely!(1, 4)` error instantiating ``` Why isn't this working? How can I get the effect I want? Cheers, -- john ``` bool[7] stagesToProcess = false; nogc nothrow safe bool shouldDoInStages(int index) { return stagesToProcess[index]; } nogc nothrow safe bool shouldDoNever(int index) { return false; } template processSafely(int low, int high) { alias ShouldDoFnT = nogc nothrow safe bool function(int); nogc nothrow safe uint processSafely(ShouldDoFnT shouldDo) { assert(low < high); uint stepsProcessed; for (int ii = low; ii <= high; ii++) { if (shouldDo(ii)) { stepsProcessed++; } } return stepsProcessed; } } void main() { stagesToProcess = [false, false, true, true, false, true, false]; uint count = processSafely!(1, 4)(&shouldDoInStages); assert(count == 2); } ```
Apr 09
Place your attributes on the right hand side of the function, not the left side. Use the left side for attributes/type qualifiers that go on the return type. ```d bool[7] stagesToProcess = false; bool shouldDoInStages(int index) nogc nothrow safe { return stagesToProcess[index]; } bool shouldDoNever(int index) nogc nothrow safe { return false; } template processSafely(int low, int high) { alias ShouldDoFnT = bool function(int) nogc nothrow safe; uint processSafely(ShouldDoFnT shouldDo) nogc nothrow safe { assert(low < high); uint stepsProcessed; for (int ii = low; ii <= high; ii++) { if (shouldDo(ii)) { stepsProcessed++; } } return stepsProcessed; } } void main() { stagesToProcess = [false, false, true, true, false, true, false]; uint count = processSafely!(1, 4)(&shouldDoInStages); assert(count == 2); } ```
Apr 10
On Wednesday, 10 April 2024 at 11:34:06 UTC, Richard (Rikki) Andrew Cattermole wrote:Place your attributes on the right hand side of the function, not the left side. Use the left side for attributes/type qualifiers that go on the return type.Just a word of warning, this explanation suggests putting qualifiers on the left side would affect the return type, this is not the case. Attributes apply to the *declaration*. In some cases this effectively applies to the return type, in some cases it applies to the function, in some cases it applies to the context pointer. In order to apply type constructors to the return type, you need to use parentheses: ```d const int foo(); // const applies to the context pointer of `foo`, not `int` const(int) bar(); // const applies to `int` return type ref int baz(); // ref applies to `baz`, which in turn means "ref returning function" ``` Where this becomes tricky is return types that are function pointers/delegates. Then using the right side of the function/delegate *type* is the only way. ```d safe void function() foo(); // `foo` is safe, the function pointer it returns is not void function() safe bar(); // `bar` is not safe, the function pointer returned is void function() safe baz() safe; // both are safe ``` -Steve
Apr 10
Interesting. Thank you to both of you. On Wednesday, 10 April 2024 at 17:38:21 UTC, Steven Schveighoffer wrote:On Wednesday, 10 April 2024 at 11:34:06 UTC, Richard (Rikki) Andrew Cattermole wrote:So in my example, what did I actually tell the compiler with the placement of the attributes? And how was it different between the function type alias declaration, and the actual function declaration? More specifically, what are the semantic differences below? ```d alias FnPrefixT = nogc nothrow safe bool function(int); // Versus alias FnSuffixT = bool function(int) nogc nothrow safe; ``` and ```d nogc nothrow safe bool fnPrefix(int) { stuff } // Versus bool fnSuffix(int) nogc nothrow safe { stuff } ``` Is there a reasonably clear overview of how this works anywhere? What I have seen so far led me to the vague impression that it wasn't significant just like attribute ordering. -- johnPlace your attributes on the right hand side of the function, not the left side. Use the left side for attributes/type qualifiers that go on the return type.Just a word of warning, this explanation suggests putting qualifiers on the left side would affect the return type, this is not the case.
Apr 10
On Thursday, 11 April 2024 at 03:17:36 UTC, John Dougan wrote:Interesting. Thank you to both of you. On Wednesday, 10 April 2024 at 17:38:21 UTC, Steven Schveighoffer wrote:So D can provide a nice mechanism to show what is happening -- `pragma(msg, ...)` If I do that with the two types above I see something *very* interesting: ```d pragma(msg, FnPrefixT); pragma(msg, FnSuffixT); ``` ``` bool function(int) nothrow nogc bool function(int) nothrow nogc safe ``` That surprises me. `nothrow` and ` nogc` go onto the type, but not ` safe` if put before the declaration? I have no idea why. All I can think of is that it is a bug.On Wednesday, 10 April 2024 at 11:34:06 UTC, Richard (Rikki) Andrew Cattermole wrote:So in my example, what did I actually tell the compiler with the placement of the attributes? And how was it different between the function type alias declaration, and the actual function declaration? More specifically, what are the semantic differences below? ```d alias FnPrefixT = nogc nothrow safe bool function(int); // Versus alias FnSuffixT = bool function(int) nogc nothrow safe; ```Place your attributes on the right hand side of the function, not the left side. Use the left side for attributes/type qualifiers that go on the return type.Just a word of warning, this explanation suggests putting qualifiers on the left side would affect the return type, this is not the case.and ```d nogc nothrow safe bool fnPrefix(int) { stuff } // Versus bool fnSuffix(int) nogc nothrow safe { stuff } ``````d pragma(msg, typeof(fnPrefix)); pragma(msg, typeof(fnSuffix)); ``` ``` nothrow nogc safe bool(int) nothrow nogc safe bool(int) ``` (as expected) -Steve
Apr 11
On Thursday, 11 April 2024 at 15:00:49 UTC, Steven Schveighoffer wrote:So D can provide a nice mechanism to show what is happening -- `pragma(msg, ...)` If I do that with the two types above I see something *very* interesting: ```d pragma(msg, FnPrefixT); pragma(msg, FnSuffixT); ``` ``` bool function(int) nothrow nogc bool function(int) nothrow nogc safe ``` That surprises me. `nothrow` and ` nogc` go onto the type, but not ` safe` if put before the declaration? I have no idea why. All I can think of is that it is a bug.`pragma(msg,...)` is very useful. Thanks. My general impressions were correct then. It shouldn't matter on which side the attrs get put, except in some ambiguous cases. It's just broken. Not every day you get to blame a compiler bug. Feeding: ```d alias FnPrefixT = safe nothrow nogc bool function(int); alias FnSuffixT = bool function(int) safe nothrow nogc ; pragma(msg, FnPrefixT); pragma(msg, FnSuffixT); void main() { return; } ``` into run.dlang and having it compile with all the compilers...gets the same result all the way back to 2.060. It has this issue with gdc 2.076, which is what I'm using normally. What is the procedure for bug reporting? I'm looking at the issues tracker and have no clue how to drive the search to see if this is already there.-Steve-- john
Apr 11
On Friday, 12 April 2024 at 03:57:40 UTC, John Dougan wrote:What is the procedure for bug reporting? I'm looking at the issues tracker and have no clue how to drive the search to see if this is already there.https://issues.dlang.org While entering the bug title, it does a fuzzy search for existing open and closed issues. -Steve
Apr 12
On Friday, 12 April 2024 at 15:08:50 UTC, Steven Schveighoffer wrote:On Friday, 12 April 2024 at 03:57:40 UTC, John Dougan wrote:The typical problem with issue/bug database searches is you have to know the important discriminating keywords that projects evolve over time. When you are new to a system, as I am with D, you end up looking manually through a lot of possibles. Another barrier to noobs that project long timers may not notice. Any rate, it appears https://issues.dlang.org/show_bug.cgi?id=22046 is the same issue. And I'm not sure how to interpret it, as a noob I don't have enough context. It appears to be deliberate and also afflicts var declarations. Since 2014. From my point of view, either it's still a bug and needs to be written up in a best practices list with all the other long term stuff you need to work around until it can be fixed (eg. "in alias and var function declarations, put attributes as a suffix because...", https://dlang.org/dstyle.html *might* be a place), or it has aged in to become the effective intended behavior and should be documented other places and have a compiler error or warning (" safe in prefix position in alias, is ignored"). Or of course, it could get fixed but my experiences have shown me that after 10 years that is low probability with most projects. I'm not trying to be a dick here. I've managed projects and know what unintentional dumb stuff can happen. But, at the moment, I'm evaluating D for a project (porting 30,000 lines of very old C with strict timing requirements) and I've got some time to build impressions of system language candidates. There appears to be a lot of talk from time to time over in General about luring new people in to work with D, and this kind of issue is relevant.What is the procedure for bug reporting? I'm looking at the issues tracker and have no clue how to drive the search to see if this is already there.https://issues.dlang.org While entering the bug title, it does a fuzzy search for existing open and closed issues.-Steve--john
Apr 12
On Friday, 12 April 2024 at 03:57:40 UTC, John Dougan wrote:Not every day you get to blame a compiler bug.D is uniquely: hacky, expressive and buggy. Having more metaprograming then c++ without the raw man power comes at a cost, in d you should distrust the spec and instead see what the compiler actually does far more then any other languge.-- john-- monkyyy
Apr 13