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