bug
bug copied to clipboard
StackOverflowError when using implicit class compiled with Scala 3 in Scala 2
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.
- 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 + _))
}
}
- Compile the following with Scala 2:
package foo.bar
object Main {
None + None
}
- 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.
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