Skip to content

Deferred given in companion object causes infinite recursion #22589

Open
@nkgm

Description

@nkgm

Compiler version

3.6.3

Minimized code

import scala.compiletime.deferred

trait MyCodec[E]

object auto {
  trait CompanionEssentials[E] {
    given MyCodec[E] = deferred
  }
}

import auto.CompanionEssentials

case class Person(name: String, age: Int)
object Person extends CompanionEssentials[Person]
// deferred given implemented as:
// override final lazy given val given_MyCodec_E: MyCodec[Person] =
//   Person.given_MyCodec_E

Output

Due to module class Person being in the implicit scope of Person, the compiler resolves the deferred given to its unimplemented self resulting in infinite recursion. This happens regardless of presence of a valid given in scope or not.

Expectation

The compiler should detect the cycle and exclude Person.given_MyCodec_E as a viable candidate, and produce an error if the deferred given couldn't be synthesized from other candidates in scope.

Workaround

The infinite recursion problem can be avoided by explicitly importing the relevant givens (which is probably what you should be doing in the first place):

object auto {
  trait CompanionEssentials[E] {
    given MyCodec[E] = deferred
  }

  given [E] => MyCodec[E] = new MyCodec[E]{}
}

import auto.{CompanionEssentials, given}

case class Person(name: String, age: Int)
object Person extends CompanionEssentials[Person]
// deferred given implemented as:
// override final lazy given val given_MyCodec_E: MyCodec[Person] =
//   auto.given_MyCodec_E[Person]

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions