@@ -9,7 +9,7 @@ import util.Positions._
99import tasty .TreePickler .Hole
1010import SymUtils ._
1111import NameKinds ._
12- import dotty .tools .dotc .ast .tpd . Tree
12+ import dotty .tools .dotc .ast .tpd
1313import typer .Implicits .SearchFailureType
1414
1515import scala .collection .mutable
@@ -61,6 +61,7 @@ import dotty.tools.dotc.util.SourcePosition
6161 */
6262class ReifyQuotes extends MacroTransformWithImplicits {
6363 import ast .tpd ._
64+ import ReifyQuotes ._
6465
6566 /** Classloader used for loading macros */
6667 private [this ] var myMacroClassLoader : java.lang.ClassLoader = _
@@ -90,7 +91,7 @@ class ReifyQuotes extends MacroTransformWithImplicits {
9091 if (ctx.compilationUnit.containsQuotesOrSplices) super .run
9192
9293 protected def newTransformer (implicit ctx : Context ): Transformer =
93- new Reifier (inQuote = false , null , 0 , new LevelInfo , new mutable. ListBuffer , ctx)
94+ new Reifier (inQuote = false , null , 0 , new LevelInfo , new Embedded , ctx)
9495
9596 private class LevelInfo {
9697 /** A map from locally defined symbols to the staging levels of their definitions */
@@ -123,13 +124,13 @@ class ReifyQuotes extends MacroTransformWithImplicits {
123124 * @param rctx the contex in the destination lifted lambda
124125 */
125126 private class Reifier (inQuote : Boolean , val outer : Reifier , val level : Int , levels : LevelInfo ,
126- val embedded : mutable. ListBuffer [ Tree ] , val rctx : Context ) extends ImplicitsTransformer {
127+ val embedded : Embedded , val rctx : Context ) extends ImplicitsTransformer {
127128 import levels ._
128129 assert(level >= - 1 )
129130
130131 /** A nested reifier for a quote (if `isQuote = true`) or a splice (if not) */
131132 def nested (isQuote : Boolean )(implicit ctx : Context ): Reifier = {
132- val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new mutable. ListBuffer [ Tree ]
133+ val nestedEmbedded = if (level > 1 || (level == 1 && isQuote)) embedded else new Embedded
133134 new Reifier (isQuote, this , if (isQuote) level + 1 else level - 1 , levels, nestedEmbedded, ctx)
134135 }
135136
@@ -423,7 +424,8 @@ class ReifyQuotes extends MacroTransformWithImplicits {
423424 }
424425 else if (level == 1 ) {
425426 val (body1, quotes) = nested(isQuote = false ).split(splice.qualifier)
426- makeHole(body1, quotes, splice.tpe).withPos(splice.pos)
427+ val tpe = outer.embedded.getHoleType(splice)
428+ makeHole(body1, quotes, tpe).withPos(splice.pos)
427429 }
428430 else if (enclosingInlineds.nonEmpty) { // level 0 in an inlined call
429431 val spliceCtx = ctx.outer // drop the last `inlineContext`
@@ -478,14 +480,18 @@ class ReifyQuotes extends MacroTransformWithImplicits {
478480 (captured : mutable.Map [Symbol , Tree ]) => {
479481 (tree : Tree ) => {
480482 def newCapture = {
481- val tpw = tree.tpe.widen
483+ val tpw = tree.tpe.widen match {
484+ case tpw : MethodicType => tpw.toFunctionType()
485+ case tpw => tpw
486+ }
487+ assert(tpw.isInstanceOf [ValueType ])
482488 val argTpe =
483489 if (tree.isType) defn.QuotedTypeType .appliedTo(tpw)
484490 else defn.QuotedExprType .appliedTo(tpw)
485491 val selectArg = arg.select(nme.apply).appliedTo(Literal (Constant (i))).asInstance(argTpe)
486492 val capturedArg = SyntheticValDef (UniqueName .fresh(tree.symbol.name.toTermName).toTermName, selectArg)
487493 i += 1
488- embedded += tree
494+ embedded.addTree( tree, capturedArg.symbol)
489495 captured.put(tree.symbol, capturedArg)
490496 capturedArg
491497 }
@@ -526,15 +532,14 @@ class ReifyQuotes extends MacroTransformWithImplicits {
526532 */
527533 private def split (tree : Tree )(implicit ctx : Context ): (Tree , List [Tree ]) = {
528534 val tree1 = if (inQuote) addTags(transform(tree)) else makeLambda(tree)
529- (tree1, embedded.toList )
535+ (tree1, embedded.getTrees )
530536 }
531537
532538 /** Register `body` as an `embedded` quote or splice
533539 * and return a hole with `splices` as arguments and the given type `tpe`.
534540 */
535541 private def makeHole (body : Tree , splices : List [Tree ], tpe : Type )(implicit ctx : Context ): Hole = {
536- val idx = embedded.length
537- embedded += body
542+ val idx = embedded.addTree(body, NoSymbol )
538543 Hole (idx, splices).withType(tpe).asInstanceOf [Hole ]
539544 }
540545
@@ -624,10 +629,31 @@ class ReifyQuotes extends MacroTransformWithImplicits {
624629object ReifyQuotes {
625630 val name = " reifyQuotes"
626631
627- def toValue (tree : Tree ): Option [Any ] = tree match {
632+ def toValue (tree : tpd. Tree ): Option [Any ] = tree match {
628633 case Literal (Constant (c)) => Some (c)
629634 case Block (Nil , e) => toValue(e)
630635 case Inlined (_, Nil , e) => toValue(e)
631636 case _ => None
632637 }
638+
639+ class Embedded (trees : mutable.ListBuffer [tpd.Tree ] = mutable.ListBuffer .empty, map : mutable.Map [Symbol , tpd.Tree ] = mutable.Map .empty) {
640+ /** Adds the tree and returns it's index */
641+ def addTree (tree : tpd.Tree , liftedSym : Symbol ): Int = {
642+ trees += tree
643+ if (liftedSym ne NoSymbol )
644+ map.put(liftedSym, tree)
645+ trees.length - 1
646+ }
647+
648+ /** Type used for the hole that will replace this splice */
649+ def getHoleType (splice : tpd.Select )(implicit ctx : Context ): Type = {
650+ // For most expressions the splice.tpe but there are some types that are lost by lifting
651+ // that can be recoverd from the original tree. Currently the cases are:
652+ // * Method types: the splice represents a method reference
653+ map.get(splice.qualifier.symbol).map(_.tpe.widen).getOrElse(splice.tpe)
654+ }
655+
656+ /** Get the list of embedded trees */
657+ def getTrees : List [tpd.Tree ] = trees.toList
658+ }
633659}
0 commit comments