Delegate contravariance

Jason House jason.james.house at gmail.com
Mon Jan 19 10:36:02 PST 2009


Silvio Ricardo Cordeiro wrote:

> Is there any good reason why the following code doesn't work?
> The function "foo" requires as its argument a delegate that
> receives a B. This means that, because of the type soundness
> of the D language, the delegate will only be called with instances
> of B. Now, why can't it be "abc", then? The "abc" delegate just
> happens to handle more than it is required...
> 
> 
> class A { }
> class B : A { }
> void foo(void delegate(B b) dg) {}
> 
> auto abc = (A a) { }
> auto qwe = (B b) { }
> 
> void main() {
> foo(abc); // this line won't compile
> foo(qwe);
> }
> 
> 
> BTW: Same thing happens for const(B). B "sort of" a derivative
> of const(B), so it would make sense. Every possible argument that can
> be passed to a delegate(B) can also be passed to a delegate(A) or
> delegate(const(B)). Why the restriction, then? Am I missing something?

Your code above is wrong, but you are right about a bug in dmd.  

Your code sample should not compile because of two issues:
1. You're missing semicolons on the declarations of abc and qwe.
2.  foo(abc) is implicitly requires casting A's to B's which is not guaranteed to be correct.  

Here is code that should compile but doesn't

class A{}
class B:A{}
void foo(void delegate(A a) dg){}

auto abc = (A a){};
auto qwe = (B b){};

void main(){
  foo(abc);
  foo(qwe);
}

test.d(10): function test.foo (void delegate(A a) dg) does not match parameter types (void delegate(B b))
test.d(10): Error: cannot implicitly convert expression (qwe) of type void delegate(B b) to void delegate(A a)




More information about the Digitalmars-d-learn mailing list