Uncallable delegates

Walter Bright newshound2 at digitalmars.com
Tue May 12 23:18:30 UTC 2026


I think of the issue completely differently. Allow me to try again, starting 
with something simpler, like function pointers:

```
pure int f();
int g();

void test()
{
     auto dgf = &f;
     auto dgg = &g;

     dgg = dgf; // works
     dgf = dgg; // error, cannot convert
}
```
This shows that we cannot add function attributes, in this case adding `pure`. 
The same applies to every other function attribute. This is not a design 
decision, it's an inevitable deriviation from the other rules of the language.

Another case:
```
const(int)* f();
int* g();

void test()
{
     auto dgf = &f;
     auto dgg = &g;

     dgg = dgf; // error, cannot convert
     dgf = dgg; // works
}
```
This is an example of contra-variance.
```
void f(const(int)*);
void g(int*);

void test()
{
     auto dgf = &f;
     auto dgg = &g;

     dgg = dgf; // works
     dgf = dgg; // error, cannot convert
}
```
and that's an example of covariance.

Let's extend the notion to inheritance in a class:

```
class A
{
     void f();
     pure void g();
}

class B : A
{
     override pure void f();
     override void g();
}
```
Unfortunately, this compiles without error. Impure function B.g cannot override 
pure A.g. Maybe this is a cause of one of the problems you've discovered.
https://github.com/dlang/dmd/issues/23125

Moving on to covariance:
```
class A
{
     void f(int*);
     void g(const(int)*);
}

class B : A
{
     override void f(const(int)*); // compiles correctly
     override void g(int*); // errors correctly
}
```
and contravariance:
```
class A
{
     int* f();
     const(int)* g();
}

class B : A
{
     override const(int)* f(); // errors correctly
     override int* g(); // compiles correctly
}
```
What this has to do with delegates is straightforward:
```
class A
{
     const(int)* f();
}

class B : A
{
     override int* f();
}

void foo()
{
     A a;
     B b;
     auto dga = &a.f;
     auto dgb = &b.f;
     dga = dgb;
}
```
In other words, the behavior of delegate assignments behaves exactly like how an 
overriding function behaves in a class hierarchy. If the behaviors diverge, then 
there is a bug in the language implementation.

Delegates are not some unique construct with their own semantics. They are 
constrained by co- and contra- variance eggzactly like function pointers and 
class inheritance. Intuition has nothing to do with it.


More information about the dip.development mailing list