Uncallable delegates
Timon Gehr
timon.gehr at gmx.ch
Wed Jun 17 10:16:45 UTC 2026
On 6/16/26 23:18, Walter Bright wrote:
> On 5/16/2026 12:20 AM, Timon Gehr wrote:
>> The best I can do right now is show you that the delegate type
>> checking is different from classes:
>>
>> ```d
>> @safe:
>> struct T{
>> int* delegate() dg;
>> int* q;
>> }
>> T foo(){
>> auto x = new int(2);
>> auto dg = ()=>x;
>> return T(dg,x);
>> }
>> void main(){
>> const ps = foo();
>> static assert(is(typeof(ps.dg)==const));
>> auto p = ps.dg();
>> static assert(is(typeof(p)==int*)); // `const` removed
>> }
>> ```
>
> Instrumenting the example:
>
> ```d
> @safe:
> struct T{
> int* delegate() dg;
> int* q;
> }
> T foo(){
> auto x = new int(2);
> auto dg = ()=>x;
> return T(dg,x);
> }
> void main(){
> const ps = foo();
> pragma(msg, typeof(foo())); // T
> pragma(msg, typeof(ps)); // const(T)
> pragma(msg, typeof(ps.dg)); // const(int* delegate() @safe)
> DING DING
> pragma(msg, typeof(ps.dg())); // int*
> pragma(msg, typeof(ps.q)); // const(int*)
> }
> ```
> DING DING here's what's happening. The `const` is not turning the return
> type of the delegate into `const`. There is no way for the type system
> to look at a delegate type and determine if a const should be applied to
> the return value or not, because the type system does not have access to
> the delegate implementation.
>
> I don't know how this might be resolved other than disallowing `const`
> being applied to a delegate, which seems rather drastic.
Applying `const` to a delegate is fine. Calling a delegate that may
require a mutable context with a `const` context is not. You can't pass
a `const` argument with indirections to a mutable parameter. Except that
for delegates, this is currently not enforced. Dukc's DIP fundamentally
just proposes consistently enforcing this basic rule.
However, the call type checking and implicit conversion rules also
should take into account that we know that the context had the correct
type and qualifier when the delegate was initially created. Without this
observation, it would be consistent to reject _all_ delegate calls.
More information about the dip.development
mailing list