Skip to content

Commit

Permalink
Merge pull request #14809 from dotty-staging/fix-14789
Browse files Browse the repository at this point in the history
Handle SummonFrom in reflect TreeAccumulator
  • Loading branch information
smarter committed Mar 30, 2022
2 parents e835668 + 1d58335 commit ee6733a
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 2 deletions.
23 changes: 21 additions & 2 deletions library/src/scala/quoted/Quotes.scala
Expand Up @@ -4621,6 +4621,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
case Bind(_, body) => foldTree(x, body)(owner)
case Unapply(fun, implicits, patterns) => foldTrees(foldTrees(foldTree(x, fun)(owner), implicits)(owner), patterns)(owner)
case Alternatives(patterns) => foldTrees(x, patterns)(owner)
case SummonFrom(cases) => foldTrees(x, cases)(owner)
case _ => throw MatchError(tree.show(using Printer.TreeStructure))
}
}
end TreeAccumulator
Expand Down Expand Up @@ -4662,7 +4664,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
def transformTree(tree: Tree)(owner: Symbol): Tree = {
tree match {
case tree: PackageClause =>
PackageClause.copy(tree)(transformTerm(tree.pid).asInstanceOf[Ref], transformTrees(tree.stats)(tree.symbol))
PackageClause.copy(tree)(transformTerm(tree.pid)(owner).asInstanceOf[Ref], transformTrees(tree.stats)(tree.symbol))
case tree: Import =>
Import.copy(tree)(transformTerm(tree.expr)(owner), tree.selectors)
case tree: Export =>
Expand All @@ -4685,6 +4687,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
Alternatives.copy(pattern)(transformTrees(pattern.patterns)(owner))
case TypedOrTest(inner, tpt) =>
TypedOrTest.copy(tree)(transformTree(inner)(owner), transformTypeTree(tpt)(owner))
case _ =>
throw MatchError(tree.show(using Printer.TreeStructure))
}
}

Expand All @@ -4708,11 +4712,20 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
val owner = tree.symbol
TypeDef.copy(tree)(tree.name, transformTree(tree.rhs)(owner))
case tree: ClassDef =>
ClassDef.copy(tree)(tree.name, tree.constructor, tree.parents, tree.self, tree.body)
val constructor @ DefDef(_, _, _, _) = transformStatement(tree.constructor)(tree.symbol)
val parents = tree.parents.map(transformTree(_)(tree.symbol))
val self = tree.self.map { slf =>
transformStatement(slf)(tree.symbol) match
case self: ValDef => self
}
val body = tree.body.map(transformStatement(_)(tree.symbol))
ClassDef.copy(tree)(tree.name, constructor, parents, self, body)
case tree: Import =>
Import.copy(tree)(transformTerm(tree.expr)(owner), tree.selectors)
case tree: Export =>
tree
case _ =>
throw MatchError(tree.show(using Printer.TreeStructure))
}
}

Expand Down Expand Up @@ -4758,6 +4771,10 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
Repeated.copy(tree)(transformTerms(elems)(owner), transformTypeTree(elemtpt)(owner))
case Inlined(call, bindings, expansion) =>
Inlined.copy(tree)(call, transformSubTrees(bindings)(owner), transformTerm(expansion)(owner))
case SummonFrom(cases) =>
SummonFrom.copy(tree)(transformCaseDefs(cases)(owner))
case _ =>
throw MatchError(tree.show(using Printer.TreeStructure))
}
}

Expand Down Expand Up @@ -4786,6 +4803,8 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
TypeBind.copy(tree)(tree.name, tree.body)
case tree: TypeBlock =>
TypeBlock.copy(tree)(tree.aliases, tree.tpt)
case _ =>
throw MatchError(tree.show(using Printer.TreeStructure))
}

def transformCaseDef(tree: CaseDef)(owner: Symbol): CaseDef = {
Expand Down
45 changes: 45 additions & 0 deletions tests/run-custom-args/tasty-inspector/i14789.scala
@@ -0,0 +1,45 @@
import scala.quoted.*
import scala.tasty.inspector.*

@main def Test = {
// Artefact of the current test infrastructure
// TODO improve infrastructure to avoid needing this code on each test
val classpath = dotty.tools.dotc.util.ClasspathFromClassloader(this.getClass.getClassLoader).split(java.io.File.pathSeparator).find(_.contains("runWithCompiler")).get
val allTastyFiles = dotty.tools.io.Path(classpath).walkFilter(_.extension == "tasty").map(_.toString).toList
val tastyFiles = allTastyFiles.filter(_.contains("App"))

// in dotty-example-project
val inspector = new Inspector {
def inspect(using Quotes)(tastys: List[Tasty[quotes.type]]): Unit = {
import quotes.reflect.*
val traverser = new TreeTraverser {
override def traverseTree(tree: Tree)(owner: Symbol): Unit = {
try {
super.traverseTree(tree)(owner)
} catch {
case e =>
report.error(s"unexpected error ${e}", tree.pos)
throw e
}
}
}
val mapper = new TreeMap { }
tastys.foreach{ tasty =>
traverser.traverseTree(tasty.ast)(tasty.ast.symbol)
mapper.transformTree(tasty.ast)(tasty.ast.symbol)
}
}
}
TastyInspector.inspectTastyFiles(tastyFiles)(inspector)
}

object App {
import scala.compiletime.*

transparent inline def summonFirst0[T]: Any =
inline erasedValue[T] match
case _: (a *: b) => summonFrom {
case instance: `a` => instance
case _ => summonFirst0[b]
}
}

0 comments on commit ee6733a

Please sign in to comment.