summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-01-11 20:08:47 +0000
committerPaul Phillips <paulp@improving.org>2011-01-11 20:08:47 +0000
commit566fefb05abe31e90f765d1fb0a89b264302d9ce (patch)
tree28be1b3d6c4b862ff9a24b6dd665cbb8df1b68a9
parent5f40fe0456238a8c58d05e58cd61a960f9a107a7 (diff)
downloadscala-566fefb05abe31e90f765d1fb0a89b264302d9ce.tar.gz
scala-566fefb05abe31e90f765d1fb0a89b264302d9ce.tar.bz2
scala-566fefb05abe31e90f765d1fb0a89b264302d9ce.zip
In r22807 an optimization was added to remove B...
In r22807 an optimization was added to remove Box(Unbox(x)) combinations. It turns out that without this in place, an expression like "x".asInstanceOf[Int] will no longer throw an exception. Refined the optimization. Closes #4148, review by dragos.
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala9
-rw-r--r--test/files/run/bug4148.check3
-rw-r--r--test/files/run/bug4148.scala9
4 files changed, 24 insertions, 4 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index 0eb58e3ad2..26b4f88f0c 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -629,6 +629,9 @@ trait Definitions extends reflect.generic.StandardDefinitions {
val unboxMethod = new HashMap[Symbol, Symbol] // Type -> Method
val boxMethod = new HashMap[Symbol, Symbol] // Type -> Method
val primitiveCompanions = new mutable.HashSet[Symbol] // AnyVal -> Companion
+
+ lazy val boxedClassValues = boxedClass.values.toSet
+
/** Maps a companion object like scala.Int to scala.runtime.Int. */
lazy val runtimeCompanions = (primitiveCompanions map { sym =>
sym -> getModule("scala.runtime." + sym.name)
@@ -799,6 +802,10 @@ trait Definitions extends reflect.generic.StandardDefinitions {
def isValueClass(sym: Symbol): Boolean =
(sym eq UnitClass) || (boxedClass contains sym)
+ /** Is symbol a boxed value class, e.g. java.lang.Integer? */
+ def isBoxedValueClass(sym: Symbol): Boolean =
+ (sym eq BoxedUnitClass) || boxedClassValues(sym)
+
/** If symbol is a value class or a boxed value class, return the value class: otherwise NoSymbol. */
def unboxedValueClass(sym: Symbol): Symbol =
if (isValueClass(sym)) sym
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 1df0b5bf3b..fa5f899da0 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -440,7 +440,6 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
/** The modifier typer which retypes with erased types. */
class Eraser(context: Context) extends Typer(context) {
-
/** Box `tree' of unboxed type */
private def box(tree: Tree): Tree = tree match {
case LabelDef(name, params, rhs) =>
@@ -454,9 +453,11 @@ abstract class Erasure extends AddInterfaces with typechecker.Analyzer with ast.
case x =>
assert(x != ArrayClass)
tree match {
- case Apply(boxFun, List(arg)) if (isUnbox(tree.symbol)) =>
- log("boxing an unbox: " + tree)
- log("replying with " + arg)
+ /** Can't always remove a Box(Unbox(x)) combination because the process of boxing x
+ * may lead to throwing an exception.
+ */
+ case Apply(boxFun, List(arg)) if isUnbox(tree.symbol) && isBoxedValueClass(arg.tpe.typeSymbol) =>
+ log("boxing an unbox: " + tree + " and replying with " + arg)
arg
case _ =>
(REF(boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectClass.tpe
diff --git a/test/files/run/bug4148.check b/test/files/run/bug4148.check
new file mode 100644
index 0000000000..544b0d19d1
--- /dev/null
+++ b/test/files/run/bug4148.check
@@ -0,0 +1,3 @@
+cce1
+5
+100
diff --git a/test/files/run/bug4148.scala b/test/files/run/bug4148.scala
new file mode 100644
index 0000000000..a7d181268d
--- /dev/null
+++ b/test/files/run/bug4148.scala
@@ -0,0 +1,9 @@
+object Test {
+ val x1 = try { "aaa".asInstanceOf[Int] } catch { case _ => "cce1" }
+ val x2 = try { (5: Any).asInstanceOf[Int] } catch { case _ => "cce2" }
+ val x3 = try { (new java.lang.Short(100.toShort).asInstanceOf[Int]) } catch { case _ => "cce3" }
+
+ def main(args: Array[String]): Unit = {
+ List(x1, x2, x3) foreach println
+ }
+}