aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/transform/Erasure.scala
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/transform/Erasure.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/transform/Erasure.scala77
1 files changed, 62 insertions, 15 deletions
diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
index 069176111..5dd2e512b 100644
--- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala
+++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala
@@ -13,6 +13,7 @@ import core.StdNames._
import core.NameOps._
import core.Decorators._
import core.Constants._
+import core.Definitions._
import typer.NoChecking
import typer.ProtoTypes._
import typer.ErrorReporting._
@@ -36,9 +37,17 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
def transform(ref: SingleDenotation)(implicit ctx: Context): SingleDenotation = ref match {
case ref: SymDenotation =>
+ def isCompacted(sym: Symbol) =
+ sym.isAnonymousFunction && {
+ sym.info(ctx.withPhase(ctx.phase.next)) match {
+ case MethodType(nme.ALLARGS :: Nil, _) => true
+ case _ => false
+ }
+ }
+
assert(ctx.phase == this, s"transforming $ref at ${ctx.phase}")
if (ref.symbol eq defn.ObjectClass) {
- // Aftre erasure, all former Any members are now Object members
+ // After erasure, all former Any members are now Object members
val ClassInfo(pre, _, ps, decls, selfInfo) = ref.info
val extendedScope = decls.cloneScope
for (decl <- defn.AnyClass.classInfo.decls)
@@ -59,7 +68,10 @@ class Erasure extends Phase with DenotTransformer { thisTransformer =>
val oldInfo = ref.info
val newInfo = transformInfo(ref.symbol, oldInfo)
val oldFlags = ref.flags
- val newFlags = ref.flags &~ Flags.HasDefaultParams // HasDefaultParams needs to be dropped because overriding might become overloading
+ val newFlags =
+ if (oldSymbol.is(Flags.TermParam) && isCompacted(oldSymbol.owner)) oldFlags &~ Flags.Param
+ else oldFlags &~ Flags.HasDefaultParams // HasDefaultParams needs to be dropped because overriding might become overloading
+
// TODO: define derivedSymDenotation?
if ((oldSymbol eq newSymbol) && (oldOwner eq newOwner) && (oldInfo eq newInfo) && (oldFlags == newFlags)) ref
else {
@@ -331,8 +343,20 @@ object Erasure extends TypeTestsCasts{
* e.m -> e.[]m if `m` is an array operation other than `clone`.
*/
override def typedSelect(tree: untpd.Select, pt: Type)(implicit ctx: Context): Tree = {
- val sym = tree.symbol
- assert(sym.exists, tree.show)
+ val oldSym = tree.symbol
+ assert(oldSym.exists)
+ val oldOwner = oldSym.owner
+ val owner =
+ if ((oldOwner eq defn.AnyClass) || (oldOwner eq defn.AnyValClass)) {
+ assert(oldSym.isConstructor, s"${oldSym.showLocated}")
+ defn.ObjectClass
+ }
+ else if (defn.isUnimplementedFunctionClass(oldOwner))
+ defn.FunctionXXLClass
+ else
+ oldOwner
+ val sym = if (owner eq oldOwner) oldSym else owner.info.decl(oldSym.name).symbol
+ assert(sym.exists, owner)
def select(qual: Tree, sym: Symbol): Tree = {
val name = tree.typeOpt match {
@@ -366,11 +390,7 @@ object Erasure extends TypeTestsCasts{
def recur(qual: Tree): Tree = {
val qualIsPrimitive = qual.tpe.widen.isPrimitiveValueType
val symIsPrimitive = sym.owner.isPrimitiveValueClass
- if ((sym.owner eq defn.AnyClass) || (sym.owner eq defn.AnyValClass)) {
- assert(sym.isConstructor, s"${sym.showLocated}")
- select(qual, defn.ObjectClass.info.decl(sym.name).symbol)
- }
- else if (qualIsPrimitive && !symIsPrimitive || qual.tpe.widenDealias.isErasedValueType)
+ if (qualIsPrimitive && !symIsPrimitive || qual.tpe.widenDealias.isErasedValueType)
recur(box(qual))
else if (!qualIsPrimitive && symIsPrimitive)
recur(unbox(qual, sym.owner.typeRef))
@@ -423,6 +443,9 @@ object Erasure extends TypeTestsCasts{
}
}
+ /** Besides notmal typing, this method collects all arguments
+ * to a compacted function into a single argument of array type.
+ */
override def typedApply(tree: untpd.Apply, pt: Type)(implicit ctx: Context): Tree = {
val Apply(fun, args) = tree
if (fun.symbol == defn.dummyApply)
@@ -434,7 +457,13 @@ object Erasure extends TypeTestsCasts{
fun1.tpe.widen match {
case mt: MethodType =>
val outers = outer.args(fun.asInstanceOf[tpd.Tree]) // can't use fun1 here because its type is already erased
- val args1 = (outers ::: args ++ protoArgs(pt)).zipWithConserve(mt.paramTypes)(typedExpr)
+ var args0 = outers ::: args ++ protoArgs(pt)
+ if (args0.length > MaxImplementedFunctionArity && mt.paramTypes.length == 1) {
+ val bunchedArgs = untpd.JavaSeqLiteral(args0, TypeTree(defn.ObjectType))
+ .withType(defn.ArrayOf(defn.ObjectType))
+ args0 = bunchedArgs :: Nil
+ }
+ val args1 = args0.zipWithConserve(mt.paramTypes)(typedExpr)
untpd.cpy.Apply(tree)(fun1, args1) withType mt.resultType
case _ =>
throw new MatchError(i"tree $tree has unexpected type of function ${fun1.tpe.widen}, was ${fun.typeOpt.widen}")
@@ -470,18 +499,36 @@ object Erasure extends TypeTestsCasts{
super.typedValDef(untpd.cpy.ValDef(vdef)(
tpt = untpd.TypedSplice(TypeTree(sym.info).withPos(vdef.tpt.pos))), sym)
+ /** Besides normal typing, this function also compacts anonymous functions
+ * with more than `MaxImplementedFunctionArity` parameters to ise a single
+ * parameter of type `[]Object`.
+ */
override def typedDefDef(ddef: untpd.DefDef, sym: Symbol)(implicit ctx: Context) = {
val restpe =
if (sym.isConstructor) defn.UnitType
else sym.info.resultType
+ var vparamss1 = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil
+ var rhs1 = ddef.rhs match {
+ case id @ Ident(nme.WILDCARD) => untpd.TypedSplice(id.withType(restpe))
+ case _ => ddef.rhs
+ }
+ if (sym.isAnonymousFunction && vparamss1.head.length > MaxImplementedFunctionArity) {
+ val bunchedParam = ctx.newSymbol(sym, nme.ALLARGS, Flags.TermParam, JavaArrayType(defn.ObjectType))
+ def selector(n: Int) = ref(bunchedParam)
+ .select(defn.Array_apply)
+ .appliedTo(Literal(Constant(n)))
+ val paramDefs = vparamss1.head.zipWithIndex.map {
+ case (paramDef, idx) =>
+ assignType(untpd.cpy.ValDef(paramDef)(rhs = selector(idx)), paramDef.symbol)
+ }
+ vparamss1 = (tpd.ValDef(bunchedParam) :: Nil) :: Nil
+ rhs1 = untpd.Block(paramDefs, rhs1)
+ }
val ddef1 = untpd.cpy.DefDef(ddef)(
tparams = Nil,
- vparamss = (outer.paramDefs(sym) ::: ddef.vparamss.flatten) :: Nil,
+ vparamss = vparamss1,
tpt = untpd.TypedSplice(TypeTree(restpe).withPos(ddef.tpt.pos)),
- rhs = ddef.rhs match {
- case id @ Ident(nme.WILDCARD) => untpd.TypedSplice(id.withType(restpe))
- case _ => ddef.rhs
- })
+ rhs = rhs1)
super.typedDefDef(ddef1, sym)
}