diff options
author | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2010-11-02 00:15:06 +0000 |
---|---|---|
committer | Hubert Plociniczak <hubert.plociniczak@epfl.ch> | 2010-11-02 00:15:06 +0000 |
commit | b80f27780458da880d47392e4ac747d196af355e (patch) | |
tree | db857dc93086a6e11d4af0cef7a8a8506a55ba00 | |
parent | b9982a3d3d338d097fbee082c5f6778f6494f5cd (diff) | |
download | scala-b80f27780458da880d47392e4ac747d196af355e.tar.gz scala-b80f27780458da880d47392e4ac747d196af355e.tar.bz2 scala-b80f27780458da880d47392e4ac747d196af355e.zip |
Don't crash the compiler for the 'companions in...
Don't crash the compiler for the 'companions in different files'
error. This turned out to be pretty bad for the presentation compiler.
References #1286. Review by extempore
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Symbols.scala | 5 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 30 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 9 | ||||
-rw-r--r-- | test/files/neg/bug1286.check | 9 |
4 files changed, 40 insertions, 13 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index f62d221320..34a9dfa5cd 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -1185,7 +1185,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable => if (res == false) { val (f1, f2) = (this.sourceFile, that.sourceFile) if (f1 != null && f2 != null && f1.path != f2.path) - throw FatalError("Companions '" + this + "' and '" + that + "' must be defined in same file.") + throw InvalidCompanions(this, that) } res @@ -2047,6 +2047,9 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable => // printStackTrace() // debug } + case class InvalidCompanions(sym1: Symbol, sym2: Symbol) + extends Throwable("Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file") + /** A class for type histories */ private sealed case class TypeHistory(var validFrom: Period, info: Type, prev: TypeHistory) { assert((prev eq null) || phaseId(validFrom) > phaseId(prev.validFrom), this) diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index cac788906b..35b34ae5fd 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1359,18 +1359,30 @@ trait Namers { self: Analyzer => * does not work for classes defined inside methods. */ def companionModuleOf(clazz: Symbol, context: Context) = { - var res = clazz.companionModule - if (res == NoSymbol) - res = context.lookup(clazz.name.toTermName, clazz.owner).suchThat(sym => - sym.hasFlag(MODULE) && sym.isCoDefinedWith(clazz)) - res + try { + var res = clazz.companionModule + if (res == NoSymbol) + res = context.lookup(clazz.name.toTermName, clazz.owner).suchThat(sym => + sym.hasFlag(MODULE) && sym.isCoDefinedWith(clazz)) + res + } catch { + case e: InvalidCompanions => + context.error(clazz.pos, e.getMessage) + NoSymbol + } } def companionClassOf(module: Symbol, context: Context) = { - var res = module.companionClass - if (res == NoSymbol) - res = context.lookup(module.name.toTypeName, module.owner).suchThat(_.isCoDefinedWith(module)) - res + try { + var res = module.companionClass + if (res == NoSymbol) + res = context.lookup(module.name.toTypeName, module.owner).suchThat(_.isCoDefinedWith(module)) + res + } catch { + case e: InvalidCompanions => + context.error(module.pos, e.getMessage) + NoSymbol + } } /** An explanatory note to be added to error messages diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index e0e8efb007..d87cd571d8 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1330,7 +1330,14 @@ trait Typers { self: Analyzer => // attributes(mdef) // initialize all constructors of the linked class: the type completer (Namer.methodSig) // might add default getters to this object. example: "object T; class T(x: Int = 1)" - val linkedClass = mdef.symbol.companionClass + val linkedClass = + try { + mdef.symbol.companionClass + } catch { + case e: InvalidCompanions => + context.error(mdef.symbol.pos, e.getMessage) + NoSymbol + } if (linkedClass != NoSymbol) for (c <- linkedClass.info.decl(nme.CONSTRUCTOR).alternatives) c.initialize diff --git a/test/files/neg/bug1286.check b/test/files/neg/bug1286.check index 9bf63252cc..734964e9cf 100644 --- a/test/files/neg/bug1286.check +++ b/test/files/neg/bug1286.check @@ -1,2 +1,7 @@ -error: fatal error: Companions 'object Foo' and 'trait Foo' must be defined in same file. -one error found +a.scala:1: error: Companions 'object Foo' and 'trait Foo' must be defined in same file +trait Foo { + ^ +b.scala:1: error: Companions 'trait Foo' and 'object Foo' must be defined in same file +object Foo extends Foo { + ^ +two errors found |