Skip to content

Symbol.asQuotes doesn't populate the implicit scope #22260

Open
@joroKr21

Description

@joroKr21

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 => ()

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions