Steven Schveighoffer <> changed:

           What    |Removed                     |Added
             Status|RESOLVED                    |REOPENED
                 CC|                            |
             Blocks|2267                        |
         Resolution|INVALID                     |
           Severity|normal                      |enhancement

--- Comment #9 from Steven Schveighoffer <>  2009-07-08 
10:36:32 PDT ---
I'll chime in a bit on this.

What the original poster is looking for is not all-encompasing contravariance,
it's a specific case.  He is saying that a delegate that takes a const type is
a subtype of the delegate that takes a mutable (or immutable) version of that
type, similar to how mutable and immutable are "subtypes" of const.

Similarly, it should be possible to implicitly convert a delegate that takes an
object to a delegate that takes, for instance, a Stream, since Stream is
implicitly convertable to object, and can viably be passed to that function.

(In reply to comment #4)
> The actual rule for matching a delegate against a type is that the delegate is
> covariant with the type. The return type is checked for covariance, and things
> like a pure function is considered covariant with an impure one. This works
> exactly the same as overriding a virtual function with a covariant one.

You're missing the issue here, a delegate today is not variant at all, you
can't implicitly cast a delegate to another type in any case that I know of.

> What you're asking for with the const parameters is contravariance.
> Contravariant parameters are a good idea until overloading is considered.

how do you overload delegates?  As far as I know, a delegate is a pointer to a
single overload, not an overload group (though the latter would sometimes be

> If
> you have two functions, one with a const parameter and the other mutable, 
> which
> one overrides the base virtual function? You could say overriding is based on 
> a
> 'best match', but things are complex enough without throwing that into the 
> mix.

Yes, contravariance in other cases makes things difficult unless you specify
the direction of the variance.  For example in C#4, you can do contravariance
and covariance with generics (check out bearophile's example:

But in delegates, we are talking about casting a concretely defined type. 
Implicit casting to what should be valid should be allowed.

In fact, I don't even think this works today:

class C{
void foo(string s);
void foo(const(char)[] s);

C c = new c;
void delegate(const(char)[]) foo2 = &; // error, didn't select the right

// or it's the other way around, can't remember

Similarly, implicit covariant delegates should also be allowed.  That is,

class C {
C foo();

C c = new C;
object delegate() foo2 = &;

(In reply to comment #1)
> Is it tango2 blocker? There is a tracker for tango2 blockers - bug 2267.

Not that I'm aware of, I removed it as a blocker.

Configure issuemail:
------- You are receiving this mail because: -------

Reply via email to