diff options
-rw-r--r-- | src/library/scala/runtime/ScalaRunTime.scala | 14 | ||||
-rw-r--r-- | test/files/run/predef-cycle.scala | 71 | ||||
-rw-r--r-- | test/junit/scala/runtime/ScalaRunTimeTest.scala | 70 |
3 files changed, 144 insertions, 11 deletions
diff --git a/src/library/scala/runtime/ScalaRunTime.scala b/src/library/scala/runtime/ScalaRunTime.scala index 1d8fe5e9ad..4fee6d75a3 100644 --- a/src/library/scala/runtime/ScalaRunTime.scala +++ b/src/library/scala/runtime/ScalaRunTime.scala @@ -34,21 +34,13 @@ object ScalaRunTime { clazz.isArray && (atLevel == 1 || isArrayClass(clazz.getComponentType, atLevel - 1)) def isValueClass(clazz: jClass[_]) = clazz.isPrimitive() - def isTuple(x: Any) = x != null && tupleNames(x.getClass.getName) + + // includes specialized subclasses and future proofed against hypothetical TupleN (for N > 22) + def isTuple(x: Any) = x != null && x.getClass.getName.startsWith("scala.Tuple") def isAnyVal(x: Any) = x match { case _: Byte | _: Short | _: Char | _: Int | _: Long | _: Float | _: Double | _: Boolean | _: Unit => true case _ => false } - // Avoiding boxing which messes up the specialized tests. Don't ask. - private val tupleNames = { - var i = 22 - var names: List[String] = Nil - while (i >= 1) { - names ::= ("scala.Tuple" + String.valueOf(i)) - i -= 1 - } - names.toSet - } /** Return the class object representing an array with element class `clazz`. */ diff --git a/test/files/run/predef-cycle.scala b/test/files/run/predef-cycle.scala new file mode 100644 index 0000000000..ab147688bc --- /dev/null +++ b/test/files/run/predef-cycle.scala @@ -0,0 +1,71 @@ +class Force { + val t1 = new Thread { + override def run() { + scala.`package` + } + } + val t2 = new Thread { + override def run() { + scala.Predef + } + } + t1.start() + t2.start() + t1.join() + t2.join() +} + +object Test { + def main(args: Array[String]) { + new Force() + } +} + +/* Was deadlocking: +"Thread-2" prio=5 tid=7f9637268000 nid=0x119601000 in Object.wait() [119600000] + java.lang.Thread.State: RUNNABLE + at scala.Predef$.<init>(Predef.scala:90) + at scala.Predef$.<clinit>(Predef.scala) + at Force$$anon$2.run(predef-cycle.scala:10) + +"Thread-1" prio=5 tid=7f9637267800 nid=0x1194fe000 in Object.wait() [1194fb000] + java.lang.Thread.State: RUNNABLE + at scala.collection.immutable.Set$Set4.$plus(Set.scala:127) + at scala.collection.immutable.Set$Set4.$plus(Set.scala:121) + at scala.collection.mutable.SetBuilder.$plus$eq(SetBuilder.scala:24) + at scala.collection.mutable.SetBuilder.$plus$eq(SetBuilder.scala:22) + at scala.collection.generic.Growable$$anonfun$$plus$plus$eq$1.apply(Growable.scala:48) + at scala.collection.generic.Growable$$anonfun$$plus$plus$eq$1.apply(Growable.scala:48) + at scala.collection.immutable.List.foreach(List.scala:318) + at scala.collection.generic.Growable$class.$plus$plus$eq(Growable.scala:48) + at scala.collection.mutable.SetBuilder.$plus$plus$eq(SetBuilder.scala:22) + at scala.collection.TraversableLike$class.to(TraversableLike.scala:629) + at scala.collection.AbstractTraversable.to(Traversable.scala:105) + at scala.collection.TraversableOnce$class.toSet(TraversableOnce.scala:267) + at scala.collection.AbstractTraversable.toSet(Traversable.scala:105) + at scala.runtime.ScalaRunTime$.<init>(ScalaRunTime.scala:50) + at scala.runtime.ScalaRunTime$.<clinit>(ScalaRunTime.scala) + at scala.collection.mutable.HashTable$HashUtils$class.elemHashCode(HashTable.scala) + at scala.collection.mutable.HashMap.elemHashCode(HashMap.scala:39) + at scala.collection.mutable.HashTable$class.findOrAddEntry(HashTable.scala:161) + at scala.collection.mutable.HashMap.findOrAddEntry(HashMap.scala:39) + at scala.collection.mutable.HashMap.put(HashMap.scala:75) + at scala.collection.mutable.HashMap.update(HashMap.scala:80) + at scala.sys.SystemProperties$.addHelp(SystemProperties.scala:64) + at scala.sys.SystemProperties$.bool(SystemProperties.scala:68) + at scala.sys.SystemProperties$.noTraceSupression$lzycompute(SystemProperties.scala:80) + - locked <7b8b0e228> (a scala.sys.SystemProperties$) + at scala.sys.SystemProperties$.noTraceSupression(SystemProperties.scala:80) + at scala.util.control.NoStackTrace$.<init>(NoStackTrace.scala:31) + at scala.util.control.NoStackTrace$.<clinit>(NoStackTrace.scala) + at scala.util.control.NoStackTrace$class.fillInStackTrace(NoStackTrace.scala:22) + at scala.util.control.BreakControl.fillInStackTrace(Breaks.scala:93) + at java.lang.Throwable.<init>(Throwable.java:181) + at scala.util.control.BreakControl.<init>(Breaks.scala:93) + at scala.util.control.Breaks.<init>(Breaks.scala:28) + at scala.collection.Traversable$.<init>(Traversable.scala:96) + at scala.collection.Traversable$.<clinit>(Traversable.scala) + at scala.package$.<init>(package.scala:46) + at scala.package$.<clinit>(package.scala) + at Force$$anon$1.run(predef-cycle.scala:4) + */
\ No newline at end of file diff --git a/test/junit/scala/runtime/ScalaRunTimeTest.scala b/test/junit/scala/runtime/ScalaRunTimeTest.scala new file mode 100644 index 0000000000..9da197c71a --- /dev/null +++ b/test/junit/scala/runtime/ScalaRunTimeTest.scala @@ -0,0 +1,70 @@ +package scala.runtime + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +/** Tests for the private class DefaultPromise */ +@RunWith(classOf[JUnit4]) +class ScalaRunTimeTest { + @Test + def testIsTuple() { + import ScalaRunTime.isTuple + def check(v: Any) = { + assertTrue(v.toString, isTuple(v)) + } + + val s = "" + check(Tuple1(s)) + check((s, s)) + check((s, s, s)) + check((s, s, s, s)) + check((s, s, s, s, s)) + check((s, s, s, s, s, s)) + check((s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + check((s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s, s)) + + // some specialized variants will have mangled classnames + check(Tuple1(0)) + check((0, 0)) + check((0, 0, 0)) + check((0, 0, 0, 0)) + check((0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + check((0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)) + + case class C() + val c = new C() + assertFalse(c.toString, isTuple(c)) + } +} |