From fdd860df184f4c8bc6997ce2c1045b23c9fb61aa Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Wed, 4 Sep 2013 15:02:00 +0200 Subject: SI-7801 Fix a nightmarish bug in Symbols#adaptInfos The compiler-in-residence has always been a sketchy affair; FSC and REPL offers a bounty of bugs that exploit the menagerie of time-travel mechanisms in play for symbols' metadata (type, flags, name and owner.) but are often cleverly masked by optimizations in the compiler based on reference equality. The latest: an innocuous change in Erasure: https://github.com/scala/scala/commit/d8b96bb8#commitcomment-3995163 means that some `ErasureMap`-s over `MethodType`-s are now true identities (as `UnitTpe` is always the same object, whereas `erasedTypeRef(UnitClass)` returns an different `TypeRef` each time.) This, in turn, enables `TypeMap#mapOver` to reuse the existing enclosing type, and so on. On such subtleties hinge further optimizations, such as whether or not a given phase's `InfoTransformer` needs to add an entry in a symbols type history. When the REPL (or FSC / Presentation Compiler) creates a new `Run`, `Symbol#rawInfo` tries to adapt the entries in the type history for the new run. For packages, this was taken to be a no-op; each entry is marked as being valid in the new run and no further action is taken. This logic lurks in `adaptInfos`. But, when the namer enters a new symbol in a package, it *mutates* the Scope of that package classes info `enteringTyper`. So the later entries in the type history *must* be invalidated and recomputed. We have two choices for a fix: 1) modify `Namers#enterInScope` to blow away the subsequent type history for the owning symbol after inserting the new member. Something like `owner.setInfo(owner.info)` would have the desired effect. 2) Change `adaptInfos` to be more conservative when it comes to package classes, and retain only the oldest entry in the type history. This commit goes for option 2. --- test/files/run/t7801.scala | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 test/files/run/t7801.scala (limited to 'test/files/run/t7801.scala') diff --git a/test/files/run/t7801.scala b/test/files/run/t7801.scala new file mode 100644 index 0000000000..3a3cc97a51 --- /dev/null +++ b/test/files/run/t7801.scala @@ -0,0 +1,12 @@ +import scala.tools.partest.ReplTest + +// was crashing due to a subtle interaction of the Namer entering packages into +// enclosing packages by mutating the scope in place without invalidating later +// entries in the enclosing package class symbols type history. +// +// Sadly, I couldn't whittle the test case down further. +object Test extends ReplTest { + override def code = """val g: scala.reflect.internal.SymbolTable = null; import g.abort + |class C(val a: Any) extends AnyVal""".stripMargin + +} -- cgit v1.2.3