aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-11-30 14:34:17 +0100
committerMartin Odersky <odersky@gmail.com>2016-11-30 14:34:17 +0100
commitb94e6ea5a54d38470e5793c0084785e2d2f9a819 (patch)
tree6a3f4e83dbf66ad9a2353d4165f6321fede1dceb /compiler/src/dotty/tools/dotc/core
parent3116142d3e0e2d560b2fa79f73e699e1ac000204 (diff)
downloaddotty-b94e6ea5a54d38470e5793c0084785e2d2f9a819.tar.gz
dotty-b94e6ea5a54d38470e5793c0084785e2d2f9a819.tar.bz2
dotty-b94e6ea5a54d38470e5793c0084785e2d2f9a819.zip
Drop function 22 limit.
Functions with more than 22 parameters are now automatically converted to functions taking a single object array parameter. This has been achieved by tweaking erasure. Other things I have tried that did ot work out well: - Use a single function type in typer. The problem with this one which could not be circumvented was that existing higher-kinded code with e.g. Funcor assumes that Functon1 is a binary type constructor. - Have a late phase that converts to FunctonXXL instead of doing it in erasure. The problem with that one was that potentially every type could be affected, which was ill-suited to the architecture of a miniphase.
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala13
-rw-r--r--compiler/src/dotty/tools/dotc/core/StdNames.scala1
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeErasure.scala17
3 files changed, 24 insertions, 7 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index e1a87d1f7..29b7bb60a 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -457,6 +457,9 @@ class Definitions {
def PartialFunctionClass(implicit ctx: Context) = PartialFunctionType.symbol.asClass
lazy val AbstractPartialFunctionType: TypeRef = ctx.requiredClassRef("scala.runtime.AbstractPartialFunction")
def AbstractPartialFunctionClass(implicit ctx: Context) = AbstractPartialFunctionType.symbol.asClass
+ lazy val FunctionXXLType: TypeRef = ctx.requiredClassRef("scala.FunctionXXL")
+ def FunctionXXLClass(implicit ctx: Context) = FunctionXXLType.symbol.asClass
+
lazy val SymbolType: TypeRef = ctx.requiredClassRef("scala.Symbol")
def SymbolClass(implicit ctx: Context) = SymbolType.symbol.asClass
lazy val DynamicType: TypeRef = ctx.requiredClassRef("scala.Dynamic")
@@ -645,6 +648,9 @@ class Definitions {
private lazy val ImplementedFunctionType = mkArityArray("scala.Function", MaxImplementedFunctionArity, 0)
def FunctionClassPerRun = new PerRun[Array[Symbol]](implicit ctx => ImplementedFunctionType.map(_.symbol.asClass))
+ lazy val TupleType = mkArityArray("scala.Tuple", MaxTupleArity, 2)
+ lazy val ProductNType = mkArityArray("scala.Product", MaxTupleArity, 0)
+
def FunctionClass(n: Int)(implicit ctx: Context) =
if (n < MaxImplementedFunctionArity) FunctionClassPerRun()(ctx)(n)
else ctx.requiredClass("scala.Function" + n.toString)
@@ -652,10 +658,7 @@ class Definitions {
lazy val Function0_applyR = ImplementedFunctionType(0).symbol.requiredMethodRef(nme.apply)
def Function0_apply(implicit ctx: Context) = Function0_applyR.symbol
- lazy val TupleType = mkArityArray("scala.Tuple", MaxTupleArity, 2)
- lazy val ProductNType = mkArityArray("scala.Product", MaxTupleArity, 0)
-
- def FunctionType(n: Int): TypeRef =
+ def FunctionType(n: Int)(implicit ctx: Context): TypeRef =
if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n)
else FunctionClass(n).typeRef
@@ -680,6 +683,8 @@ class Definitions {
tp.derivesFrom(NothingClass) || tp.derivesFrom(NullClass)
def isFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.Function)
+ def isUnimplementedFunctionClass(cls: Symbol) =
+ isFunctionClass(cls) && cls.name.functionArity >= MaxImplementedFunctionArity
def isAbstractFunctionClass(cls: Symbol) = isVarArityClass(cls, tpnme.AbstractFunction)
def isTupleClass(cls: Symbol) = isVarArityClass(cls, tpnme.Tuple)
def isProductClass(cls: Symbol) = isVarArityClass(cls, tpnme.Product)
diff --git a/compiler/src/dotty/tools/dotc/core/StdNames.scala b/compiler/src/dotty/tools/dotc/core/StdNames.scala
index c2a14b36f..741ff8b1f 100644
--- a/compiler/src/dotty/tools/dotc/core/StdNames.scala
+++ b/compiler/src/dotty/tools/dotc/core/StdNames.scala
@@ -265,6 +265,7 @@ object StdNames {
val THIS: N = "_$this"
val TRAIT_CONSTRUCTOR: N = "$init$"
val U2EVT: N = "u2evt$"
+ val ALLARGS: N = "$allArgs"
final val Nil: N = "Nil"
final val Predef: N = "Predef"
diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
index abbacee49..57397a8bc 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala
@@ -7,6 +7,7 @@ import Uniques.unique
import dotc.transform.ExplicitOuter._
import dotc.transform.ValueClasses._
import util.DotClass
+import Definitions.MaxImplementedFunctionArity
/** Erased types are:
*
@@ -38,7 +39,10 @@ object TypeErasure {
case _: ErasedValueType =>
true
case tp: TypeRef =>
- tp.symbol.isClass && tp.symbol != defn.AnyClass && tp.symbol != defn.ArrayClass
+ val sym = tp.symbol
+ sym.isClass &&
+ sym != defn.AnyClass && sym != defn.ArrayClass &&
+ !defn.isUnimplementedFunctionClass(sym)
case _: TermRef =>
true
case JavaArrayType(elem) =>
@@ -176,8 +180,13 @@ object TypeErasure {
else if (sym.isAbstractType) TypeAlias(WildcardType)
else if (sym.isConstructor) outer.addParam(sym.owner.asClass, erase(tp)(erasureCtx))
else erase.eraseInfo(tp, sym)(erasureCtx) match {
- case einfo: MethodType if sym.isGetter && einfo.resultType.isRef(defn.UnitClass) =>
- MethodType(Nil, defn.BoxedUnitType)
+ case einfo: MethodType =>
+ if (sym.isGetter && einfo.resultType.isRef(defn.UnitClass))
+ MethodType(Nil, defn.BoxedUnitType)
+ else if (sym.isAnonymousFunction && einfo.paramTypes.length > MaxImplementedFunctionArity)
+ MethodType(nme.ALLARGS :: Nil, JavaArrayType(defn.ObjectType) :: Nil, einfo.resultType)
+ else
+ einfo
case einfo =>
einfo
}
@@ -317,6 +326,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
* - For a term ref p.x, the type <noprefix> # x.
* - For a typeref scala.Any, scala.AnyVal or scala.Singleton: |java.lang.Object|
* - For a typeref scala.Unit, |scala.runtime.BoxedUnit|.
+ * - For a typeref scala.FunctionN, where N > MaxImplementedFunctionArity, scala.FunctionXXL
* - For a typeref P.C where C refers to a class, <noprefix> # C.
* - For a typeref P.C where C refers to an alias type, the erasure of C's alias.
* - For a typeref P.C where C refers to an abstract type, the erasure of C's upper bound.
@@ -345,6 +355,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
if (!sym.isClass) this(tp.info)
else if (semiEraseVCs && isDerivedValueClass(sym)) eraseDerivedValueClassRef(tp)
else if (sym == defn.ArrayClass) apply(tp.appliedTo(TypeBounds.empty)) // i966 shows that we can hit a raw Array type.
+ else if (defn.isUnimplementedFunctionClass(sym)) defn.FunctionXXLType
else eraseNormalClassRef(tp)
case tp: RefinedType =>
val parent = tp.parent