Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Contravariance mucks with implicit resolution #2509

Closed
scabug opened this issue Oct 22, 2009 · 11 comments · Fixed by scala/scala#6037
Closed

Contravariance mucks with implicit resolution #2509

scabug opened this issue Oct 22, 2009 · 11 comments · Fixed by scala/scala#6037
Assignees
Milestone

Comments

@scabug
Copy link

scabug commented Oct 22, 2009

A condition under which the most-specific implicit is not being selected:

// Test.scala
class A
class B extends A

trait Y {
  def value: String
} 

trait X[-T] { // if I make X invariant, this works
  def y(t: T): Y
}

object XA extends X[A] {
  def y(a: A) = new Y { def value = a.getClass + ": AValue" }
}

object XB extends X[B] {
  def y(b: B) = new Y { def value = b.getClass + ": BValue" }
}

object Test {
  implicit def f[T](t: T)(implicit x: X[T]): Y = x.y(t)
  implicit val xa: X[A] = XA
  implicit val xb: X[B] = XB

  def main(argv: Array[String]) {
    val a = new A
    val b = new B
    println("A: " + a.value)
    println("B: " + b.value)
  }
}

gives:

$$ scala Test
A: class A: AValue
B: class B: AValue

Making X invariant in T gives a correct result, but of course is much less flexible.

@scabug
Copy link
Author

scabug commented Oct 22, 2009

Imported From: https://issues.scala-lang.org/browse/SI-2509?orig=1
Reporter: Kris Nuttycombe (nuttycom)

@scabug
Copy link
Author

scabug commented Oct 27, 2009

@adriaanm said:
this is due to a known limitation of our type inference algorithm (contravariant type params are problematic wrt inference)

@scabug
Copy link
Author

scabug commented Nov 18, 2009

@adriaanm said:
Actually, what I said is a little imprecise:

type inference&implicit search yields:

    println("A: " + f[A](a)(xa).value)
    println("B: " + f[B](b)(xa).value)

but that's what's expected because xa is the value with the most specific type: X[A], as X[A] <: X[B] (since B <: A and X is contravariant in its first type argument)

@scabug
Copy link
Author

scabug commented Nov 18, 2009

Kris Nuttycombe (nuttycom) said:
What I find surprising about this is that specificity is conflated with the direction of the variance. At least to my mind, variance is associated with substitutability, whereas specificity is a unidirectional relation in the direction of covariance.

The concepts aren't totally orthogonal; it's more like there should be a distinction between subclassing (where subclasses are always more specific) and subtyping, where an instance of a subtype is always substitutable for an instance of the supertype.

@scabug
Copy link
Author

scabug commented Sep 4, 2012

@paulp said:
Noting for any future database searchers that as far as I'm concerned I fixed this.

Discussion: https://groups.google.com/forum/#!topic/scala-language/ZE83TvSWpT4

Implementation: https://github.com/paulp/scala/tree/topic/contrarivariance

@scabug
Copy link
Author

scabug commented May 29, 2016

@milessabin said (edited on May 29, 2016 7:56:40 AM UTC):
In the light of this Dotty commit I think we should un-Won't Fix this ticket and deal with it here too.

@scabug
Copy link
Author

scabug commented May 29, 2016

