diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2015-02-03 18:46:33 +1000 |
---|---|---|
committer | Jason Zaugg <jzaugg@gmail.com> | 2015-02-03 18:46:33 +1000 |
commit | 1a56eb30da31dc4134c8ef78a45dde45df3c8b27 (patch) | |
tree | 5f7899b6f40e2ad5f4ec6984edc5d3a5642cd055 | |
parent | 5d7098c629bbb7cc0ab7e74c235bd4afca3de24e (diff) | |
download | scala-1a56eb30da31dc4134c8ef78a45dde45df3c8b27.tar.gz scala-1a56eb30da31dc4134c8ef78a45dde45df3c8b27.tar.bz2 scala-1a56eb30da31dc4134c8ef78a45dde45df3c8b27.zip |
SI-9133 Harden against infinite loop in NoSymbol.owner
The available evidence gathered in an IDE hang suggests that
while editing erronenous code, a call to `Erasure#javaSig` by the
IDE's structure builder triggered the `ExplicitOuter` info transformer
on a symbol with some sort of incoherent owner chain, which led to
an infinite loop in `NoSymbol#outerClass`.
This commit hardens that method to work in the same manner as a call
to `NoSymbol.owner`: log the error under -Xdev or -Ydebug and return
return `NoSymbol` to soldier on without crashing / hanging.
I haven't formulated a theory about how we might have ended up with
the corrupt owner chain.
-rw-r--r-- | src/reflect/scala/reflect/internal/Symbols.scala | 6 | ||||
-rw-r--r-- | test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala | 5 |
2 files changed, 10 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index e91bfadc85..d5fc52abbf 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -2054,7 +2054,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => * where it is the outer class of the enclosing class. */ final def outerClass: Symbol = - if (owner.isClass) owner + if (this == NoSymbol) { + // ideally we shouldn't get here, but its better to harden against this than suffer the infinite loop in SI-9133 + devWarningDumpStack("NoSymbol.outerClass", 15) + NoSymbol + } else if (owner.isClass) owner else if (isClassLocalToConstructor) owner.enclClass.outerClass else owner.outerClass diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala index 11e955a4bb..895ad9d683 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala @@ -44,4 +44,9 @@ class SymbolTableTest { assertFalse("Foo should be a superclass of Foo", fooSymbol.tpe <:< barSymbol.tpe) } + @Test + def noSymbolOuterClass_t9133: Unit = { + import symbolTable._ + assert(NoSymbol.outerClass == NoSymbol) + } } |