diff options
author | Paul Phillips <paulp@improving.org> | 2011-01-11 20:08:47 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-01-11 20:08:47 +0000 |
commit | 566fefb05abe31e90f765d1fb0a89b264302d9ce (patch) | |
tree | 28be1b3d6c4b862ff9a24b6dd665cbb8df1b68a9 | |
parent | 5f40fe0456238a8c58d05e58cd61a960f9a107a7 (diff) | |
download | scala-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.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 9 | ||||
-rw-r--r-- | test/files/run/bug4148.check | 3 | ||||
-rw-r--r-- | test/files/run/bug4148.scala | 9 |
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 + } +} |