@dwijnand said:
(here's the commit SHA that eventually made it into lampepfl/dotty: scala/scala3@8954026)

@scabug
Copy link
Author

scabug commented May 29, 2016

@soc said:
Agree. Would be nice to get this into 2.12 as a flag to allow all the "base" libraries to play with it. Without it this would delay even thinking about integrating some fundamental typeclasses into the std lib for years.

@scabug
Copy link
Author

scabug commented May 30, 2016

Tongfei Chen (ctongfei) said:
I'd very much like to see this fixed in 2.12. Spire/Cats/Scalaz/... are in desperate need of this :-)

@scabug
Copy link
Author

scabug commented May 30, 2016

Guillaume Martres (Smarter) said (edited on May 30, 2016 4:03:19 PM UTC):
For reference, scala/scala3#1246 (comment) documents the sort of issues with existing implicits that might pop up if you change that rule, and how to fix them.

@scabug scabug added this to the Backlog milestone Apr 7, 2017
@milessabin milessabin modified the milestones: Backlog, 2.13.0-M4 Mar 2, 2018
milessabin added a commit to milessabin/scala that referenced this issue Mar 6, 2018
This is a backport of the following Dotty change to scalac,

scala/scala3@8954026

As in the Dotty implementation the specificity comparison which is used
for overload resolution and implicit selection is now performed as-if
all contravariant positions in top level type constructors were
covariant.

Currently this breaks test/files/run/t2030.scala in exactly the same way
as in Dotty as reported here,

scala/scala3#1246 (comment)

and in this PR it has been changed to a neg test. However,
test/files/run/t2030.scala passes when this PR is combined with,

scala#6139

so if/when that is merged it can be switched back to a pos test.

Fixes scala/bug#2509. Fixes scala/bug#7768.
milessabin added a commit to milessabin/scala that referenced this issue Mar 22, 2018
This is a backport of the following Dotty change to scalac,

scala/scala3@8954026

As in the Dotty implementation the specificity comparison which is used
for overload resolution and implicit selection is now performed as-if
all contravariant positions in top level type constructors were
covariant.

Currently this breaks test/files/run/t2030.scala in exactly the same way
as in Dotty as reported here,

scala/scala3#1246 (comment)

and in this PR it has been changed to a neg test. However,
test/files/run/t2030.scala passes when this PR is combined with,

scala#6139

so if/when that is merged it can be switched back to a pos test.

Fixes scala/bug#2509. Fixes scala/bug#7768.
milessabin added a commit to milessabin/scala that referenced this issue Mar 29, 2018
This is a backport of the following Dotty change to scalac,

scala/scala3@8954026

As in the Dotty implementation the specificity comparison which is used
for overload resolution and implicit selection is now performed as-if
all contravariant positions in top level type constructors were
covariant.

Currently this breaks test/files/run/t2030.scala in exactly the same way
as in Dotty as reported here,

scala/scala3#1246 (comment)

and in this PR it has been changed to a neg test. However,
test/files/run/t2030.scala passes when this PR is combined with,

scala#6139

so if/when that is merged it can be switched back to a pos test.

Fixes scala/bug#2509. Fixes scala/bug#7768.
@lrytz
Copy link
Member

lrytz commented Apr 19, 2018

scala/scala#6037

@SethTisue SethTisue modified the milestones: 2.13.0-M4, 2.13.0-M5 May 14, 2018
milessabin added a commit to milessabin/scala that referenced this issue Jul 26, 2018
This is a backport of the following Dotty change to scalac,

scala/scala3@8954026

As in the Dotty implementation the specificity comparison which is used
for overload resolution and implicit selection is now performed as-if
all contravariant positions in top level type constructors were
covariant.

Currently this breaks test/files/run/t2030.scala in exactly the same way
as in Dotty as reported here,

scala/scala3#1246 (comment)

and in this PR it has been changed to a neg test. However,
test/files/run/t2030.scala passes when this PR is combined with,

scala#6139

so if/when that is merged it can be switched back to a pos test.

Fixes scala/bug#2509. Fixes scala/bug#7768.
milessabin added a commit to milessabin/scala that referenced this issue Jul 26, 2018
This is a backport of the following Dotty change to scalac,

scala/scala3@8954026

As in the Dotty implementation the specificity comparison which is used
for overload resolution and implicit selection is now performed as-if
all contravariant positions in type constructors were covariant.

Currently this breaks test/files/run/t2030.scala in exactly the same way
as in Dotty as reported here,

scala/scala3#1246 (comment)

and in this PR it has been changed to a neg test. However,
test/files/run/t2030.scala passes when this PR is combined with,

scala#6139

so if/when that is merged it can be switched back to a pos test.

Fixes scala/bug#2509. Fixes scala/bug#7768.
milessabin added a commit to milessabin/scala that referenced this issue Aug 6, 2018
This is a backport of the following Dotty change to scalac,

scala/scala3@8954026

As in the Dotty implementation the specificity comparison which is used
for overload resolution and implicit selection is now performed as-if
all contravariant positions in type constructors were covariant.

Fixes scala/bug#2509. Fixes scala/bug#7768.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants