summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-06-29 20:43:52 +0000
committerPaul Phillips <paulp@improving.org>2011-06-29 20:43:52 +0000
commit7c15ff1c2a24856cd2b9541c756b7e72f04d5848 (patch)
tree7450e901d19050e68e724cf3a659c8e772471faf
parent3d5eab83ad9dc047008e7ac9d04a478314119dd0 (diff)
downloadscala-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.scala27
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala9
-rw-r--r--test/files/neg/bug1286.check4
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