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:
(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:
(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 with that.
I generally dislike the qualifier casts because they override all existing qualifiers.
cast(qualifiers)
removes all qualifiers, then adds the given qualifiers (includescast()
).
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 typecast(... attributes)
adds the given (member) function attributes to a function / delegate type
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