summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdriaan Moors <adriaan.moors@typesafe.com>2016-03-17 09:45:42 -0700
committerAdriaan Moors <adriaan.moors@typesafe.com>2016-03-26 22:54:03 -0700
commit8a7919bb543ee152dab9874abc37f9bbaac7eeaf (patch)
tree7a0e417d13b9aee24362c15894357a8b0d49e5d2
parent8433b6fa0e86dfdcd3db31b97844b14d65e45359 (diff)
downloadscala-8a7919bb543ee152dab9874abc37f9bbaac7eeaf.tar.gz
scala-8a7919bb543ee152dab9874abc37f9bbaac7eeaf.tar.bz2
scala-8a7919bb543ee152dab9874abc37f9bbaac7eeaf.zip
Refactoring. Decakify TypeAdaptingTransformer
-rw-r--r--src/compiler/scala/tools/nsc/transform/Delambdafy.scala4
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala5
-rw-r--r--src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala90
3 files changed, 47 insertions, 52 deletions
diff --git a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
index 8a318b194f..3262dd9202 100644
--- a/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
+++ b/src/compiler/scala/tools/nsc/transform/Delambdafy.scala
@@ -172,8 +172,8 @@ abstract class Delambdafy extends Transform with TypingTransformers with ast.Tre
if (resTpOk && isReferenceType(samResultType) && functionResultType <:< samResultType) functionResultType
else samResultType
- val typeAdapter = new TypeAdapter { val typer = localTyper }
- import typeAdapter.{box, unbox, cast, adaptToType, unboxValueClass}
+ val typeAdapter = new TypeAdapter { def typedPos(pos: Position)(tree: Tree): Tree = localTyper.typedPos(pos)(tree) }
+ import typeAdapter.{adaptToType, unboxValueClass}
val targetParams = target.paramss.head
val numCaptures = targetParams.length - functionParamTypes.length
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index 58be6b53a0..be6316cc57 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -578,8 +578,9 @@ abstract class Erasure extends AddInterfaces
}
/** The modifier typer which retypes with erased types. */
- class Eraser(_context: Context) extends Typer(_context) with TypeAdapter {
- val typer = this.asInstanceOf[analyzer.Typer]
+ class Eraser(_context: Context) extends Typer(_context) {
+ val typeAdapter = new TypeAdapter { def typedPos(pos: Position)(tree: Tree): Tree = Eraser.this.typedPos(pos)(tree) }
+ import typeAdapter._
override protected def stabilize(tree: Tree, pre: Type, mode: Mode, pt: Type): Tree = tree
diff --git a/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala b/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala
index 246d9ebf3f..596091f75d 100644
--- a/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala
+++ b/src/compiler/scala/tools/nsc/transform/TypeAdaptingTransformer.scala
@@ -7,62 +7,58 @@ import scala.tools.nsc.ast.TreeDSL
/**
* A trait usable by transforms that need to adapt trees of one type to another type
*/
-trait TypeAdaptingTransformer {
- self: TreeDSL =>
-
- val analyzer: typechecker.Analyzer { val global: self.global.type }
-
- trait TypeAdapter {
- val typer: analyzer.Typer
+trait TypeAdaptingTransformer { self: TreeDSL =>
+ abstract class TypeAdapter {
import global._
import definitions._
- import CODE._
+
+ def typedPos(pos: Position)(tree: Tree): Tree
private def isSafelyRemovableUnbox(fn: Tree, arg: Tree): Boolean = {
currentRun.runDefinitions.isUnbox(fn.symbol) && {
val cls = arg.tpe.typeSymbol
- (cls == definitions.NullClass) || isBoxedValueClass(cls)
+ (cls == NullClass) || isBoxedValueClass(cls)
}
}
- private def isPrimitiveValueType(tpe: Type) = isPrimitiveValueClass(tpe.typeSymbol)
- def isPrimitiveValueMember(sym: Symbol) = isPrimitiveValueClass(sym.owner)
- def isMethodTypeWithEmptyParams(tpe: Type) = tpe.isInstanceOf[MethodType] && tpe.params.isEmpty
- def applyMethodWithEmptyParams(qual: Tree) = Apply(qual, List()) setPos qual.pos setType qual.tpe.resultType
+ private def isPrimitiveValueType(tpe: Type) = isPrimitiveValueClass(tpe.typeSymbol)
+ final def isPrimitiveValueMember(sym: Symbol) = isPrimitiveValueClass(sym.owner)
+ final def isMethodTypeWithEmptyParams(tpe: Type) = tpe.isInstanceOf[MethodType] && tpe.params.isEmpty
+ final def applyMethodWithEmptyParams(qual: Tree) = Apply(qual, List()) setPos qual.pos setType qual.tpe.resultType
+
+ import CODE._
/** Box `tree` of unboxed type */
- def box(tree: Tree): Tree = tree match {
+ final def box(tree: Tree): Tree = tree match {
case LabelDef(_, _, _) =>
val ldef = deriveLabelDef(tree)(box)
ldef setType ldef.rhs.tpe
case _ =>
val tree1 = tree.tpe match {
- case ErasedValueType(clazz, _) =>
- New(clazz, cast(tree, underlyingOfValueClass(clazz)))
- case _ =>
- tree.tpe.typeSymbol match {
- case UnitClass =>
- if (treeInfo isExprSafeToInline tree) REF(BoxedUnit_UNIT)
- else BLOCK(tree, REF(BoxedUnit_UNIT))
- case NothingClass => tree // a non-terminating expression doesn't need boxing
- case x =>
- assert(x != ArrayClass)
- tree match {
- /* Can't always remove a Box(Unbox(x)) combination because the process of boxing x
- * may lead to throwing an exception.
- *
- * This is important for specialization: calls to the super constructor should not box/unbox specialized
- * fields (see TupleX). (ID)
- */
- case Apply(boxFun, List(arg)) if isSafelyRemovableUnbox(tree, arg) =>
- log(s"boxing an unbox: ${tree.symbol} -> ${arg.tpe}")
- arg
- case _ =>
- (REF(currentRun.runDefinitions.boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectTpe
- }
- }
+ case ErasedValueType(clazz, _) => New(clazz, cast(tree, underlyingOfValueClass(clazz)))
+ case _ => tree.tpe.typeSymbol match {
+ case UnitClass =>
+ if (treeInfo isExprSafeToInline tree) REF(BoxedUnit_UNIT)
+ else BLOCK(tree, REF(BoxedUnit_UNIT))
+ case NothingClass => tree // a non-terminating expression doesn't need boxing
+ case x =>
+ assert(x != ArrayClass)
+ tree match {
+ /* Can't always remove a Box(Unbox(x)) combination because the process of boxing x
+ * may lead to throwing an exception.
+ *
+ * This is important for specialization: calls to the super constructor should not box/unbox specialized
+ * fields (see TupleX). (ID)
+ */
+ case Apply(boxFun, List(arg)) if isSafelyRemovableUnbox(tree, arg) =>
+ log(s"boxing an unbox: ${tree.symbol} -> ${arg.tpe}")
+ arg
+ case _ =>
+ (REF(currentRun.runDefinitions.boxMethod(x)) APPLY tree) setPos (tree.pos) setType ObjectTpe
+ }
+ }
}
- typer.typedPos(tree.pos)(tree1)
+ typedPos(tree.pos)(tree1)
}
/** Unbox `tree` of boxed type to expected type `pt`.
@@ -71,7 +67,7 @@ trait TypeAdaptingTransformer {
* @param pt the expected type.
* @return the unboxed tree
*/
- def unbox(tree: Tree, pt: Type): Tree = tree match {
+ final def unbox(tree: Tree, pt: Type): Tree = tree match {
case LabelDef(_, _, _) =>
val ldef = deriveLabelDef(tree)(unbox(_, pt))
ldef setType ldef.rhs.tpe
@@ -89,10 +85,10 @@ trait TypeAdaptingTransformer {
Apply(currentRun.runDefinitions.unboxMethod(pt.typeSymbol), tree)
}
}
- typer.typedPos(tree.pos)(tree1)
+ typedPos(tree.pos)(tree1)
}
- def unboxValueClass(tree: Tree, clazz: Symbol, underlying: Type): Tree =
+ final def unboxValueClass(tree: Tree, clazz: Symbol, underlying: Type): Tree =
if (tree.tpe.typeSymbol == NullClass && isPrimitiveValueClass(underlying.typeSymbol)) {
// convert `null` directly to underlying type, as going via the unboxed type would yield a NPE (see SI-5866)
unbox(tree, underlying)
@@ -105,13 +101,12 @@ trait TypeAdaptingTransformer {
*/
final def cast(tree: Tree, pt: Type): Tree = {
if (settings.debug && (tree.tpe ne null) && !(tree.tpe =:= ObjectTpe)) {
- def word = (
+ def word =
if (tree.tpe <:< pt) "upcast"
else if (pt <:< tree.tpe) "downcast"
else if (pt weak_<:< tree.tpe) "coerce"
else if (tree.tpe weak_<:< pt) "widen"
else "cast"
- )
log(s"erasure ${word}s from ${tree.tpe} to $pt")
}
if (pt =:= UnitTpe) {
@@ -123,7 +118,8 @@ trait TypeAdaptingTransformer {
val needsExtraCast = isPrimitiveValueType(tree.tpe.typeArgs.head) && !isPrimitiveValueType(pt.typeArgs.head)
val tree1 = if (needsExtraCast) gen.mkRuntimeCall(nme.toObjectArray, List(tree)) else tree
gen.mkAttributedCast(tree1, pt)
- } else gen.mkAttributedCast(tree, pt)
+ } else if (samMatchingFunction(tree, pt).exists) tree setType pt // SAM <:< FunctionN if sam is convertible to said function
+ else gen.mkAttributedCast(tree, pt)
}
/** Adapt `tree` to expected type `pt`.
@@ -147,9 +143,7 @@ trait TypeAdaptingTransformer {
if (gotPrimitiveVC && !expectedPrimitiveVC) adaptToType(box(tree), pt)
else if (!gotPrimitiveVC && expectedPrimitiveVC) adaptToType(unbox(tree, pt), pt)
- else if (samMatchingFunction(tree, pt).exists) {
- tree setType pt
- } else cast(tree, pt)
+ else cast(tree, pt)
}
}
}