diff options
author | Eugene Burmako <xeno.by@gmail.com> | 2014-01-19 22:25:20 +0300 |
---|---|---|
committer | Eugene Burmako <xeno.by@gmail.com> | 2014-01-20 09:48:13 +0300 |
commit | 35300b46311c93c692744701275dbb4807f851e2 (patch) | |
tree | 492e5202d3f52afd60c9ee419c3e1a1a98098fed | |
parent | 936d60a2621088ba463a44c2f2d6450986022169 (diff) | |
download | scala-35300b46311c93c692744701275dbb4807f851e2.tar.gz scala-35300b46311c93c692744701275dbb4807f851e2.tar.bz2 scala-35300b46311c93c692744701275dbb4807f851e2.zip |
introduces failsafe against endless type printing
The parent commit works around a particular problem that led to a compiler
freeze in SI-8158, whereas this commit introduces a general solution -
a cache that tracks all types that we've recursed into during printing.
I can't immediately come up with an example of a type that would be caught
by this safety net, but unknown unknowns are the worst of them all, so why not
guard against them while we can.
3 files changed, 16 insertions, 1 deletions
diff --git a/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala b/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala index ebc4394d25..b08aabef85 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeToStrings.scala @@ -3,6 +3,8 @@ package reflect package internal package tpe +import scala.collection.mutable.HashSet + private[internal] trait TypeToStrings { self: SymbolTable => @@ -14,8 +16,15 @@ private[internal] trait TypeToStrings { def tostringRecursions = _tostringRecursions def tostringRecursions_=(value: Int) = _tostringRecursions = value + private var _tostringSubjects = HashSet[Type]() + def tostringSubjects = _tostringSubjects + protected def typeToString(tpe: Type): String = - if (tostringRecursions >= maxTostringRecursions) { + if (tostringSubjects contains tpe) { + // handles self-referential anonymous classes and who knows what else + "..." + } + else if (tostringRecursions >= maxTostringRecursions) { devWarning("Exceeded recursion depth attempting to print " + util.shortClassOfInstance(tpe)) if (settings.debug) (new Throwable).printStackTrace @@ -25,8 +34,10 @@ private[internal] trait TypeToStrings { else try { tostringRecursions += 1 + tostringSubjects += tpe tpe.safeToString } finally { + tostringSubjects -= tpe tostringRecursions -= 1 } } diff --git a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala index 6b3985d434..ac6dd0783d 100644 --- a/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala +++ b/src/reflect/scala/reflect/runtime/JavaUniverseForce.scala @@ -42,6 +42,7 @@ trait JavaUniverseForce { self: runtime.JavaUniverse => // inaccessible: this._glbResults // inaccessible: this._indent // inaccessible: this._tostringRecursions + // inaccessible: this._tostringSubjects // inaccessible: this.atomicIds // inaccessible: this.atomicExistentialIds // inaccessible: this._recursionTable diff --git a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala index de78e527a7..12ada07a56 100644 --- a/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala +++ b/src/reflect/scala/reflect/runtime/SynchronizedTypes.scala @@ -85,6 +85,9 @@ private[reflect] trait SynchronizedTypes extends internal.Types { self: SymbolTa override def tostringRecursions = _tostringRecursions.get override def tostringRecursions_=(value: Int) = _tostringRecursions.set(value) + private lazy val _tostringSubjects = mkThreadLocalStorage(new mutable.HashSet[Type]) + override def tostringSubjects = _tostringSubjects.get + /* The idea of caches is as follows. * When in reflexive mode, a cache is either null, or one sentinal * value representing undefined or the final defined |