Skip to content

Unintended recursive implicit conversion #13542

Closed
@prolativ

Description

@prolativ

Compiler version

3.0.2

Minimized code

import scala.language.implicitConversions
implicit def strToInt(s: String): Int = s.toInt
val x: Int = "1"

Output (at runtime)

java.lang.StackOverflowError
  at repl$.rs$line$1$.strToInt(rs$line$1:1)
  at repl$.rs$line$1$.strToInt(rs$line$1:1)
  at repl$.rs$line$1$.strToInt(rs$line$1:1)
  ...

Less minimal but more self-contained code

import scala.language.implicitConversions

case class Foo(i: Int) extends AnyVal:
  def toFoo = this

case class Bar(i: Int) extends AnyVal

class BarOps(bar: Bar):
  def toFoo = Foo(bar.i)

implicit def augmentBar(bar: Bar): BarOps = BarOps(bar)

val x =
  implicit def barToFoo(bar: Bar): Foo = bar.toFoo
  val foo: Foo = Bar(1)

Output (at runtime)

java.lang.StackOverflowError
  at repl$.rs$line$1$.barToFoo$1(rs$line$1:14)
  at repl$.rs$line$1$.barToFoo$1(rs$line$1:14)
  at repl$.rs$line$1$.barToFoo$1(rs$line$1:14)
  ...

Expectation

The first snippet was a real puzzler to me and I spent quite a lot of time trying to figure out what was happening there until I found the reason shown in the second snippet (in the first one it's about toInt being defined on Int and at the same time added to String from StringOps by augmentString from Predef).

Not sure whether this would be easy to achieve with the current scheme of resolving implicits but it would be good to avoid the cyclic call of barToFoo by choosing the method added by the old style extension. Note that there's no cycle if we use a new style extension method instead.

import scala.language.implicitConversions

case class Foo(i: Int) extends AnyVal:
  def toFoo = this

case class Bar(i: Int) extends AnyVal

extension (bar: Bar)
  def toFoo = Foo(bar.i)
  
val x =
  implicit def barToFoo(bar: Bar): Foo = bar.toFoo
  val foo: Foo = Bar(1)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions