Skip to content

Implicit nesting rules breaks usage of some existing libraries #7069

Open
@smarter

Description

@smarter

Given:

trait HasApply {
  def apply(a: Int, b: String): Int = a
}
object HasApply {
  implicit def foo[T](x: T): HasApply = ???
}

import HasApply._

object Test {
  val str = "abc"
  str.apply(0)
}

Dotty by default will complain:

-- Error: try/impany.scala:12:5 ------------------------------------------------
12 |  str(0)
   |  ^^^^^^
   |missing argument for parameter b of method apply: (a: Int, b: String): Int

On the other hand, if we run with -language:Scala2, then Dotty will find Predef.augmentString, like Scala 2 does, because of this check: https://github.com/lampepfl/dotty/blob/1f22a403680094659f4013811b971e74b1b32160/compiler/src/dotty/tools/dotc/typer/Implicits.scala#L270

It would be nicer if we were able to select the correct implicit conversion without using the Scala 2 mode, e.g. because the type of the argument of augmentString is more precise than the type of the argument of foo, or because the apply method we want to call only takes one parameter of type Int which does not match the signature of HasApply#apply. Otherwise, some Scala 2 libraries which (ab)use implicit conversions become hard to use from Dotty because of definitions such as:

https://github.com/typelevel/scalacheck/blob/3fc537dde9d8fdf951503a8d8b027a568d52d055/src/main/scala/org/scalacheck/util/Pretty.scala#L109

https://github.com/typelevel/scalacheck/blob/3fc537dde9d8fdf951503a8d8b027a568d52d055/src/main/scala/org/scalacheck/Gen.scala#L431-L432

Simply removing these implicit conversions is usually not an option, because it would likely break a lot of code that relies on it, with no easy migration strategy.

WDYT @odersky ?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions