www.digitalmars.com         C & C++   DMDScript  

digitalmars.dip.development - [First Draft] Add gc as a Function Attribute

reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
Permalink: 
https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

---

**Abstract:** Add ` gc` as a new function attribute that acts as 
the inverse of the ` nogc` attribute.
Jun 14
next sibling parent reply "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 15/06/2024 4:20 AM, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md
 
 ---
 
 **Abstract:** Add ` gc` as a new function attribute that acts as the 
 inverse of the ` nogc` attribute.
At some point I wanted to do a DIP that ensured all attributes had a positive form, a common negated syntax `` !identifier``, changed throwing to be set based `` throws(...)`` and add `` notls``, `` localnogc``. So I'm in support of this proposal, but it doesn't go anywhere near where it needs to in terms of scope. You're welcome to do the proposal instead as I'm busy on other things atm if it interests you.
Jun 14
next sibling parent reply ryuukk_ <ryuukk.dev gmail.com> writes:
On Friday, 14 June 2024 at 16:38:09 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 On 15/06/2024 4:20 AM, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md
 
 ---
 
 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
At some point I wanted to do a DIP that ensured all attributes had a positive form, a common negated syntax `` !identifier``, changed throwing to be set based `` throws(...)`` and add `` notls``, `` localnogc``. So I'm in support of this proposal, but it doesn't go anywhere near where it needs to in terms of scope. You're welcome to do the proposal instead as I'm busy on other things atm if it interests you.
Why couldn't attributes accept a parameter, perhaps a flag ` gc(:yes | :local)`
Jun 16
next sibling parent "Richard (Rikki) Andrew Cattermole" <richard cattermole.co.nz> writes:
On 16/06/2024 8:13 PM, ryuukk_ wrote:
 Why couldn't attributes accept a parameter, perhaps a flag
 
 | gc(:yes | :local)|
Right now we have yes/no, infer(red)/explicit bit fields for some flags. The only attribute that we've had consistent desire to have local for is `` nogc`` it doesn't need to be supported for all. As positive/negative state of an annotate are both common things, it should take minimal characters to represent, in this case a single additional ``!``. So I don't think we need to over complicate it by introducing parameters to any attributes other than for the throws set and thats only because we need to be able to represent what a value type exception style exceptional handling mechanism would be returning in the type system.
Jun 16
prev sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Sunday, 16 June 2024 at 08:13:33 UTC, ryuukk_ wrote:
 Why couldn't attributes accept a parameter, perhaps a flag

 ` gc(:yes | :local)`
