Open
Description
Compiler version
3.6.2
Minimized code
import scala.quoted.*
def withGiven[T: Type](values: List[Expr[Any]])(result: Quotes ?=> Expr[T])(using Quotes): Expr[T] =
values match
case '{ $x: t } :: values =>
'{ given t = $x; ${ withGiven(values)(result) } }
case _ =>
result
def withGivenInt(x: Expr[Int])(using Quotes) =
withGiven(x :: Nil)(Expr.summon[Int].get)
inline def withInt(inline x: Int) =
${withGivenInt('x)}
Output
scala> withInt(42)
-- Error: ----------------------------------------------------------------------
1 |withInt(42)
|^^^^^^^^^^^
|Exception occurred while executing macro expansion.
|java.util.NoSuchElementException: None.get
| at scala.None$.get(Option.scala:627)
| at scala.None$.get(Option.scala:626)
| at rs$line$1$.withGivenInt$$anonfun$1(rs$line$1:11)
| at rs$line$1$.withGiven(rs$line$1:8)
| at rs$line$1$.withGiven$$anonfun$1(rs$line$1:6)
| at rs$line$1$.withGiven$$anonfun$adapted$1(rs$line$1:6)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:111)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1571)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:136)
| at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformBlock$$anonfun$1$$anonfun$1(tpd.scala:1270)
| at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.loop$2(tpd.scala:1252)
| at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformStats(tpd.scala:1265)
| at dotty.tools.dotc.ast.tpd$TreeMapWithPreciseStatContexts.transformBlock(tpd.scala:1270)
| at dotty.tools.dotc.ast.Trees$Instance$TreeMap.transform(Trees.scala:1551)
| at dotty.tools.dotc.quoted.PickledQuotes$$anon$1.transform(PickledQuotes.scala:136)
| at dotty.tools.dotc.quoted.PickledQuotes$.spliceTerms(PickledQuotes.scala:153)
| at dotty.tools.dotc.quoted.PickledQuotes$.unpickleTerm(PickledQuotes.scala:89)
| at scala.quoted.runtime.impl.QuotesImpl.unpickleExprV2(QuotesImpl.scala:3279)
| at rs$line$1$.withGiven(rs$line$1:6)
| at rs$line$1$.withGivenInt(rs$line$1:11)
|
|----------------------------------------------------------------------------
|Inline stack trace
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|This location contains code that was inlined from rs$line$1:14
14 | ${withGivenInt('x)}
| ^^^^^^^^^^^^^^^^^^^
----------------------------------------------------------------------------
1 error found
Expectation
Symbol.asQuotes
should populate the implicit scope.
Real world use-case: typelevel/cats-tagless#588
See the hack that I had to do (refs
here are the implicit parameters of the method owning the quotes q
):
def addToGivenScope(refs: List[TermRef])(using q: Quotes) =
if refs.nonEmpty then
try
Expr.summon[Nothing] // fill implicit cache
val ctxMethod = q.getClass.getMethod("ctx")
val ctx = ctxMethod.invoke(q)
val cache = ctxMethod.getReturnType.getDeclaredField("implicitsCache")
cache.setAccessible(true)
val contextual = Class.forName("dotty.tools.dotc.typer.Implicits$ContextualImplicits")
val modified = contextual.getConstructors.head.newInstance(refs, cache.get(ctx), false, ctx)
cache.set(ctx, modified)
catch case _: ReflectiveOperationException => ()