summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2010-03-13 20:21:13 +0000
committerMartin Odersky <odersky@gmail.com>2010-03-13 20:21:13 +0000
commit2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc (patch)
treea9262231804ebf8b7e42d5eb8026c19f194c45d3 /src/compiler/scala
parent1b14f49ff297a29c489dd184ee8f1f3c885a1b33 (diff)
downloadscala-2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc.tar.gz
scala-2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc.tar.bz2
scala-2f3988dd7cd72dcc09204a0559d2f85e3d2eb4cc.zip
Closes #2918. Review by moors.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Types.scala31
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala2
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
* `&lt;prefix&gt;.&lt;sym.name&gt;[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))