Attributes taking booleans would be a separate DIP. As I wrote in my answer to Rikki, local nogc should not be an attribute at all. C++ made `noexcept` take a boolean. C++ also made `noexcept` a unary operator that returns a boolean if the expression inside uses only `noexcept` stuff. D could easily do the same with `nothrow` and `pure` (as those are first-class keywords). It makes less sense for ` safe` (a program is supposed to be UB-free anyways), but it would make sense for ` nogc`. I don’t think D would be clever to follow C++’s syntax with a prefix operator. [My preferred syntax would be postfix](https://issues.dlang.org/show_bug.cgi?id=23797) `is pure`, `is nothrow`, `is nogc`, and yes, even `is safe`. Those would operate on types, though, meaning you’d have to write `typeof({ expression; }) is nogc`. The `typeof` returns a function pointer or delegate type which has attributes inferred and those attributes can be queried using the new syntax. You could use these together: ```d void higherOrderFunction(DG)(scope DG callback) safe(DG is safe) nogc(DG is nogc) { … } ``` As for the query for member function attributes that are also type qualifiers, I’d suggest a syntax similar to the one I proposed in [Issue 20010)](https://issues.dlang.org/show_bug.cgi?id=20010): `DG is ...const`. For example, a template could have an `if (DG is ... const pure)` restriction so that it’s guaranteed the callback’s results can be cached. (If a delegate isn’t `const` it can maintain state in its context, and if it’s not pure, it can maintain state globally.)
Jun 17
prev sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Friday, 14 June 2024 at 16:38:09 UTC, Richard (Rikki) Andrew 
Cattermole wrote:
 On 15/06/2024 4:20 AM, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md
 
 ---
 
 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
At some point I wanted to do a DIP that ensured all attributes had a positive form, a common negated syntax `` !identifier``, changed throwing to be set based `` throws(...)`` and add `` notls``, `` localnogc``.
This is like 4 orthogonal proposals. I have no clue what ` notls` would do exactly. If anything, `localnogc` should be a pragma (probably named differently) as it provides no actual guarantees. I know from other posts that its intention is to particularly guarantee that array literals and closures present in the function block aren’t GC-allocated. It means nothing for the caller of a function, it only means something for the implementer. The question if a closure is allocated or not is practically the same if the compiler recognizes your specific case. It does not make sense as a function attribute as a caller need not know about it. Set-based exception specifications are controversial. I’m not sure if they’re a win or not, but this proposal is completely unrelated. Zig has them, but Zig has return-based exceptions, where anything other than a white list of possible exceptions is hard to imagine. Java’s are considered a failure and C++ removed them.
 So I'm in support of this proposal, but it doesn't go anywhere 
 near where it needs to in terms of scope.
Yes, the scope of this DIP is to be small and uncontroversial.
 You're welcome to do the proposal instead as I'm busy on other 
 things atm if it interests you.
The `pragma(nogcClosures)` and `pragma(nogcArrayLiterals)` should not even require a DIP. I cannot write anything about `notls` as I don’t know what it means. I can write a DIP for a complete revision of guarantee-making attributes, and that would include things like attribute `inout`s/attribute variables. I once wrote a DIP draft for something like that; ADAs comes close. My takeaway is that very ambitious DIPs generally make it nowhere. My sense is: Let’s first add contravariant inverses (guarantee-absence indicating) for ` nogc` and `pure`. Those solve a very basic non-orthogonality issue. Then let’s talk about guarantee-making attributes taking booleans or variables for guarantee-making attributes.
Jun 17
prev sibling next sibling parent reply jmh530 <john.michael.hall gmail.com> writes:
On Friday, 14 June 2024 at 16:20:02 UTC, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

 ---

 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
The DIP makes it seem like it is an escape-hatch for nogc. But then nogc would no longer be providing any guarantees.
Jun 14
parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Friday, 14 June 2024 at 19:19:15 UTC, jmh530 wrote:
 On Friday, 14 June 2024 at 16:20:02 UTC, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

 ---

 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
The DIP makes it seem like it is an escape-hatch for nogc. But then nogc would no longer be providing any guarantees.
You didn’t understand the DIP. It’s not an escape hatch. ` gc` is just an explicit form of the default behavior allowing GC allocations. You can’t call a ` gc` function from a ` nogc` function, the same as you can’t call a ` system` function from a ` safe` function.
Jun 17
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 17 June 2024 at 11:37:22 UTC, Quirin Schroll wrote:
 On Friday, 14 June 2024 at 19:19:15 UTC, jmh530 wrote:
 [snip]

 The DIP makes it seem like it is an escape-hatch for  nogc. 
 But then  nogc would no longer be providing any guarantees.
You didn’t understand the DIP. It’s not an escape hatch. ` gc` is just an explicit form of the default behavior allowing GC allocations. You can’t call a ` gc` function from a ` nogc` function, the same as you can’t call a ` system` function from a ` safe` function.
I said "The DIP makes it seem like it is an escape-hatch". I didn't say "The DIP introduces an escape-hatch". It's not that I didn't understand it, so much as I'm doing my best to try to understand what it says and coming to an understanding that is inconsistent with what I think you intend. In the rationale section, you detail the motivation relating to the issue of dealing with adding a function that allocates with the GC to nogc blocks. You then introduce the example ```d nogc { int[] f() => [1]; // Error: array literal in ` nogc` function `f` may cause a GC allocation int[] g() gc => [1]; // Okay, `g` is not ` nogc` } ``` This makes it seem like you can have a function that may cause a GC allocation in a nogc block by adding the gc attribute. Maybe that's not what you intended, but you should spell it out in more detail if you intend something else. If gc means not nogc, then how can the compiler verify that it can be called from a nogc block?
Jun 17
parent reply Dom DiSc <dominikus scherkl.de> writes:
On Monday, 17 June 2024 at 13:02:12 UTC, jmh530 wrote:
 If  gc means not  nogc, then how can the compiler verify that 
 it can be called from a  nogc block?
A block is nothing. A block cannot call anything, it's just a kind of namespace, meaning the same as declaring every function within it as " nogc". Of course nogc functions _cannot_ call a function marked as gc.
Jun 17
parent reply jmh530 <john.michael.hall gmail.com> writes:
On Monday, 17 June 2024 at 13:10:16 UTC, Dom DiSc wrote:
 On Monday, 17 June 2024 at 13:02:12 UTC, jmh530 wrote:
 If  gc means not  nogc, then how can the compiler verify that 
 it can be called from a  nogc block?
A block is nothing. A block cannot call anything, it's just a kind of namespace, meaning the same as declaring every function within it as " nogc". Of course nogc functions _cannot_ call a function marked as gc.
My point is that the current behavior is that you know that every function within ` nogc {}` does not allocate with the GC. Under this DIP, that's no longer guaranteed. So fine, it's not an "escape-hatch" per se, but it means that when you see ` nogc {}` or ` nogc:` it won't mean what it meant before. At the very least, if I can misunderstand it, then others could too.
Jun 17
parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Monday, 17 June 2024 at 13:36:25 UTC, jmh530 wrote:
 On Monday, 17 June 2024 at 13:10:16 UTC, Dom DiSc wrote:
 On Monday, 17 June 2024 at 13:02:12 UTC, jmh530 wrote:
 If  gc means not  nogc, then how can the compiler verify that 
 it can be called from a  nogc block?
A block is nothing. A block cannot call anything, it's just a kind of namespace, meaning the same as declaring every function within it as " nogc". Of course nogc functions _cannot_ call a function marked as gc.
My point is that the current behavior is that you know that every function within ` nogc {}` does not allocate with the GC. Under this DIP, that's no longer guaranteed. So fine, it's not an "escape-hatch" per se, but it means that when you see ` nogc {}` or ` nogc:` it won't mean what it meant before.
It’s similar to how ` safe:` and ` safe{}` don’t mean every function that follows is ` safe` because there can be ` system` or ` trusted` functions, and for `nothrow:`, while not implemented, the DIP adding `throw` as its inverse has been accepted. The general consensus is that guarantee-making attributes (` safe`, `pure`, `nothrow`, and ` nogc`) all should have inverses, and the only question is, what syntax they’ll have. This is answered for two of them already (` system` and `throw`); this DIP answers it for the one of the two remaining ones for which is very easy: ` gc`.
 At the very least, if I can misunderstand it, then others could 
 too.
It seems you didn’t actually misunderstand it, I just misunderstood you when you used the term _escape-hatch_ because an example of what I consider an escape-hatch is ` trusted`. I thought, you thought ` gc` would be the ` trusted` equivalent of ` nogc`, which it’s definitely not supposed to be.
Jun 17
prev sibling next sibling parent reply Mathias Lang <geod24 gmail.com> writes:
On Friday, 14 June 2024 at 16:20:02 UTC, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

 ---

 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
The rationale is very weak. If the only use case is to support bad usage of ` attribute:` or ` attribute {}`, there is no benefit at all to this.
Jun 17
next sibling parent Dom DiSc <dominikus scherkl.de> writes:
On Monday, 17 June 2024 at 22:01:18 UTC, Mathias Lang wrote:
 On Friday, 14 June 2024 at 16:20:02 UTC, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

 ---

 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
The rationale is very weak. If the only use case is to support bad usage of ` attribute:` or ` attribute {}`, there is no benefit at all to this.
I don't think so. If a program is all nogc except a single function (or even a unittest), using nogc: is plausible. I wouldn't call this "bad usage". But at the moment there is no way to mark this single test as "not nogc". I find this situation annoying. The same problem arises with pure:
Jun 18
prev sibling parent Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Monday, 17 June 2024 at 22:01:18 UTC, Mathias Lang wrote:
 On Friday, 14 June 2024 at 16:20:02 UTC, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

 ---

 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
The rationale is very weak. If the only use case is to support bad usage of ` attribute:` or ` attribute {}`, there is no benefit at all to this.
It’s exactly as strong or weak as adding `throw` as the inverse of `nothrow` was. The only argument that is different between DIP 1029 and this is that `throw` was already a keyword whereas ` gc` would have to be added. Compare that to the (hypothetical) suggestion of adding `impure` as a keyword to have an inverse of `pure`.
Jun 19
prev sibling next sibling parent reply Walter Bright <newshound2 digitalmars.com> writes:
On 6/14/2024 9:20 AM, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md
 
 ---
 
 **Abstract:** Add ` gc` as a new function attribute that acts as the inverse
of 
 the ` nogc` attribute.
 
I've been thinking about a ` default` attribute, which will reset the state of attributes to the defaults. This will obviate the need for gc, impure, throw, and so forth.
Jun 21
next sibling parent Dom DiSc <dominikus scherkl.de> writes:
On Saturday, 22 June 2024 at 04:37:01 UTC, Walter Bright wrote:
 I've been thinking about a ` default` attribute, which will 
 reset the state of attributes to the defaults. This will 
 obviate the need for  gc,  impure,  throw, and so forth.
But will bite us if we ever changing the default :-/
Jun 22
prev sibling parent reply Quirin Schroll <qs.il.paperinik gmail.com> writes:
On Saturday, 22 June 2024 at 04:37:01 UTC, Walter Bright wrote:
 On 6/14/2024 9:20 AM, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md
 
 ---
 
 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
 
I've been thinking about a ` default` attribute, which will reset the state of attributes to the defaults. This will obviate the need for gc, impure, throw, and so forth.
It doesn’t. Having a formal name for the inverse of an attribute has several advantages over just saying “default,” e.g. the compiler today spells out ` system` when printing function (pointer) and delegate types. Likewise, one can declare a function (template) explicitly ` system` and it would allow one to be explicit about ` gc` things. If anything, I’d want to see `default` with regards to attributes used in a block or label statement with the meaning of changing the default attributes, but not touch inference. Something like: ```d nogc safe { void f() { … } // ` nogc safe` by ` safe` ` nogc` block void g(T)() { … } // ` gc`/` nogc` ` safe`/` system` inference disabled } ``` ```d default nogc safe { void f() { … } // ` nogc safe` by `default nogc safe` block void g(T)() { … } // ` gc`/` nogc` ` safe`/` system` inference enabled } ``` The `default …` block sets defaults. We can easily define `default:` and `default{}` to mean `default system throw gc impure` (or the module default, see below), but without an `impure` keyword, in a ` safe pure:` context, one would have to do: ```d default safe pure: … default // idea: `default impure`, but is actually `default impure system`, therefore ... { default safe: // ... set ` safe` as default again … } ``` to apply impure as the default. That is annoying because expressing a simple idea becomes hard. A programming language is a language to express ideas human-to-human and incidentally human-to-machine. Applying `default` to a declaration directly goes against the whole idea of what a default setting is. I also see a difference between specifying default attributes for a module versus what’s formally a part of a module (even if it happens to span the whole module). E.g. ```d default safe module m; ``` would differ from ```d module m; default safe: ``` by how function pointer and delegate types are interpreted: ```d module m; safe: // same as `default safe:` in this example void f(void function() callback) { } ``` makes `typeof(&f)` be `void function(void function() system) safe`, whereas ```d default safe module m; void f(void function() callback) { } ``` makes `typeof(&f)` be `void function(void function() safe) safe`. The type of the function parameter is ` safe`/` system` based on the module’s default and nothing else. I suspect that making any attribute the default, higher-order functions will be a big hurdle because no matter if a the new language-level default affects parameters of function pointer / delegate types or not, things break. However, for an individual code base, changing the default for a module in this way can make sense and happen to be without issues. Making ` safe` the language default *requires* something like [ADAs](https://github.com/Geod24/DIPs/blob/adas/DIPs/DIP4242.md), but allowing for module-specified defaults is orthogonal.
Jun 25
parent Walter Bright <newshound2 digitalmars.com> writes:
Most of your post was about  safe/ trusted/ system. I had neglected to mention 
that  default wouldn't apply to that, as there is no purpose to it for those 
attributes.

 default would only apply to nothrow, pure,  nogc. It would not override
inference.

For example,

 nogc  default = as if  nogc never happened

 default = no effect

 default  nogc =  nogc

and so on.

This addresses your issues.
Aug 18
prev sibling next sibling parent IchorDev <zxinsworld gmail.com> writes:
On Friday, 14 June 2024 at 16:20:02 UTC, Quirin Schroll wrote:
 Permalink: 
 https://github.com/Bolpat/DIPs/blob/8a26c2545b0a6926d799e9d8dc8c3662e58d516b/DIPs/DIP-4NNN-QFS.md

 ---

 **Abstract:** Add ` gc` as a new function attribute that acts 
 as the inverse of the ` nogc` attribute.
Excited to see that this got merged.
Aug 11
prev sibling parent Mike Parker <aldacron gmail.com> writes:
This DIP has been submitted for Formal Assessment as DIP 1047:

https://forum.dlang.org/post/ycvbiosyhqfljxaspbqj forum.dlang.org

Please consider this thread closed.  Further posts will be 
deleted. Thanks!
Aug 17