scala / bug

Scala 2 bug reports only. Please, no questions — proper bug reports only.
https://scala-lang.org
230 stars 21 forks source link

Implicit conversion does not trigger for private extension methods in the body of the owning class #12802

Open noresttherein opened 1 year ago

noresttherein commented 1 year ago

Reproduction steps

Scala version: 2.13.10

    implicit class Extension(private val self :Int) {
        private def squared :Int = self * self
        def avg(other :Int) :Int = math.sqrt(squared * other.squared).toInt
    }

Problem

value squared is not a member of Int
        def avg(other :Int) :Int = math.sqrt(squared * other.squared).toInt

Would be nice if implicit conversions triggered for all methods accessible in a given scope.

SethTisue commented 1 year ago

"fixed in Scala 3" in the sense that the compiler accepts the extension equivalent:

extension (self: Int)
  def squared: Int = self * self
  def avg(other: Int): Int = math.sqrt(squared * other.squared).toInt
som-snytt commented 1 year ago

Note that it is explicit for extensions. If it could be made to work for implicit class, it would require a spec.

SethTisue commented 1 year ago

perhaps it's sort of obvious, but for the record, in Scala 2 the workaround is to write out the call to the conversion yourself, so

def avg(other: Int): Int =
  math.sqrt(squared * Extension(other).squared).toInt
lrytz commented 1 year ago

Is the behavior according to the spec? Should the spec be clarified? Scala 3 does the same, it doesn't infer a view if the desired member is private. Changing this might have a bad impact on compiler performance.

https://www.scala-lang.org/files/archive/spec/2.13/07-implicits.html#views

som-snytt commented 7 months ago

I missed lrytz's previous point. The spec doesn't say that the member provided by the implicit must be accessible. (If two competing conversions offer a public and a private member respectively, the public is chosen and the private ignore, instead of ambiguity.)