diff options
author | Martin Odersky <odersky@gmail.com> | 2010-03-13 20:21:13 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2010-03-13 20:21:13 +0000 |
commit | 2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc (patch) | |
tree | a9262231804ebf8b7e42d5eb8026c19f194c45d3 /src | |
parent | 1b14f49ff297a29c489dd184ee8f1f3c885a1b33 (diff) | |
download | scala-2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc.tar.gz scala-2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc.tar.bz2 scala-2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc.zip |
Closes #2918. Review by moors.
Diffstat (limited to 'src')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Types.scala | 31 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Typers.scala | 2 |
2 files changed, 30 insertions, 3 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Types.scala b/src/compiler/scala/tools/nsc/symtab/Types.scala index b1842176dd..3db5be2e4e 100644 --- a/src/compiler/scala/tools/nsc/symtab/Types.scala +++ b/src/compiler/scala/tools/nsc/symtab/Types.scala @@ -73,6 +73,7 @@ trait Types extends reflect.generic.Types { self: SymbolTable => private final val LogPendingSubTypesThreshold = 50 private final val LogPendingBaseTypesThreshold = 50 + private final val LogVolatileThreshold = 50 /** A don't care value for the depth parameter in lubs/glbs and related operations */ private final val AnyDepth = -3 @@ -1532,6 +1533,9 @@ trait Types extends reflect.generic.Types { self: SymbolTable => } } + private var volatileRecursions: Int = 0 + private var pendingVolatiles = new collection.mutable.HashSet[Symbol] + /** A class for named types of the form * `<prefix>.<sym.name>[args]' * Cannot be created directly; one should always use `typeRef' @@ -1560,9 +1564,32 @@ trait Types extends reflect.generic.Types { self: SymbolTable => sym.isAbstractType && (bounds.hi.typeSymbol isSubClass SingletonClass) } - override def isVolatile: Boolean = + override def isVolatile: Boolean = { sym.isAliasType && normalize.isVolatile || - sym.isAbstractType && bounds.hi.isVolatile + sym.isAbstractType && { + // need to be careful not to fall into an infinite recursion here + // because volatile checking is done before all cycles are detected. + // the case to avoid is an abstract type directly or + // indirectly upper-bounded by itself. See #2918 + try { + volatileRecursions += 1 + if (volatileRecursions < LogVolatileThreshold) + bounds.hi.isVolatile + else if (pendingVolatiles contains sym) + true // we can return true here, because a cycle will be detected + // here afterwards and an error will result anyway. + else + try { + pendingVolatiles += sym + bounds.hi.isVolatile + } finally { + pendingVolatiles -= sym + } + } finally { + volatileRecursions -= 1 + } + } + } override val isTrivial: Boolean = !sym.isTypeParameter && pre.isTrivial && args.forall(_.isTrivial) diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 720994dff3..1356fbf7f9 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3641,7 +3641,7 @@ trait Typers { self: Analyzer => if (defSym.exists && impSym.exists) { // imported symbols take precedence over package-owned symbols in different - // compilation units. Defined symbols take precedence over errenous imports. + // compilation units. Defined symbols take precedence over erroneous imports. if (defSym.definedInPackage && (!currentRun.compiles(defSym) || (context.unit ne null) && defSym.sourceFile != context.unit.source.file)) |