bug icon indicating copy to clipboard operation
bug copied to clipboard

StackOverflowError when using implicit class compiled with Scala 3 in Scala 2

Open jadenPete opened this issue 6 months ago • 1 comments

Reproduction steps

Scala 2 version: 2.13.16 Scala 3 version: 3.6.3

Please let me know if scala/scala3 is a better place to post this.

  1. Compile the following with Scala 3:
package foo

package object bar {
  implicit class EnrichedNumberOption(private val number: Option[Int]) {
    def +(other: Option[Int]): Option[Int] = number.flatMap(number => other.map(number + _))
  }
}
  1. Compile the following with Scala 2:
package foo.bar

object Main {
  None + None
}
  1. Observe the following exception:
java.lang.StackOverflowError
scala.reflect.internal.Symbols$Symbol.isTopLevel(Symbols.scala:1048)
scala.reflect.internal.Symbols$ClassSymbol.associatedFile(Symbols.scala:3442)
scala.reflect.internal.Symbols$Symbol.isCoDefinedWith(Symbols.scala:2346)
scala.reflect.internal.Symbols$Symbol.$anonfun$companionClass$1(Symbols.scala:2385)
scala.reflect.internal.Symbols$Symbol.$anonfun$companionClass$1$adapted(Symbols.scala:2385)
scala.reflect.internal.Symbols$Symbol.filter(Symbols.scala:2061)
scala.reflect.internal.Symbols$Symbol.suchThat(Symbols.scala:2065)
scala.reflect.internal.Symbols$Symbol.companionClass(Symbols.scala:2385)
scala.reflect.internal.Symbols$ModuleClassSymbol.linkedClassOfClass(Symbols.scala:3549)
scala.tools.nsc.typechecker.Infer$Inferencer.isProperSubClassOrObject(Infer.scala:923)
scala.tools.nsc.typechecker.Infer$Inferencer.isProperSubClassOrObject(Infer.scala:923)
scala.tools.nsc.typechecker.Infer$Inferencer.isProperSubClassOrObject(Infer.scala:923)
...

Problem

I'd expect the Scala 2 code to compile.

jadenPete avatar Jun 03 '25 21:06 jadenPete

It works if the operator is not +.

This is an example where it would have been convenient to have the directives first.

This doesn't seem to work, using local Scala 2:

skalac -d out -cp "out;../../projects/dotty/library/target/scala-3.7.1/scala3-library_3-3.7.2-RC1-bin-SNAPSHOT-nonbootstrapped.jar" -Ytasty-reader main.scala
main.scala:10: error: value % is not a member of Option[Int]

I did not use my sabbatical year to figure out why.

Sample working operator:

//> using options -Ytasty-reader
//> using dep org.scala-lang:scala3-library_3:3.7.1
///> using dep org.scala-lang:scala3-library_3:3.6.4
package foo.bar

// masking imports allows using `+`
import scala.Predef.{any2stringadd => _, _}

object Main extends App {
  println {
    //None + None
    //Option(42) + Option(27)
    Option(42) % Option(27)
  }
}

The masking import works for the OP, no idea why.

What also works is "excluding" that conversion using -Xsource-features:

//> using options -Ytasty-reader -Xsource:3 -Xsource-features:any2stringadd

som-snytt avatar Jun 04 '25 00:06 som-snytt