diff options
author | Martin Odersky <odersky@gmail.com> | 2012-01-04 07:05:19 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2012-01-04 07:05:19 +0100 |
commit | fafbffc2950aa3f25f91575786093e044f9af549 (patch) | |
tree | a3ebfdd4cc67b4e4b7f4299cdc872e5b1210599a /src | |
parent | 471a63a9e6618f25feb3a5266c38ad98ea2a5ac7 (diff) | |
download | scala-fafbffc2950aa3f25f91575786093e044f9af549.tar.gz scala-fafbffc2950aa3f25f91575786093e044f9af549.tar.bz2 scala-fafbffc2950aa3f25f91575786093e044f9af549.zip |
Closes SI-5354.
The reason why the test case compiled without error is pretty devious: When checking the `Foo.x' implicit, a CyclicReference error occurs which causes the alternative to be discarded. Why a CylicReference? Because the inferencer tries to decide whether the owner of `z` is a subclass of the owner od `x`. To do this, it computed the info of the owner of `z1`, which is not complete because no result type for `f1` was given. Hence a CyclicReference error.
The fix is twofold: (1) We make isNonBottomSubClass smarter so that it always returns false if the symbol in question is not a type; hence the info need not be computed. (2) It's dubious to swallow CyclicReference errors anywhere, but I deemed it too risky to propagate them. But at least the CyclicReference is now logged if -Ylog-implicit is true. This hopefully spares future maintainers the same detective work I had to go through when digging this out.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/reflect/internal/Symbols.scala | 15 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Implicits.scala | 9 |
2 files changed, 17 insertions, 7 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala index 0c57f0c43a..e629b0ed43 100644 --- a/src/compiler/scala/reflect/internal/Symbols.scala +++ b/src/compiler/scala/reflect/internal/Symbols.scala @@ -1244,12 +1244,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => */ final def isNestedIn(that: Symbol): Boolean = owner == that || owner != NoSymbol && (owner isNestedIn that) - - /** Is this class symbol a subclass of that symbol? */ - final def isNonBottomSubClass(that: Symbol): Boolean = ( - (this eq that) || this.isError || that.isError || - info.baseTypeIndex(that) >= 0 - ) + + /** Is this class symbol a subclass of that symbol, + * and is this class symbol also different from Null or Nothing? */ + def isNonBottomSubClass(that: Symbol): Boolean = false /** Overridden in NullClass and NothingClass for custom behavior. */ @@ -2226,6 +2224,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => super.info_=(tp) } + final override def isNonBottomSubClass(that: Symbol): Boolean = ( + (this eq that) || this.isError || that.isError || + info.baseTypeIndex(that) >= 0 + ) + override def reset(completer: Type) { super.reset(completer) tpePeriod = NoPeriod diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala index d54cb248cf..77dde88a80 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala @@ -816,7 +816,14 @@ trait Implicits { val newPending = undoLog undo { is filterNot (alt => alt == i || { try improves(i, alt) - catch { case e: CyclicReference => true } + catch { + case e: CyclicReference => + if (printInfers) { + println(i+" discarded because cyclic reference occurred") + e.printStackTrace() + } + true + } }) } rankImplicits(newPending, i :: acc) |