Dotty: Implicit conversions taking by-name and by-value args are now ambiguous

Created on 21 Jan 2020  路  4Comments  路  Source: lampepfl/dotty

minimized code

import scala.language.implicitConversions

class Ops1 {
  def foo: String = "1"
}

class Ops2 {
  def foo: String = "2"
}

object Ops {
  implicit def toOps1(value: => String): Ops1 = new Ops1
  implicit def toOps2(value: String): Ops2 = new Ops2
}

object ExtensionTest {
  import Ops._

  val res = "".foo
}


Compilation output

-- [E007] Type Mismatch Error: ExtensionTest.scala:19:12 -----------------------
19 |  val res = "".foo
   |            ^^
   |Found:    ("" : String)
   |Required: ?{ foo: ? }
   |Note that implicit extension methods cannot be applied because they are ambiguous;
   |both method toOps1 in object Ops and method toOps2 in object Ops provide an extension method `foo` on ("" : String)
1 error found

expectation

This code compiles on Scala 2 (the by-value conversion is chosen). I ran into this issue in ScalaCheck, where importing org.scalacheck.Prop._ causes problems on Dotty:

1 |true :| "foo"
  |^^^^^^^
  |value :is not a member of Boolean, but could be made available as an extension method.
  |
  |One of the following imports might fix the problem:
  |
  |  import org.scalacheck.Prop.BooleanOperators
  |  import org.scalacheck.Prop.propBoolean
  |  import org.scalacheck.Gen.const
  |         

This should generally be easy to work around in this particular case, since there's not any good reason to import Prop._ wholesale (and also BooleanOperators is now deprecated), but that's what sbt-doctest does at the moment (I'm opening a PR there now).

I thought there was a slight chance this might be related to #8035, but compiling with #8046 gives the same error.

wontfix

All 4 comments

That one is known and intentional. See https://dotty.epfl.ch/docs/reference/changed-features/implicit-resolution.html point 6. I think the fix would have to be in the libraries.

Note that I fixed scalacheck upstream to remove the ambiguity, but there's no release of scalacheck with the fix yet.

Should the doc expand on why the behaviour was dropped? Optionally, why it was like that in the first place in Scala 2?

If someone can drop the reason here I can pipe it into a PR.

I think it's just that there was no good reason for A to be considered more specific than => A.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

odersky picture odersky  路  3Comments

ohze picture ohze  路  3Comments

adamgfraser picture adamgfraser  路  3Comments

mcku picture mcku  路  3Comments

Blaisorblade picture Blaisorblade  路  3Comments