summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2015-02-18 15:25:29 -0800
committerAdriaan Moors <adriaan.moors@typesafe.com>2015-02-18 15:25:29 -0800
commit9a3ea24596c9a929ad821bf18bb1bd73e569bc0a (patch)
treed2a2e196f0db07097b7e03258937c3790a37478f
parent7a872f4ed261947070a2937982efa9f35684a8dd (diff)
parente53165c4a3f1551624d477efd37fbb189fb750d5 (diff)
downloadscala-9a3ea24596c9a929ad821bf18bb1bd73e569bc0a.tar.gz
scala-9a3ea24596c9a929ad821bf18bb1bd73e569bc0a.tar.bz2
scala-9a3ea24596c9a929ad821bf18bb1bd73e569bc0a.zip
Merge pull request #4329 from adriaanm/followup-4235
Simpler & Scala.js-friendly `ClassTag.unapply`
-rwxr-xr-xbuild.xml12
-rw-r--r--src/library/scala/reflect/ClassTag.scala39
-rw-r--r--test/junit/scala/reflect/ClassTag.scala29
3 files changed, 50 insertions, 30 deletions
diff --git a/build.xml b/build.xml
index f8e44c6f5c..5f6b04b8e4 100755
--- a/build.xml
+++ b/build.xml
@@ -1445,15 +1445,7 @@ TODO:
<stopwatch name="quick.sbt-interface.timer" action="total"/>
</target>
- <target name="test.junit.init" depends="quick.done">
- <uptodate property="test.junit.available" targetfile="${build-junit.dir}/test-compile.complete">
- <srcfiles dir="${test.junit.src}">
- <include name="**/*.scala"/>
- </srcfiles>
- </uptodate>
- </target>
-
- <target name="test.junit.comp" depends="test.junit.init, quick.done" unless="test.junit.available">
+ <target name="test.junit.comp" depends="pack.done">
<stopwatch name="test.junit.compiler.timer"/>
<mkdir dir="${test.junit.classes}"/>
<scalacfork
@@ -1469,7 +1461,7 @@ TODO:
<stopwatch name="test.junit.compiler.timer" action="total"/>
</target>
- <target name="test.junit" depends="test.junit.comp, test.junit.init">
+ <target name="test.junit" depends="test.junit.comp">
<stopwatch name="test.junit.timer"/>
<mkdir dir="${test.junit.classes}"/>
<echo message="Note: details of failed tests will be output to ${build-junit.dir}"/>
diff --git a/src/library/scala/reflect/ClassTag.scala b/src/library/scala/reflect/ClassTag.scala
index 2f4aa9cb84..9dd96183da 100644
--- a/src/library/scala/reflect/ClassTag.scala
+++ b/src/library/scala/reflect/ClassTag.scala
@@ -69,22 +69,22 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
* `SomeExtractor(...)` is turned into `ct(SomeExtractor(...))` if `T` in `SomeExtractor.unapply(x: T)`
* is uncheckable, but we have an instance of `ClassTag[T]`.
*/
- def unapply(x: Any): Option[T] = x match {
- case null => None
- case b: Byte => unapply(b)
- case s: Short => unapply(s)
- case c: Char => unapply(c)
- case i: Int => unapply(i)
- case l: Long => unapply(l)
- case f: Float => unapply(f)
- case d: Double => unapply(d)
- case b: Boolean => unapply(b)
- case u: Unit => unapply(u)
- case a: Any => unapplyImpl(a)
- }
+ def unapply(x: Any): Option[T] =
+ if (null != x && (
+ (runtimeClass.isInstance(x))
+ || (x.isInstanceOf[Byte] && runtimeClass.isAssignableFrom(classOf[Byte]))
+ || (x.isInstanceOf[Short] && runtimeClass.isAssignableFrom(classOf[Short]))
+ || (x.isInstanceOf[Char] && runtimeClass.isAssignableFrom(classOf[Char]))
+ || (x.isInstanceOf[Int] && runtimeClass.isAssignableFrom(classOf[Int]))
+ || (x.isInstanceOf[Long] && runtimeClass.isAssignableFrom(classOf[Long]))
+ || (x.isInstanceOf[Float] && runtimeClass.isAssignableFrom(classOf[Float]))
+ || (x.isInstanceOf[Double] && runtimeClass.isAssignableFrom(classOf[Double]))
+ || (x.isInstanceOf[Boolean] && runtimeClass.isAssignableFrom(classOf[Boolean]))
+ || (x.isInstanceOf[Unit] && runtimeClass.isAssignableFrom(classOf[Unit])))
+ ) Some(x.asInstanceOf[T])
+ else None
- // TODO: Inline the bodies of these into the Any-accepting unapply overload above and delete them.
- // This cannot be done until at least 2.12.0 for reasons of binary compatibility
+ // TODO: deprecate overloads in 2.12.0, remove in 2.13.0
def unapply(x: Byte) : Option[T] = unapplyImpl(x, classOf[Byte])
def unapply(x: Short) : Option[T] = unapplyImpl(x, classOf[Short])
def unapply(x: Char) : Option[T] = unapplyImpl(x, classOf[Char])
@@ -94,11 +94,10 @@ trait ClassTag[T] extends ClassManifestDeprecatedApis[T] with Equals with Serial
def unapply(x: Double) : Option[T] = unapplyImpl(x, classOf[Double])
def unapply(x: Boolean) : Option[T] = unapplyImpl(x, classOf[Boolean])
def unapply(x: Unit) : Option[T] = unapplyImpl(x, classOf[Unit])
-
- private[this] def unapplyImpl(x: Any, alternative: jClass[_] = null): Option[T] = {
- val conforms = runtimeClass.isAssignableFrom(x.getClass) || (alternative != null && runtimeClass.isAssignableFrom(alternative))
- if (conforms) Some(x.asInstanceOf[T]) else None
- }
+
+ private[this] def unapplyImpl(x: Any, primitiveCls: java.lang.Class[_]): Option[T] =
+ if (runtimeClass.isInstance(x) || runtimeClass.isAssignableFrom(primitiveCls)) Some(x.asInstanceOf[T])
+ else None
// case class accessories
override def canEqual(x: Any) = x.isInstanceOf[ClassTag[_]]
diff --git a/test/junit/scala/reflect/ClassTag.scala b/test/junit/scala/reflect/ClassTag.scala
new file mode 100644
index 0000000000..90cc981fc1
--- /dev/null
+++ b/test/junit/scala/reflect/ClassTag.scala
@@ -0,0 +1,29 @@
+package scala.reflect
+
+import org.junit.Test
+import org.junit.Assert._
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+import scala.tools.testing.AssertUtil._
+
+class Misc
+
+@RunWith(classOf[JUnit4])
+class ClassTagTest {
+ def checkNotString[A: ClassTag](a: Any) = a match { case x: String => false case x: A => true case _ => false }
+ def checkNotInt[A: ClassTag](a: Any) = a match { case x: Int => false case x: A => true case _ => false }
+ def checkNotLong[A: ClassTag](a: Any) = a match { case x: Long => false case x: A => true case _ => false }
+
+ @Test def checkMisc = assertTrue(checkNotString[Misc](new Misc))
+ @Test def checkString = assertTrue(checkNotInt[String] ("woele"))
+ @Test def checkByte = assertTrue(checkNotInt[Byte] (0.toByte))
+ @Test def checkShort = assertTrue(checkNotInt[Short] (0.toShort))
+ @Test def checkChar = assertTrue(checkNotInt[Char] (0.toChar))
+ @Test def checkInt = assertTrue(checkNotLong[Int] (0.toInt))
+ @Test def checkLong = assertTrue(checkNotInt[Long] (0.toLong))
+ @Test def checkFloat = assertTrue(checkNotInt[Float] (0.toFloat))
+ @Test def checkDouble = assertTrue(checkNotInt[Double] (0.toDouble))
+ @Test def checkBoolean = assertTrue(checkNotInt[Boolean](false))
+ @Test def checkUnit = assertTrue(checkNotInt[Unit] ({}))
+} \ No newline at end of file