summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala9
2 files changed, 12 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