From c552416c37b9dbd37dd0b65a1827ec7f094ffb17 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Mon, 28 Aug 2017 12:51:00 +0200 Subject: [PATCH 1/3] Fix IDE crash on @AfterClass The TreeAccumulator was stuck in an infinite loop over the synthetic constructor of java annotations. This could be reproduced by opening the CompilationTests.scala in the IDE. --- .../dotc/interactive/InteractiveDriver.scala | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index 14ab4046d702..17c4811363f9 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -182,14 +182,24 @@ class InteractiveDriver(settings: List[String]) extends Driver { * of a previous run. Note that typed trees can have untyped or partially * typed children if the source contains errors. */ - private def cleanup(tree: tpd.Tree)(implicit ctx: Context): Unit = tree.foreachSubTree { t => - if (t.hasType) { - if (t.symbol.exists) { - if (!t.symbol.isCompleted) t.symbol.info = UnspecifiedErrorType - t.symbol.annotations.foreach(annot => cleanup(annot.tree)) + private def cleanup(tree: tpd.Tree)(implicit ctx: Context): Unit = { + val cleanedTree = mutable.Set.empty[tpd.Tree] + def cleanupTree(tree: tpd.Tree): Unit = { + cleanedTree += tree + tree.foreachSubTree { t => + if (t.hasType) { + if (t.symbol.exists) { + if (!t.symbol.isCompleted) t.symbol.info = UnspecifiedErrorType + t.symbol.annotations.foreach { annot => + if (!cleanedTree(annot.tree)) + cleanupTree(annot.tree) + } + } + } + t.removeAllAttachments() } } - t.removeAllAttachments() + cleanupTree(tree) } def run(uri: URI, sourceCode: String): List[MessageContainer] = { From f963bc287d4c17e982b31a826120f55bfcca4dd0 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Wed, 13 Sep 2017 11:21:09 +0200 Subject: [PATCH 2/3] Rename and join nested if expression --- .../dotc/interactive/InteractiveDriver.scala | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index 17c4811363f9..e0a8a3acf9c8 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -183,17 +183,15 @@ class InteractiveDriver(settings: List[String]) extends Driver { * typed children if the source contains errors. */ private def cleanup(tree: tpd.Tree)(implicit ctx: Context): Unit = { - val cleanedTree = mutable.Set.empty[tpd.Tree] + val seen = mutable.Set.empty[tpd.Tree] def cleanupTree(tree: tpd.Tree): Unit = { - cleanedTree += tree + seen += tree tree.foreachSubTree { t => - if (t.hasType) { - if (t.symbol.exists) { - if (!t.symbol.isCompleted) t.symbol.info = UnspecifiedErrorType - t.symbol.annotations.foreach { annot => - if (!cleanedTree(annot.tree)) - cleanupTree(annot.tree) - } + if (t.symbol.exists && t.hasType) { + if (!t.symbol.isCompleted) t.symbol.info = UnspecifiedErrorType + t.symbol.annotations.foreach { annot => + if (!seen(annot.tree)) + cleanupTree(annot.tree) } } t.removeAllAttachments() From 5b88356e12c351575ca6b3e5d78bd48058bd748b Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 19 Sep 2017 10:04:24 +0200 Subject: [PATCH 3/3] Add comment --- .../dotty/tools/dotc/interactive/InteractiveDriver.scala | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala index e0a8a3acf9c8..dffe81c5216b 100644 --- a/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala +++ b/compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala @@ -190,6 +190,12 @@ class InteractiveDriver(settings: List[String]) extends Driver { if (t.symbol.exists && t.hasType) { if (!t.symbol.isCompleted) t.symbol.info = UnspecifiedErrorType t.symbol.annotations.foreach { annot => + /* In some cases annotations are are used on themself (possibly larger cycles). + * This is the case with the java.lang.annotation.Target annotation, would end + * in an infinite loop while cleaning. The `seen` is added to ensure that those + * trees are not cleand twice. + * TODO: Find a less expensive way to check for those cycles. + */ if (!seen(annot.tree)) cleanupTree(annot.tree) }