summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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
+ }
+}