Trying to use Mir ion, its a perfect example of the failure of D's attribute system
Quirin Schroll
qs.il.paperinik at gmail.com
Fri Jan 20 13:08:46 UTC 2023
On Friday, 20 January 2023 at 05:48:26 UTC, Steven Schveighoffer
wrote:
> On 1/19/23 10:38 PM, Walter Bright wrote:
>> On 1/19/2023 6:18 PM, Adam D Ruppe wrote:
>>> Ideally, you'd be able to say `process` inherits the
>>> nogc-ness of `userData`.
>>
>> That's exactly what template attribute inference does.
>>
> […]
>
> What we want is the effective attributes of the function to be
> the most restrictive possible of both the code inside the
> function, and the argument to the function.
>
> The compiler would need a way to specify this for non-inferred
> functions, but it could be inferred for templates and auto
> functions.
I wrote a DIP (_Attributes for Higher-Order Functions,_ AfHOF)
for that, but didn’t make it. I tried to be pragmatic and squeeze
it into the current syntax via doubling-down on a bug in the type
system (i.e. making it a ‘feature’). Timon Gehr made me aware of
the bug. Writing the DIP made me aware that higher-order
functions are a blocker for making e.g. `@safe` the default: If
you have `void f(void delegate() dg)`, there is no consistent way
to add `@safe` to `f` and/or `dg` that won’t break properly
annotated `@system` code.
Mathias Lang has a work-in-progress DIP called _Argument
dependent attributes_ (AdA). It introduces syntax to specify that
the attributes of higher-order function (i.e. a function with
callbacks) depend on the attributes of the callback arguments.
It’s a half-way solution that only targets parameters of delegate
or function pointer type. A full solution would include
parameters of composed types that include delegate or function
pointer types somewhere: Slices of delegate or function pointer
type could be considered reasonably common. Attribute variables
would do that.
* D has runtime value variables, e.g. your good old `x` in `int
x;`.
* D has type variables, e.g. you good old `T` in `template
t(T){..}`
* D has symbol variables, e.g. template `alias` parameters.
* D has 1 type constructor variable: `inout`. (D were more
consistent if it allowed for two or more independent type
constructor variables, but that’s rarely needed practically.)
* D has no attribute variables.
If D added 1 fixed-name attribute variable per attribute (cf.
`inout`), they could be spelled `@safety`, `purity`, `@gcness`,
and `throwiness`.
```d
void callInSequence(
void delegate() @safety purity @gcness throwiness[] dgs
) @safety purity @gcness throwiness
{
foreach (dg; dgs) dg();
}
```
When called, the argument is a slice of delegates that are
`@safe` or `@system` – `@safety` is replaced by that; that are
`pure` or not – purity is replaced by that; that are `@nogc` or
not – `@gcness` is replaced by that; that may throw or not –
`throwiness` by `throw` or `nothrow`.
This works the same way as when `inout(int)[] f() inout` is
called on a mutable, `const` or `immutable` object, its return
type will be `int[]`, `const(int)[]`, or `immutable(int)[]` after
replacing `inout` with the call-side type constructor applied to
the object’s type.
More information about the Digitalmars-d
mailing list