aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/Definitions.scala
diff options
context:
space:
mode:
authorodersky <odersky@gmail.com>2016-12-03 11:01:43 +0100
committerGitHub <noreply@github.com>2016-12-03 11:01:43 +0100
commit8288a3462353de80d8295bbd1f69afe141b2ed4c (patch)
treeba4031a89c9ec87af02cc62096dd931db75f88ad /compiler/src/dotty/tools/dotc/core/Definitions.scala
parentb0a64ec191b1b0c4ab0b066c4dcb11e0c073d6b5 (diff)
parent055f12f957ec176323e4e0bf01af51666b9ff433 (diff)
downloaddotty-8288a3462353de80d8295bbd1f69afe141b2ed4c.tar.gz
dotty-8288a3462353de80d8295bbd1f69afe141b2ed4c.tar.bz2
dotty-8288a3462353de80d8295bbd1f69afe141b2ed4c.zip
Merge pull request #1758 from dotty-staging/change-functions
Drop function 22 limit
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Definitions.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Definitions.scala214
1 files changed, 137 insertions, 77 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Definitions.scala b/compiler/src/dotty/tools/dotc/core/Definitions.scala
index c5ccab261..e4e5761b2 100644
--- a/compiler/src/dotty/tools/dotc/core/Definitions.scala
+++ b/compiler/src/dotty/tools/dotc/core/Definitions.scala
@@ -12,13 +12,20 @@ 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 in erasure to functions taking a single parameter of type
+ * Object[].
+ * 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
@@ -45,32 +52,29 @@ class Definitions {
ctx.newSymbol(owner, name, flags | Permanent, info)
private def newClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet, infoFn: ClassSymbol => Type) =
- ctx.newClassSymbol(owner, name, flags | Permanent, infoFn).entered
+ ctx.newClassSymbol(owner, name, flags | Permanent, infoFn)
- private def newCompleteClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet, parents: List[TypeRef], decls: Scope = newScope) =
+ private def enterCompleteClassSymbol(owner: Symbol, name: TypeName, flags: FlagSet, parents: List[TypeRef], decls: Scope = newScope) =
ctx.newCompleteClassSymbol(owner, name, flags | Permanent, parents, decls).entered
- private def newTopClassSymbol(name: TypeName, flags: FlagSet, parents: List[TypeRef]) =
- completeClass(newCompleteClassSymbol(ScalaPackageClass, name, flags, parents))
-
- private def newTypeField(cls: ClassSymbol, name: TypeName, flags: FlagSet, scope: MutableScope) =
+ private def enterTypeField(cls: ClassSymbol, name: TypeName, flags: FlagSet, scope: MutableScope) =
scope.enter(newSymbol(cls, name, flags, TypeBounds.empty))
- private def newTypeParam(cls: ClassSymbol, name: TypeName, flags: FlagSet, scope: MutableScope) =
- newTypeField(cls, name, flags | ClassTypeParamCreationFlags, scope)
+ private def enterTypeParam(cls: ClassSymbol, name: TypeName, flags: FlagSet, scope: MutableScope) =
+ enterTypeField(cls, name, flags | ClassTypeParamCreationFlags, scope)
- private def newSyntheticTypeParam(cls: ClassSymbol, scope: MutableScope, paramFlags: FlagSet, suffix: String = "T0") =
- newTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope)
+ private def enterSyntheticTypeParam(cls: ClassSymbol, paramFlags: FlagSet, scope: MutableScope, suffix: String = "T0") =
+ enterTypeParam(cls, suffix.toTypeName.expandedName(cls), ExpandedName | paramFlags, scope)
// NOTE: Ideally we would write `parentConstrs: => Type*` but SIP-24 is only
// implemented in Dotty and not in Scala 2.
// See <http://docs.scala-lang.org/sips/pending/repeated-byname.html>.
- private def specialPolyClass(name: TypeName, paramFlags: FlagSet, parentConstrs: => Seq[Type]): ClassSymbol = {
+ private def enterSpecialPolyClass(name: TypeName, paramFlags: FlagSet, parentConstrs: => Seq[Type]): ClassSymbol = {
val completer = new LazyType {
def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
val cls = denot.asClass.classSymbol
val paramDecls = newScope
- val typeParam = newSyntheticTypeParam(cls, paramDecls, paramFlags)
+ val typeParam = enterSyntheticTypeParam(cls, paramFlags, paramDecls)
def instantiate(tpe: Type) =
if (tpe.typeParams.nonEmpty) tpe.appliedTo(typeParam.typeRef)
else tpe
@@ -79,31 +83,54 @@ 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 =
- newSymbol(cls, name.encode, flags | Method, info).entered.asTerm
+ newSymbol(cls, name.encode, flags | Method, info).asTerm
- private def newAliasType(name: TypeName, tpe: Type, flags: FlagSet = EmptyFlags): TypeSymbol = {
+ private def enterMethod(cls: ClassSymbol, name: TermName, info: Type, flags: FlagSet = EmptyFlags): TermSymbol =
+ newMethod(cls, name, info, flags).entered
+
+ private def enterAliasType(name: TypeName, tpe: Type, flags: FlagSet = EmptyFlags): TypeSymbol = {
val sym = newSymbol(ScalaPackageClass, name, flags, TypeAlias(tpe))
ScalaPackageClass.currentPackageDecls.enter(sym)
sym
}
- private def newPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int,
+ private def enterPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int,
resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = {
val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount)
val tparamBounds = tparamNames map (_ => TypeBounds.empty)
val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn)
- newMethod(cls, name, ptype, flags)
+ enterMethod(cls, name, ptype, flags)
}
- private def newT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) =
- newPolyMethod(cls, name, 1, resultTypeFn, flags)
+ private def enterT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) =
+ enterPolyMethod(cls, name, 1, resultTypeFn, flags)
- private def newT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) =
- newPolyMethod(cls, name, 1, pt => MethodType(Nil, resultTypeFn(pt)), flags)
+ private def enterT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) =
+ enterPolyMethod(cls, name, 1, pt => MethodType(Nil, resultTypeFn(pt)), flags)
private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[TypeRef] = {
val arr = new Array[TypeRef](arity + 1)
@@ -172,20 +199,20 @@ class Definitions {
* def getClass: java.lang.Class[T] = ???
* }
*/
- lazy val AnyClass: ClassSymbol = completeClass(newCompleteClassSymbol(ScalaPackageClass, tpnme.Any, Abstract, Nil))
+ lazy val AnyClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.Any, Abstract, Nil))
def AnyType = AnyClass.typeRef
- lazy val AnyValClass: ClassSymbol = completeClass(newCompleteClassSymbol(ScalaPackageClass, tpnme.AnyVal, Abstract, List(AnyClass.typeRef)))
+ lazy val AnyValClass: ClassSymbol = completeClass(enterCompleteClassSymbol(ScalaPackageClass, tpnme.AnyVal, Abstract, List(AnyClass.typeRef)))
def AnyValType = AnyValClass.typeRef
- lazy val Any_== = newMethod(AnyClass, nme.EQ, methOfAny(BooleanType), Final)
- lazy val Any_!= = newMethod(AnyClass, nme.NE, methOfAny(BooleanType), Final)
- lazy val Any_equals = newMethod(AnyClass, nme.equals_, methOfAny(BooleanType))
- lazy val Any_hashCode = newMethod(AnyClass, nme.hashCode_, MethodType(Nil, IntType))
- lazy val Any_toString = newMethod(AnyClass, nme.toString_, MethodType(Nil, StringType))
- lazy val Any_## = newMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final)
- lazy val Any_getClass = newMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
- lazy val Any_isInstanceOf = newT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
- lazy val Any_asInstanceOf = newT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final)
+ lazy val Any_== = enterMethod(AnyClass, nme.EQ, methOfAny(BooleanType), Final)
+ lazy val Any_!= = enterMethod(AnyClass, nme.NE, methOfAny(BooleanType), Final)
+ lazy val Any_equals = enterMethod(AnyClass, nme.equals_, methOfAny(BooleanType))
+ lazy val Any_hashCode = enterMethod(AnyClass, nme.hashCode_, MethodType(Nil, IntType))
+ lazy val Any_toString = enterMethod(AnyClass, nme.toString_, MethodType(Nil, StringType))
+ lazy val Any_## = enterMethod(AnyClass, nme.HASHHASH, ExprType(IntType), Final)
+ lazy val Any_getClass = enterMethod(AnyClass, nme.getClass_, MethodType(Nil, ClassClass.typeRef.appliedTo(TypeBounds.empty)), Final)
+ lazy val Any_isInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.isInstanceOf_, _ => BooleanType, Final)
+ lazy val Any_asInstanceOf = enterT1ParameterlessMethod(AnyClass, nme.asInstanceOf_, PolyParam(_, 0), Final)
def AnyMethods = List(Any_==, Any_!=, Any_equals, Any_hashCode,
Any_toString, Any_##, Any_getClass, Any_isInstanceOf, Any_asInstanceOf)
@@ -205,37 +232,37 @@ class Definitions {
}
def ObjectType = ObjectClass.typeRef
- lazy val AnyRefAlias: TypeSymbol = newAliasType(tpnme.AnyRef, ObjectType)
+ lazy val AnyRefAlias: TypeSymbol = enterAliasType(tpnme.AnyRef, ObjectType)
def AnyRefType = AnyRefAlias.typeRef
- lazy val Object_eq = newMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final)
- lazy val Object_ne = newMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final)
- lazy val Object_synchronized = newPolyMethod(ObjectClass, nme.synchronized_, 1,
+ lazy val Object_eq = enterMethod(ObjectClass, nme.eq, methOfAnyRef(BooleanType), Final)
+ lazy val Object_ne = enterMethod(ObjectClass, nme.ne, methOfAnyRef(BooleanType), Final)
+ lazy val Object_synchronized = enterPolyMethod(ObjectClass, nme.synchronized_, 1,
pt => MethodType(List(PolyParam(pt, 0)), PolyParam(pt, 0)), Final)
- lazy val Object_clone = newMethod(ObjectClass, nme.clone_, MethodType(Nil, ObjectType), Protected)
- lazy val Object_finalize = newMethod(ObjectClass, nme.finalize_, MethodType(Nil, UnitType), Protected)
- lazy val Object_notify = newMethod(ObjectClass, nme.notify_, MethodType(Nil, UnitType))
- lazy val Object_notifyAll = newMethod(ObjectClass, nme.notifyAll_, MethodType(Nil, UnitType))
- lazy val Object_wait = newMethod(ObjectClass, nme.wait_, MethodType(Nil, UnitType))
- lazy val Object_waitL = newMethod(ObjectClass, nme.wait_, MethodType(LongType :: Nil, UnitType))
- lazy val Object_waitLI = newMethod(ObjectClass, nme.wait_, MethodType(LongType :: IntType :: Nil, UnitType))
+ lazy val Object_clone = enterMethod(ObjectClass, nme.clone_, MethodType(Nil, ObjectType), Protected)
+ lazy val Object_finalize = enterMethod(ObjectClass, nme.finalize_, MethodType(Nil, UnitType), Protected)
+ lazy val Object_notify = enterMethod(ObjectClass, nme.notify_, MethodType(Nil, UnitType))
+ lazy val Object_notifyAll = enterMethod(ObjectClass, nme.notifyAll_, MethodType(Nil, UnitType))
+ lazy val Object_wait = enterMethod(ObjectClass, nme.wait_, MethodType(Nil, UnitType))
+ lazy val Object_waitL = enterMethod(ObjectClass, nme.wait_, MethodType(LongType :: Nil, UnitType))
+ lazy val Object_waitLI = enterMethod(ObjectClass, nme.wait_, MethodType(LongType :: IntType :: Nil, UnitType))
def ObjectMethods = List(Object_eq, Object_ne, Object_synchronized, Object_clone,
Object_finalize, Object_notify, Object_notifyAll, Object_wait, Object_waitL, Object_waitLI)
/** Dummy method needed by elimByName */
- lazy val dummyApply = newPolyMethod(
+ lazy val dummyApply = enterPolyMethod(
OpsPackageClass, nme.dummyApply, 1,
pt => MethodType(List(FunctionOf(Nil, PolyParam(pt, 0))), PolyParam(pt, 0)))
/** Method representing a throw */
- lazy val throwMethod = newMethod(OpsPackageClass, nme.THROWkw,
+ lazy val throwMethod = enterMethod(OpsPackageClass, nme.THROWkw,
MethodType(List(ThrowableType), NothingType))
- lazy val NothingClass: ClassSymbol = newCompleteClassSymbol(
+ lazy val NothingClass: ClassSymbol = enterCompleteClassSymbol(
ScalaPackageClass, tpnme.Nothing, AbstractFinal, List(AnyClass.typeRef))
def NothingType = NothingClass.typeRef
- lazy val NullClass: ClassSymbol = newCompleteClassSymbol(
+ lazy val NullClass: ClassSymbol = enterCompleteClassSymbol(
ScalaPackageClass, tpnme.Null, AbstractFinal, List(ObjectClass.typeRef))
def NullType = NullClass.typeRef
@@ -281,7 +308,7 @@ class Definitions {
lazy val SingletonClass: ClassSymbol =
// needed as a synthetic class because Scala 2.x refers to it in classfiles
// but does not define it as an explicit class.
- newCompleteClassSymbol(
+ enterCompleteClassSymbol(
ScalaPackageClass, tpnme.Singleton, PureInterfaceCreationFlags | Final,
List(AnyClass.typeRef), EmptyScope)
@@ -387,17 +414,17 @@ class Definitions {
lazy val BoxedDoubleModule = ctx.requiredModule("java.lang.Double")
lazy val BoxedUnitModule = ctx.requiredModule("java.lang.Void")
- lazy val ByNameParamClass2x = specialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, Seq(AnyType))
- lazy val EqualsPatternClass = specialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, Seq(AnyType))
+ lazy val ByNameParamClass2x = enterSpecialPolyClass(tpnme.BYNAME_PARAM_CLASS, Covariant, Seq(AnyType))
+ lazy val EqualsPatternClass = enterSpecialPolyClass(tpnme.EQUALS_PATTERN, EmptyFlags, Seq(AnyType))
- lazy val RepeatedParamClass = specialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, Seq(ObjectType, SeqType))
+ lazy val RepeatedParamClass = enterSpecialPolyClass(tpnme.REPEATED_PARAM_CLASS, Covariant, Seq(ObjectType, SeqType))
// fundamental classes
lazy val StringClass = ctx.requiredClass("java.lang.String")
def StringType: Type = StringClass.typeRef
lazy val StringModule = StringClass.linkedClass
- lazy val String_+ = newMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final)
+ lazy val String_+ = enterMethod(StringClass, nme.raw.PLUS, methOfAny(StringType), Final)
lazy val String_valueOf_Object = StringModule.info.member(nme.valueOf).suchThat(_.info.firstParamTypes match {
case List(pt) => (pt isRef AnyClass) || (pt isRef ObjectClass)
case _ => false
@@ -431,6 +458,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")
@@ -562,14 +592,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 +643,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)
- def Function0_apply(implicit ctx: Context) = Function0_applyR.symbol
+ 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)
- private lazy val FunctionTypes: Set[TypeRef] = FunctionType.toSet
+ 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
+
+ def FunctionType(n: Int)(implicit ctx: Context): 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
@@ -646,6 +684,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)
@@ -695,10 +735,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
@@ -774,6 +815,23 @@ class Definitions {
// ----- Initialization ---------------------------------------------------
+ /** Give the scala package a scope where a FunctionN trait is automatically
+ * added when someone looks for it.
+ */
+ private def makeScalaSpecial()(implicit ctx: Context) = {
+ val oldInfo = ScalaPackageClass.classInfo
+ val oldDecls = oldInfo.decls
+ val newDecls = new MutableScope(oldDecls) {
+ override def lookupEntry(name: Name)(implicit ctx: Context): ScopeEntry = {
+ val res = super.lookupEntry(name)
+ if (res == null && name.functionArity > 0)
+ newScopeEntry(newFunctionNTrait(name.functionArity))
+ else res
+ }
+ }
+ ScalaPackageClass.info = oldInfo.derivedClassInfo(decls = newDecls)
+ }
+
/** Lists core classes that don't have underlying bytecode, but are synthesized on-the-fly in every reflection universe */
lazy val syntheticScalaClasses = List(
AnyClass,
@@ -801,6 +859,8 @@ class Definitions {
def init()(implicit ctx: Context) = {
this.ctx = ctx
if (!_isInitialized) {
+ makeScalaSpecial()
+
// force initialization of every symbol that is synthesized or hijacked by the compiler
val forced = syntheticCoreClasses ++ syntheticCoreMethods ++ ScalaValueClasses()