diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala index ec58f8863e6..3ca7b7a1538 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala @@ -13,7 +13,9 @@ package scala.tools.nsc package typechecker +import scala.collection.mutable import scala.collection.mutable.ArrayDeque +import scala.reflect.internal.util.JavaClearable /** Defines the sub-components for the namer, packageobjects, and typer phases. */ @@ -55,7 +57,13 @@ trait Analyzer extends AnyRef object packageObjects extends { val global: Analyzer.this.global.type = Analyzer.this.global } with SubComponent { - val deferredOpen = perRunCaches.newSet[Symbol]() + val deferredOpen: mutable.Set[Symbol] = { + import scala.jdk.CollectionConverters._ + // This will throw a ConcurrentModificationException if we mutate during iteration + val javaSet = new java.util.LinkedHashSet[Symbol]() + perRunCaches.recordCache(JavaClearable.forCollection(javaSet)) + javaSet.asScala + } val phaseName = "packageobjects" val runsAfter = List[String]() val runsRightAfter= Some("namer") @@ -80,8 +88,18 @@ trait Analyzer extends AnyRef def apply(unit: CompilationUnit): Unit = { openPackageObjectsTraverser(unit.body) - deferredOpen.foreach(openPackageModule(_)) - deferredOpen.clear() + } + + override def run(): Unit = { + super.run() + + for (sym <- deferredOpen.toVector) { + if (deferredOpen.remove(sym)) { + // this can remove entries from `deferredOpen`, hence the copy to a vector + // and the check of `remove` return value + openPackageModule(sym) + } + } } } } diff --git a/test/files/pos/package-object-deferred-load-bug/A_1.scala b/test/files/pos/package-object-deferred-load-bug/A_1.scala new file mode 100644 index 00000000000..2597aff42d2 --- /dev/null +++ b/test/files/pos/package-object-deferred-load-bug/A_1.scala @@ -0,0 +1,7 @@ +package p1 { + package x_01 { object zappo {}} + + package x_64 { + object zappo {} + } +} diff --git a/test/files/pos/package-object-deferred-load-bug/A_2.scala b/test/files/pos/package-object-deferred-load-bug/A_2.scala new file mode 100644 index 00000000000..f40038de1a6 --- /dev/null +++ b/test/files/pos/package-object-deferred-load-bug/A_2.scala @@ -0,0 +1,10 @@ +package p1 { + import x_64._ + package x_01 { + object blerg extends AnyRef {} + } + + package x_64 { + object blerg {} + } +} \ No newline at end of file diff --git a/test/files/pos/package-object-deferred-load-bug/B_2.scala b/test/files/pos/package-object-deferred-load-bug/B_2.scala new file mode 100644 index 00000000000..b39bbae9da7 --- /dev/null +++ b/test/files/pos/package-object-deferred-load-bug/B_2.scala @@ -0,0 +1,10 @@ +package p1 { + import x_64._ + package x_01 { + object `package` extends AnyRef { def m = "m "} + } + + package x_64 { + object `package` { def m = "m" } + } +}