Thread overview
[Issue 3075] Implement parameter contravariance
May 09, 2017
Walter Bright
May 09, 2017
Walter Bright
May 09, 2017
Walter Bright
Sep 27, 2019
RazvanN
Jan 09
Bolpat
Jan 09
Bolpat
June 09, 2015
https://issues.dlang.org/show_bug.cgi?id=3075

Andrei Alexandrescu <andrei@erdani.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
            Version|2.028                       |D2

--
May 09, 2017
https://issues.dlang.org/show_bug.cgi?id=3075

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=16303

--
May 09, 2017
https://issues.dlang.org/show_bug.cgi?id=3075

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           See Also|                            |https://issues.dlang.org/sh
                   |                            |ow_bug.cgi?id=17349

--
May 09, 2017
https://issues.dlang.org/show_bug.cgi?id=3075

Walter Bright <bugzilla@digitalmars.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|RESOLVED                    |REOPENED
         Resolution|INVALID                     |---

--- Comment #28 from Walter Bright <bugzilla@digitalmars.com> ---
Reopened because contravariance really should work.

--
September 27, 2019
https://issues.dlang.org/show_bug.cgi?id=3075

RazvanN <razvan.nitu1305@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |razvan.nitu1305@gmail.com

--- Comment #29 from RazvanN <razvan.nitu1305@gmail.com> ---
(In reply to Walter Bright from comment #2)
> A test case:
> 
> void foo(void delegate(void[]) dg);
> 
> void test()
> {
>     void func(const(void)[] t)
>     {
>     }
> 
>     foo(&func);
> }

This test case compiles today. Is this issue fixed?

--
January 09
https://issues.dlang.org/show_bug.cgi?id=3075

Bolpat <qs.il.paperinik@gmail.com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |qs.il.paperinik@gmail.com

--- Comment #30 from Bolpat <qs.il.paperinik@gmail.com> ---
Overriding with contravariant parameter types can work.
Because D has overloading and contravariant overriding is factually
indistinguishable from overloading, an annotation must be used to clarify:

It could be as simple as giving override an optional type list that signifies the types of the parameters of the method to be overridden:

Attribute:
    ...
    override
+   override Parameters

class X {}
class Y : X {}

class C
{
  void foo(Y y) {}
}

class D : C
{
  override(Y) void foo(X x) {} // overrides foo(Y y)
}

It's similar to the VisibilityAttribute package with a QualifiedIdentifier to signify the exact package it should be visible from. It's very specific and one could argue that overloading and forwarding solves the issue in almost all cases.

class D : C
{
  override void foo(Y y) { foo(cast(X) y); }
  void foo(X x) { ... }
}

There might be very specific circumstances where this is not a viable option.

--
January 09
https://issues.dlang.org/show_bug.cgi?id=3075

--- Comment #31 from Bolpat <qs.il.paperinik@gmail.com> ---
In the context of Argument-dependent Attributes (ADA) or Attributes for Higher-Order Functions (AfHOF) (pending DIPs), contravariant overloading is necessary. Imagine a proper sink-toString interface. The whole reason to have a sink in the first place instead of returning an allocated string is not doing the allocation.

So, considering

  interface SinkToString
  {
      void toString(scope void delegate(char) @nogc) @nogc;
  }

the following override should work in some way:

  class C : SinkToString
  {
      override(scope void delegate(char) @nogc)
      void toString(in void delegate(char) sink) @nogc const
      { ... }
  }

The intention of the interface is: toString is @nogc and may require a @nogc
delegate for this.
An implementation of it may not require a @nogc delegate in its internal logic,
but by the reasoning explained in AfHOF, calling C.toString with a @nogc
argument will result in a @nogc execution. ADA is similar (as far as I can
tell): one would replace the @nogc of C.toString by @nogc(*).

--