Skip to content

Inline summon generated by macro doesn't consider expanded macro scope #12359

Open
@japgolly

Description

@japgolly

Compiler version

3.0.0-RC3

Attempt 1: summonInline

Minimized code

a:scala:

import scala.quoted.*

case class F[A]()

object F:
  implicit def option[A: F]: F[Option[A]] = F()

  inline def test[A]: F[Option[A]] =
    ${ _test[A] }

  def _test[A](using Quotes, Type[A]): Expr[F[Option[A]]] =
    import quotes.reflect.*

    // Dynamically created `implicit val`
    val faSym  = Symbol.newVal(Symbol.spliceOwner, "fa", TypeRepr.of[F[A]], Flags.Implicit, Symbol.noSymbol)
    val faBody = '{ F[Int]() }.asTerm
    val faDef  = ValDef(faSym, Some(faBody))

    val summonInline = '{ scala.compiletime.summonInline[F[Option[A]]] }.asTerm
    val result = Block(List(faDef), summonInline).asExprOf[F[Option[A]]]

    println(s"\n${result.show}\n")
    result

b:scala:

object Test:

  val ko = F.test[Int]

  // Copy-paste of the .show output of the generated Expr
  val ok =
    implicit val fa: F[scala.Int] = F.apply[scala.Int]()
    scala.compiletime.package$package.summonInline[F[scala.Option[scala.Int]]]

Output

{
  implicit val fa: F[scala.Int] = F.apply[scala.Int]()
  scala.compiletime.package$package.summonInline[F[scala.Option[scala.Int]]]
}

[error] -- Error: b.scala:3:17 ----------------
[error] 3 |  val ko = F.test[Int]
[error]   |           ^^^^^^^^^^^
[error]   |           cannot reduce summonFrom with
[error]   |            patterns :  case given t @ _:F[Option[Int]]
[error]   | This location contains code that was inlined from package.scala:140
[error]   | This location contains code that was inlined from a.scala:19
[error]   | This location contains code that was inlined from a.scala:19
[error] one error found

Attempt 2: inline call to Implicits.search

Minimized code

a:scala:

import scala.quoted.*

object Util:
  def summonLater[A: Type](using Quotes): Expr[A] =
    '{ inlineSummon[A] }

  inline def inlineSummon[A]: A =
    ${ _inlineSummon[A] }

  def _inlineSummon[A: Type](using Quotes): Expr[A] =
    summonOrError[A]

  def summonOrError[A](using Type[A])(using Quotes): Expr[A] =
    import quotes.reflect.*
    Implicits.search(TypeRepr.of[A]) match
      case iss: ImplicitSearchSuccess => iss.tree.asExpr.asInstanceOf[Expr[A]]
      case isf: ImplicitSearchFailure => report.throwError(isf.explanation)

case class F[A]()

object F:
  implicit def option[A: F]: F[Option[A]] = F()

  inline def test[A]: F[Option[A]] =
    ${ _test[A] }

  def _test[A](using Quotes, Type[A]): Expr[F[Option[A]]] =
    import quotes.reflect.*

    // Dynamically created `implicit val`
    val faSym  = Symbol.newVal(Symbol.spliceOwner, "fa", TypeRepr.of[F[A]], Flags.Implicit, Symbol.noSymbol)
    val faBody = '{ F[Int]() }.asTerm
    val faDef  = ValDef(faSym, Some(faBody))

    val summonInline = Util.summonLater[F[Option[A]]].asTerm
    val result = Block(List(faDef), summonInline).asExprOf[F[Option[A]]]

    println(s"\n${result.show}\n")
    result

b:scala:

object Test:

  val ko = F.test[Int]

  // Copy-paste of the .show output of the generated Expr
  val ok =
    implicit val fa: F[scala.Int] = F.apply[scala.Int]()
    Util.inlineSummon[F[scala.Option[scala.Int]]]

Output

{
  implicit val fa: F[scala.Int] = F.apply[scala.Int]()
  Util.inlineSummon[F[scala.Option[scala.Int]]]
}

[error] -- Error: b.scala:3:17 ----------------
[error] 3 |  val ko = F.test[Int]
[error]   |           ^^^^^^^^^^^
[error]   |           no implicit values were found that match type F[Int]
[error]   | This location contains code that was inlined from b.scala:3
[error]   | This location contains code that was inlined from a.scala:5
[error]   | This location contains code that was inlined from a.scala:5
[error] one error found

Expectation

Neither macro compiles, however in both cases if I copy-paste the output of .show, the code compiles ok.

Implicit search should consider sibling implicits in local scope, just like normal code.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions