Open
Description
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.