cast(function qualifier)
Quirin Schroll
qs.il.paperinik at gmail.com
Wed Feb 5 11:22:59 UTC 2025
On Monday, 3 February 2025 at 18:38:51 UTC, Atila Neves wrote:
> https://forum.dlang.org/post/v0urjh$58i$1@digitalmars.com
>
> On Thursday, 2 May 2024 at 01:51:45 UTC, Timon Gehr wrote:
>> The status quo is that it is annoying to type-pun function
>> pointers to stronger function attributes as the entire type
>> has to be specified:
>>
>> ```d
>> (cast(int function(int)pure)&f)(2);
>> ```
>>
>> This is also error prone as the return type and/or argument
>> types could go out of sync with the actual type of `f`.
>>
>>
>> `cast` could simply allow a list of function attributes and
>> cast a function pointer or delegate to a type that
>> additionally has those attributes:
>>
>> ```d
>> (cast(pure)&f)(2);
>> ```
>>
>> This simple syntactic sugar would make it a bit easier to work
>> with attributes in `@system`/`@trusted` code. Of course,
>> safety checks would still be performed, as for the more
>> explicit cast syntax.
>
> This looks nice.
I addressed [this
enhancement](https://github.com/dlang/dmd/issues/19596) with that.
I generally dislike the qualifier casts because they override all
existing qualifiers.
* `cast(qualifiers)` removes all qualifiers, then adds the given
qualifiers (includes `cast()`).
It’s a blunt tool that makes making precise cuts hard. You locked
a mutex and and now are good to go with casting away `shared`?
Well, too bad, you did `cast()` and also removed a `const`,
welcome to UB town. You made sure some C API doesn’t mutate your
stuff and cast away `const`? Well, too bad, you also cast away
`shared` and now you’re debugging race conditions.
My idea is to use `...` to abbreviate the type of the operand
within the `cast`; that would make `cast(...)` a no-op.
Qualifier manipulations go in front of `...` and (member)
function attribute manipulations trail behind. `cast(const ...
const) dg` adds(!) `const` both as a qualifier and a member
function attribute to the type of `dg`.
Before a single qualifier or attribute, there can be a `-` or
`!`. Both remove the qualifier or attribute, but the `-` is a
compile-error if the qualifier or attribute is not present,
whereas `!` removes if it is present, essentially just ensuring a
qualifier or attribute isn’t present in the result.
IMO, there should be:
* `cast()` removes all qualifiers.
* `cast(!qualifier ...)` removes the given qualifier (only one)
* `cast(qualifiers ...)` adds the given qualifiers (at least one
must be given)
* `cast(... !attribute)` removes the given (member) function
attribute from a function / delegate type
* `cast(... attributes)` adds the given (member) function
attributes to a function / delegate type
```d
shared inout void delegate() @safe const dg;
cast() dg; // void delegate() const @safe
cast(!shared ...) dg; // inout void delegate() const @safe
cast(-shared ...) dg; // inout void delegate() const @safe
cast(-const ...) dg; // error, `dg` isn’t const
cast(const ...) dg; // const inout shared void delegate() const
@safe
cast(... !const) dg; // inout shared void delegate() @safe
cast(... !@safe) dg; // inout shared void delegate() const
cast(... !pure) dg; // inout shared void delegate() const @safe
cast(... -pure) dg; // error, `dg` isn’t pure
cast(... pure nothrow) dg; // const inout shared void delegate()
const nothrow pure @safe
```
More information about the dip.ideas
mailing list