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:
@nogc @safe
{
void f() { … } // `@nogc @safe` by `@safe` `@nogc` block
void g(T)() { … } // `@gc`/`@nogc` `@safe`/`@system` inference disabled
}
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:
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.
default @safe
module m;
would differ from
module m;
default @safe:
by how function pointer and delegate types are interpreted:
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
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, but allowing for module-specified defaults is orthogonal.