Uncallable delegates
Dukc
ajieskola at gmail.com
Sat May 16 17:09:59 UTC 2026
On Saturday, 16 May 2026 at 02:05:17 UTC, Walter Bright wrote:
>
> The overriding of class functions must behave the same as
> implicit conversions on delegates.
Okay, time to analyse this view.
I'm assuming you mean that if you assign one delegate to another,
the this pointer should be type checked the same way as visible
parameter. In other words, the rhs delegate this pointer would be
compatible with all values the lhs side is. This is how it works
now.
It certainly is important to check the delegate can actually
accept it's context pointer, but it is *already done when the
delegate is created*. For example, if you're creating a `void
delegate(int) immutable`, you do it by taking address of a member
function that has an `immutable` this pointer. The compiler will
refuse this if the object you use to do it isn't `immutable`.
This means that all delegates, when they are created (excluding
type system bypassing tricks), can safely accept their own
context, no matter how the context parameter is qualified. We can
thus safely assign `void delegate(int) immutable` to `void
delegate(int) const`, `void delegate(int)` or even `void
delegate(int) shared`. The DIP has a simple rule for context
parameter qualifiers when converting types: can always be removed
but never added (`@safe`ly). `immutable` counts as `immutable
inout const shared`.
So, the delegate context parameter qualifier is not needed to
check the delegate will accept it's own context object when the
delegate is in it's plain mutable unshared form. This is always
the case. However, if the delegate is qualified somehow after
it's creation, we still need to make sure the function it points
to is still compatible with that before calling it. This is where
the context parameter qualification is useful. If the context
parameter is `immutable`, it is compatible with any qualification
of the delegate. This is because an `immutable` context parameter
means the object must also be immutable, and immutable objects
are safe in both shared and read-only contextes.
A `const` context parameter is also compatible with all
qualifications. While the function behind the such a delegate
might be `immutable` - which wouldn't support a mutable object -
this can only be the case if the object is also immutable.
`shared(void delegate(int) const)` might appear dangerous to call
at first, but the DIP actually allows it. It is safe, because the
DIP disallows converting `void delegate(int) const` one could
obtain from a thread-local object to `shared(void delegate(int)
const)`. Instead, it must originate from either `void
delegate(int) immutable` or `void delegate(int) shared const`,
and therefore the the object at time of delegate creation is also
`immutable` or some variant of `shared`.
More information about the dip.development
mailing list