summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala13
-rw-r--r--test/files/run/t8010.scala22
2 files changed, 35 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index abd3262c56..df220b7381 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -918,11 +918,24 @@ abstract class Erasure extends AddInterfaces
}
val decls = root.info.decls
+
+ // SI-8010 force infos, otherwise makeNotPrivate in ExplicitOuter info transformer can trigger
+ // a scope rehash while were iterating and we can see the same entry twice!
+ // Inspection of SymbolPairs (the basis of OverridingPairs), suggests that it is immune
+ // from this sort of bug as it copies the symbols into a temporary scope *before* any calls to `.info`,
+ // ie, no variant of it calls `info` or `tpe` in `SymbolPair#exclude`.
+ //
+ // Why not just create a temporary scope here? We need to force the name changes in any case before
+ // we do these checks, so that we're comparing same-named methods based on the expanded names that actually
+ // end up in the bytecode.
+ afterPostErasure(decls.foreach(_.info))
+
var e = decls.elems
while (e ne null) {
if (e.sym.isTerm) {
var e1 = decls.lookupNextEntry(e)
while (e1 ne null) {
+ assert(e.sym ne e1.sym, s"Internal error: encountered ${e.sym.debugLocationString} twice during scope traversal. This might be related to SI-8010.")
if (sameTypeAfterErasure(e1.sym, e.sym)) doubleDefError(e.sym, e1.sym)
e1 = decls.lookupNextEntry(e1)
}
diff --git a/test/files/run/t8010.scala b/test/files/run/t8010.scala
new file mode 100644
index 0000000000..8636bbd12e
--- /dev/null
+++ b/test/files/run/t8010.scala
@@ -0,0 +1,22 @@
+trait Base {
+ def t = 1
+ def t(n: Int) = n
+ def bt = 2
+ def bt(n: Int) = n
+}
+trait Derived extends Base {
+ // was: double defintion error
+ override def t = 1 + super.t
+ override def t(n: Int) = 1 + super.t(n)
+ override def bt = 1 + super.bt
+ override def bt(n: Int) = 1 + super.bt(n)
+}
+
+object Test extends App {
+ val d = new Derived {}
+ // not the focus of thie bug, but let's just check the runtime behaviour while we're here.
+ assert(d.t == 2)
+ assert(d.t(1) == 2)
+ assert(d.bt == 3)
+ assert(d.bt(1) == 2)
+}