aboutsummaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-11-29 19:37:15 +0100
committerMartin Odersky <odersky@gmail.com>2016-11-29 19:37:36 +0100
commit3116142d3e0e2d560b2fa79f73e699e1ac000204 (patch)
treea8fdcbeaccdbeae7a89e07f90e3af8579aec868b /compiler
parente7a0d03f0d29b4644b09b0a36fb3557849d6cf72 (diff)
downloaddotty-3116142d3e0e2d560b2fa79f73e699e1ac000204.tar.gz
dotty-3116142d3e0e2d560b2fa79f73e699e1ac000204.tar.bz2
dotty-3116142d3e0e2d560b2fa79f73e699e1ac000204.zip
Drop limit 30 of generated function classes
Function classes beyond 22 are now generated on demand, with no upper limit.
Diffstat (limited to 'compiler')
-rw-r--r--compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala85
2 files changed, 61 insertions, 26 deletions
diff --git a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
index a7c449947..397382c2f 100644
--- a/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
+++ b/compiler/src/dotty/tools/backend/jvm/DottyBackendInterface.scala
@@ -140,7 +140,7 @@ class DottyBackendInterface(outputDirectory: AbstractFile, val superCallsMap: Ma
val externalEqualsNumChar: Symbol = NoSymbol // ctx.requiredMethod(BoxesRunTimeTypeRef, nme.equalsNumChar) // this method is private
val externalEqualsNumObject: Symbol = defn.BoxesRunTimeModule.requiredMethod(nme.equalsNumObject)
val externalEquals: Symbol = defn.BoxesRunTimeClass.info.decl(nme.equals_).suchThat(toDenot(_).info.firstParamTypes.size == 2).symbol
- val MaxFunctionArity: Int = Definitions.MaxFunctionArity
+ val MaxFunctionArity: Int = Definitions.MaxImplementedFunctionArity
val FunctionClass: Array[Symbol] = defn.FunctionClassPerRun()
val AbstractFunctionClass: Array[Symbol] = defn.AbstractFunctionClassPerRun()
val PartialFunctionClass: Symbol = defn.PartialFunctionClass
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index 44f4acffa..e1a87d1f7 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -12,13 +12,19 @@ import collection.mutable
import scala.reflect.api.{ Universe => ApiUniverse }
object Definitions {
- val MaxTupleArity, MaxAbstractFunctionArity = 22
- val MaxFunctionArity = 30
- // Awaiting a definite solution that drops the limit altogether, 30 gives a safety
- // margin over the previous 22, so that treecopiers in miniphases are allowed to
- // temporarily create larger closures. This is needed in lambda lift where large closures
- // are first formed by treecopiers before they are split apart into parameters and
- // environment in the lambdalift transform itself.
+
+ /** The maximum number of elements in a tuple or product.
+ * This should be removed once we go to hlists.
+ */
+ val MaxTupleArity = 22
+
+ /** The maximum arity N of a function type that's implemented
+ * as a trait `scala.FunctionN`. Functions of higher arity are possible,
+ * but are mapped to functions taking a vararg by erasure.
+ * The limit 22 is chosen for Scala2x interop. It could be something
+ * else without affecting the set of programs that can be compiled.
+ */
+ val MaxImplementedFunctionArity = 22
}
/** A class defining symbols and types of standard definitions
@@ -76,7 +82,27 @@ class Definitions {
denot.info = ClassInfo(ScalaPackageClass.thisType, cls, parentRefs, paramDecls)
}
}
- newClassSymbol(ScalaPackageClass, name, EmptyFlags, completer)
+ newClassSymbol(ScalaPackageClass, name, EmptyFlags, completer).entered
+ }
+
+ /** The trait FunctionN, for some N */
+ private def newFunctionNTrait(n: Int) = {
+ val completer = new LazyType {
+ def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
+ val cls = denot.asClass.classSymbol
+ val decls = newScope
+ val argParams =
+ for (i <- List.range(0, n)) yield
+ enterTypeParam(cls, s"T$i".toTypeName, Contravariant, decls)
+ val resParam = enterTypeParam(cls, s"R".toTypeName, Covariant, decls)
+ val applyMeth =
+ decls.enter(
+ newMethod(cls, nme.apply,
+ MethodType(argParams.map(_.typeRef), resParam.typeRef), Deferred))
+ denot.info = ClassInfo(ScalaPackageClass.thisType, cls, ObjectType :: Nil, decls)
+ }
+ }
+ newClassSymbol(ScalaPackageClass, s"Function$n".toTypeName, Trait, completer)
}
private def newMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
@@ -562,14 +588,15 @@ class Definitions {
object FunctionOf {
def apply(args: List[Type], resultType: Type)(implicit ctx: Context) =
FunctionType(args.length).appliedTo(args ::: resultType :: Nil)
- def unapply(ft: Type)(implicit ctx: Context)/*: Option[(List[Type], Type)]*/ = {
- // -language:keepUnions difference: unapply needs result type because inferred type
- // is Some[(List[Type], Type)] | None, which is not a legal unapply type.
+ def unapply(ft: Type)(implicit ctx: Context) = {
val tsym = ft.typeSymbol
- lazy val targs = ft.argInfos
- val numArgs = targs.length - 1
- if (numArgs >= 0 && numArgs <= MaxFunctionArity &&
- (FunctionType(numArgs).symbol == tsym)) Some(targs.init, targs.last)
+ if (isFunctionClass(tsym)) {
+ lazy val targs = ft.argInfos
+ val numArgs = targs.length - 1
+ if (numArgs >= 0 && FunctionType(numArgs).symbol == tsym)
+ Some(targs.init, targs.last)
+ else None
+ }
else None
}
}
@@ -612,19 +639,26 @@ class Definitions {
// ----- Symbol sets ---------------------------------------------------
- lazy val AbstractFunctionType = mkArityArray("scala.runtime.AbstractFunction", MaxAbstractFunctionArity, 0)
+ lazy val AbstractFunctionType = mkArityArray("scala.runtime.AbstractFunction", MaxImplementedFunctionArity, 0)
val AbstractFunctionClassPerRun = new PerRun[Array[Symbol]](implicit ctx => AbstractFunctionType.map(_.symbol.asClass))
def AbstractFunctionClass(n: Int)(implicit ctx: Context) = AbstractFunctionClassPerRun()(ctx)(n)
- lazy val FunctionType = mkArityArray("scala.Function", MaxFunctionArity, 0)
- def FunctionClassPerRun = new PerRun[Array[Symbol]](implicit ctx => FunctionType.map(_.symbol.asClass))
- def FunctionClass(n: Int)(implicit ctx: Context) = FunctionClassPerRun()(ctx)(n)
- lazy val Function0_applyR = FunctionType(0).symbol.requiredMethodRef(nme.apply)
+ private lazy val ImplementedFunctionType = mkArityArray("scala.Function", MaxImplementedFunctionArity, 0)
+ def FunctionClassPerRun = new PerRun[Array[Symbol]](implicit ctx => ImplementedFunctionType.map(_.symbol.asClass))
+
+ def FunctionClass(n: Int)(implicit ctx: Context) =
+ if (n < MaxImplementedFunctionArity) FunctionClassPerRun()(ctx)(n)
+ else ctx.requiredClass("scala.Function" + n.toString)
+
+ 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)
- private lazy val FunctionTypes: Set[TypeRef] = FunctionType.toSet
+ def FunctionType(n: Int): TypeRef =
+ if (n < MaxImplementedFunctionArity) ImplementedFunctionType(n)
+ else FunctionClass(n).typeRef
+
private lazy val TupleTypes: Set[TypeRef] = TupleType.toSet
private lazy val ProductTypes: Set[TypeRef] = ProductNType.toSet
@@ -688,10 +722,11 @@ class Definitions {
def isProductSubType(tp: Type)(implicit ctx: Context) =
(tp derivesFrom ProductType.symbol) && tp.baseClasses.exists(isProductClass)
- def isFunctionType(tp: Type)(implicit ctx: Context) = {
- val arity = functionArity(tp)
- 0 <= arity && arity <= MaxFunctionArity && (tp isRef FunctionType(arity).symbol)
- }
+ def isFunctionType(tp: Type)(implicit ctx: Context) =
+ isFunctionClass(tp.dealias.typeSymbol) && {
+ val arity = functionArity(tp)
+ arity >= 0 && tp.isRef(FunctionType(functionArity(tp)).typeSymbol)
+ }
def functionArity(tp: Type)(implicit ctx: Context) = tp.dealias.argInfos.length - 1