From a80966e394b8f119b0875d9a9a7994591bdaf1d8 Mon Sep 17 00:00:00 2001 From: Martin Duhem Date: Mon, 7 Apr 2014 11:33:47 +0200 Subject: [PATCH] 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 --- compile/interface/src/main/scala/xsbt/Dependency.scala | 7 ++++++- .../interface/src/main/scala/xsbt/ExtractUsedNames.scala | 8 +++++++- .../macro-arg-dep-2-11/{pending => test} | 0 .../macro-arg-dep-nested-2-11/{pending => test} | 0 4 files changed, 13 insertions(+), 2 deletions(-) rename sbt/src/sbt-test/source-dependencies/macro-arg-dep-2-11/{pending => test} (100%) rename sbt/src/sbt-test/source-dependencies/macro-arg-dep-nested-2-11/{pending => test} (100%) diff --git a/compile/interface/src/main/scala/xsbt/Dependency.scala b/compile/interface/src/main/scala/xsbt/Dependency.scala index b8a55c8a93..77dd9355ff 100644 --- a/compile/interface/src/main/scala/xsbt/Dependency.scala +++ b/compile/interface/src/main/scala/xsbt/Dependency.scala @@ -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 => () } diff --git a/compile/interface/src/main/scala/xsbt/ExtractUsedNames.scala b/compile/interface/src/main/scala/xsbt/ExtractUsedNames.scala index 6ab01c9eb6..1bcaf125f0 100644 --- a/compile/interface/src/main/scala/xsbt/ExtractUsedNames.scala +++ b/compile/interface/src/main/scala/xsbt/ExtractUsedNames.scala @@ -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 => () diff --git a/sbt/src/sbt-test/source-dependencies/macro-arg-dep-2-11/pending b/sbt/src/sbt-test/source-dependencies/macro-arg-dep-2-11/test similarity index 100% rename from sbt/src/sbt-test/source-dependencies/macro-arg-dep-2-11/pending rename to sbt/src/sbt-test/source-dependencies/macro-arg-dep-2-11/test diff --git a/sbt/src/sbt-test/source-dependencies/macro-arg-dep-nested-2-11/pending b/sbt/src/sbt-test/source-dependencies/macro-arg-dep-nested-2-11/test similarity index 100% rename from sbt/src/sbt-test/source-dependencies/macro-arg-dep-nested-2-11/pending rename to sbt/src/sbt-test/source-dependencies/macro-arg-dep-nested-2-11/test