mirror of https://github.com/sbt/sbt.git
Handle macros that have themselves as original tree
It has been reported in sbt/sbt#1237 that stack overflows may occur during the extraction of used names (and later of dependencies between files). This problem has been introduced by sbt/sbt#1163, which was about recording the dependencies of macro arguments. When a macro is expanded, the compiler attaches the tree before expansion to the tree representing the expanded macro. As of Scala 2.11-RC3, some macros have themselves attached as original tree, which caused the same macro to be inspected over and over until a stack overflow. This commit solves this problem by making sure that the original of a macro expansion will be inspected if and only if it is different from the expanded tree. Fixes sbt/sbt#1237
This commit is contained in:
parent
12a799c929
commit
a80966e394
|
|
@ -146,7 +146,12 @@ final class Dependency(val global: CallbackGlobal) extends LocateClassFile
|
|||
deps.foreach(addDependency)
|
||||
case Template(parents, self, body) =>
|
||||
traverseTrees(body)
|
||||
case MacroExpansionOf(original) =>
|
||||
/*
|
||||
* Some macros appear to contain themselves as original tree
|
||||
* In this case, we don't need to inspect the original tree because
|
||||
* we already inspected its expansion, which is equal.
|
||||
*/
|
||||
case MacroExpansionOf(original) if original != tree =>
|
||||
this.traverse(original)
|
||||
case other => ()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,13 @@ class ExtractUsedNames[GlobalType <: CallbackGlobal](val global: GlobalType) ext
|
|||
}
|
||||
|
||||
def handleTreeNode(node: Tree): Unit = {
|
||||
def handleMacroExpansion(original: Tree): Unit = original.foreach(handleTreeNode)
|
||||
def handleMacroExpansion(original: Tree): Unit = {
|
||||
// Some macros seem to have themselves registered as original tree.
|
||||
// In this case, we only need to handle the children of the original tree,
|
||||
// because we already handled the expanded tree.
|
||||
if(original == node) original.children.foreach(handleTreeNode)
|
||||
else original.foreach(handleTreeNode)
|
||||
}
|
||||
|
||||
def handleClassicTreeNode(node: Tree): Unit = node match {
|
||||
case _: DefTree | _: Template => ()
|
||||
|
|
|
|||
Loading…
Reference in New Issue