diff options
author | Paul Phillips <paulp@improving.org> | 2011-06-29 20:43:52 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-06-29 20:43:52 +0000 |
commit | 7c15ff1c2a24856cd2b9541c756b7e72f04d5848 (patch) | |
tree | 7450e901d19050e68e724cf3a659c8e772471faf | |
parent | 3d5eab83ad9dc047008e7ac9d04a478314119dd0 (diff) | |
download | scala-7c15ff1c2a24856cd2b9541c756b7e72f04d5848.tar.gz scala-7c15ff1c2a24856cd2b9541c756b7e72f04d5848.tar.bz2 scala-7c15ff1c2a24856cd2b9541c756b7e72f04d5848.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 | 27 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Namers.scala | 4 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 9 | ||||
-rw-r--r-- | test/files/neg/bug1286.check | 4 |
4 files changed, 29 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Symbols.scala b/src/compiler/scala/tools/nsc/symtab/Symbols.scala index 9dec01fb7d..ef295acd02 100644 --- a/src/compiler/scala/tools/nsc/symtab/Symbols.scala +++ b/src/compiler/scala/tools/nsc/symtab/Symbols.scala @@ -1220,16 +1220,21 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable => /** Is this symbol defined in the same scope and compilation unit as `that' symbol? */ def isCoDefinedWith(that: Symbol) = - (this.rawInfo ne NoType) && - (this.owner == that.owner) && { - !this.owner.isPackageClass || - (this.sourceFile eq null) || - (that.sourceFile eq null) || - (this.sourceFile == that.sourceFile) || { - // recognize companion object in separate file and fail, else compilation - // appears to succeed but highly opaque errors come later: see bug #1286 - if (this.sourceFile.path != that.sourceFile.path) + (this.rawInfo ne NoType) && { + val res = + !this.owner.isPackageClass || + (this.sourceFile eq null) || + (that.sourceFile eq null) || + (this.sourceFile eq that.sourceFile) || + (this.sourceFile == that.sourceFile) + + // recognize companion object in separate file and fail, else compilation + // appears to succeed but highly opaque errors come later: see bug #1286 + if (res == false) { + val (f1, f2) = (this.sourceFile, that.sourceFile) + if (f1 != null && f2 != null && f1.path != f2.path) throw InvalidCompanions(this, that) + } false } @@ -2103,9 +2108,7 @@ trait Symbols extends reflect.generic.Symbols { self: SymbolTable => } case class InvalidCompanions(sym1: Symbol, sym2: Symbol) - extends Throwable("Companions '" + sym1 + "' and '" + sym2 + "' must be defined in same file") { - override def toString = getMessage - } + 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) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index 27f8df18b3..07cce81565 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -1382,7 +1382,7 @@ trait Namers { self: Analyzer => * Finds the companion module of a class symbol. Calling .companionModule * does not work for classes defined inside methods. */ - def companionModuleOf(clazz: Symbol, context: Context): Symbol = { + def companionModuleOf(clazz: Symbol, context: Context) = { try { var res = clazz.companionModule if (res == NoSymbol) @@ -1396,7 +1396,7 @@ trait Namers { self: Analyzer => } } - def companionClassOf(module: Symbol, context: Context): Symbol = { + def companionClassOf(module: Symbol, context: Context) = { try { var res = module.companionClass if (res == NoSymbol) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 745809ccbb..1bf51973ba 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -1340,7 +1340,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 d45d8094fd..734964e9cf 100644 --- a/test/files/neg/bug1286.check +++ b/test/files/neg/bug1286.check @@ -1,3 +1,7 @@ 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 |