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 /src/compiler | |
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.
Diffstat (limited to 'src/compiler')
-rw-r--r-- | src/compiler/scala/tools/nsc/symtab/Definitions.scala | 7 | ||||
-rw-r--r-- | src/compiler/scala/tools/nsc/transform/Erasure.scala | 9 |
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 |