aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala62
-rw-r--r--src/dotty/tools/dotc/core/Flags.scala7
-rw-r--r--src/dotty/tools/dotc/core/NameOps.scala12
-rw-r--r--src/dotty/tools/dotc/core/StdNames.scala13
4 files changed, 81 insertions, 13 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 6f34efc8b..3f567d87a 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -422,7 +422,7 @@ class Definitions {
def functionArity(tp: Type) = tp.dealias.argInfos.length - 1
// ----- Higher kinds machinery ------------------------------------------
-
+ // tbr
private var _hkTraits: Set[Symbol] = Set()
/** The set of HigherKindedXYZ traits encountered so far */
@@ -476,6 +476,66 @@ class Definitions {
hkTraitOfArity.getOrElseUpdate(vcs, createTrait)
}
+ // ----- LambdaXYZ traits ------------------------------------------
+
+ private var myLambdaTraits: Set[Symbol] = Set()
+
+ /** The set of HigherKindedXYZ traits encountered so far */
+ def lambdaTraits: Set[Symbol] = myLambdaTraits
+
+ private var lambdaTraitForVariances = mutable.Map[List[Int], ClassSymbol]()
+
+ /** The HigherKinded trait corresponding to symbols `boundSyms` (which are assumed
+ * to be the type parameters of a higher-kided type). This is a class symbol that
+ * would be generated by the following schema.
+ *
+ * class LambdaXYZ { type v_1 Arg1; ...; type v_N ArgN; type Apply }
+ *
+ * Here:
+ *
+ * - XYZ is a string of length N with one letter for each variant of a bound symbols,
+ * using `P` (positive variance), `N` (negative variance), `I` (invariant).
+ * - v_i are the variances of the bound symbols (i.e. +, -, or empty).
+ */
+ def lambdaTrait(vcs: List[Int]): ClassSymbol = {
+ assert(vcs.nonEmpty)
+
+ def varianceFlags(v: Int) = v match {
+ case -1 => Contravariant
+ case 0 => EmptyFlags
+ case 1 => Covariant
+ }
+
+ val completer = new LazyType {
+ def complete(denot: SymDenotation)(implicit ctx: Context): Unit = {
+ val cls = denot.asClass.classSymbol
+ val paramDecls = newScope
+ for (i <- 0 until vcs.length)
+ newTypeParam(cls, tpnme.lambdaArgName(i), varianceFlags(vcs(i)), paramDecls)
+ newTypeParam(cls, tpnme.Apply, EmptyFlags, paramDecls)
+ val parentTraitRefs =
+ for (i <- 0 until vcs.length if vcs(i) != 0)
+ yield lambdaTrait(vcs.updated(i, 0)).typeRef
+ denot.info = ClassInfo(
+ ScalaPackageClass.thisType, cls, ObjectClass.typeRef :: parentTraitRefs.toList, paramDecls)
+ }
+ }
+
+ val traitName = tpnme.lambdaTraitName(vcs)
+
+ def createTrait = {
+ val cls = newClassSymbol(
+ ScalaPackageClass,
+ traitName,
+ Trait | Interface | Synthetic,
+ completer)
+ myLambdaTraits += cls
+ cls
+ }
+
+ lambdaTraitForVariances.getOrElseUpdate(vcs, createTrait)
+ }
+
// ----- primitive value class machinery ------------------------------------------
lazy val ScalaNumericValueClasses: collection.Set[Symbol] = Set(
diff --git a/src/dotty/tools/dotc/core/Flags.scala b/src/dotty/tools/dotc/core/Flags.scala
index 9f87120f8..40da7525d 100644
--- a/src/dotty/tools/dotc/core/Flags.scala
+++ b/src/dotty/tools/dotc/core/Flags.scala
@@ -198,8 +198,9 @@ object Flags {
final val Final = commonFlag(6, "final")
/** A method symbol. */
- final val MethodCommon = commonFlag(7, "<method>")
- final val Method = MethodCommon.toTermFlags
+ final val MethodOrHKCommon = commonFlag(7, "<method>")
+ final val Method = MethodOrHKCommon.toTermFlags
+ final val HigherKinded = MethodOrHKCommon.toTypeFlags
/** A (term or type) parameter to a class or method */
final val Param = commonFlag(8, "<param>")
@@ -411,7 +412,7 @@ object Flags {
/** Flags guaranteed to be set upon symbol creation */
final val FromStartFlags =
- AccessFlags | Module | Package | Deferred | MethodCommon | Param | Scala2ExistentialCommon | Touched |
+ AccessFlags | Module | Package | Deferred | MethodOrHKCommon | Param | Scala2ExistentialCommon | Touched |
Static | CovariantCommon | ContravariantCommon | ExpandedName | AccessorOrSealed |
CaseAccessorOrTypeArgument | Frozen | Erroneous | ImplicitCommon | Permanent | SelfNameOrImplClass
diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala
index 22a7e5734..187946590 100644
--- a/src/dotty/tools/dotc/core/NameOps.scala
+++ b/src/dotty/tools/dotc/core/NameOps.scala
@@ -87,13 +87,15 @@ object NameOps {
name.last == '=' && name.head != '=' && isOperatorPart(name.head)
}
- /** Is this the name of a higher-kinded type parameter? */
- def isHkParamName: Boolean = name(0) == '_' && name.startsWith(HK_PARAM_PREFIX)
+ /** Is this the name of a higher-kinded type parameter of a Lambda? */
+ def isLambdaArgName = name.startsWith(tpnme.LAMBDA_ARG_PREFIX)
+ def isHkParamName: Boolean = name(0) == '_' && name.startsWith(HK_PARAM_PREFIX) // tbr
/** The index of the higher-kinded type parameter with this name.
- * Pre: isHkParamName.
+ * Pre: isLambdaArgName.
*/
- def hkParamIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt
+ def lambdaArgIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt
+ def hkParamIndex: Int = name.drop(name.lastIndexOf('$') + 1).toString.toInt // tbr
/** If the name ends with $nn where nn are
* all digits, strip the $ and the digits.
@@ -181,7 +183,7 @@ object NameOps {
* by this name.
* @pre The name is a higher-kinded trait name, i.e. it starts with HK_TRAIT_PREFIX
*/
- def hkVariances: List[Int] = {
+ def hkVariances: List[Int] = { // tbr
def varianceOfSuffix(suffix: Char): Int = {
val idx = tpnme.varianceSuffixes.indexOf(suffix)
assert(idx >= 0)
diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala
index 593feb909..3b1cb63f1 100644
--- a/src/dotty/tools/dotc/core/StdNames.scala
+++ b/src/dotty/tools/dotc/core/StdNames.scala
@@ -166,6 +166,7 @@ object StdNames {
final val WILDCARD_STAR: N = "_*"
final val REIFY_TREECREATOR_PREFIX: N = "$treecreator"
final val REIFY_TYPECREATOR_PREFIX: N = "$typecreator"
+ final val LAMBDA_ARG_PREFIX: N = "$hkArg$"
final val Any: N = "Any"
final val AnyVal: N = "AnyVal"
@@ -249,8 +250,8 @@ object StdNames {
val SKOLEM: N = "<skolem>"
val SPECIALIZED_INSTANCE: N = "specInstance$"
val THIS: N = "_$this"
- val HK_PARAM_PREFIX: N = "_$hk$"
- val HK_TRAIT_PREFIX: N = "$HigherKinded$"
+ val HK_PARAM_PREFIX: N = "_$hk$" // tbr
+ val HK_TRAIT_PREFIX: N = "$HigherKinded$" // tbr
final val Nil: N = "Nil"
final val Predef: N = "Predef"
@@ -286,6 +287,7 @@ object StdNames {
val Flag : N = "Flag"
val Ident: N = "Ident"
val Import: N = "Import"
+ val LambdaPrefix: N = "Lambda$"
val Literal: N = "Literal"
val LiteralAnnotArg: N = "LiteralAnnotArg"
val Modifiers: N = "Modifiers"
@@ -645,8 +647,11 @@ object StdNames {
def syntheticTypeParamNames(num: Int): List[TypeName] =
(0 until num).map(syntheticTypeParamName)(breakOut)
- def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString
- def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString
+ def higherKindedTraitName(vcs: List[Int]): TypeName = HK_TRAIT_PREFIX ++ vcs.map(varianceSuffix).mkString // tbr
+ def higherKindedParamName(n: Int) = HK_PARAM_PREFIX ++ n.toString //tbr
+
+ def lambdaTraitName(vcs: List[Int]): TypeName = LambdaPrefix ++ vcs.map(varianceSuffix).mkString
+ def lambdaArgName(n: Int) = LAMBDA_ARG_PREFIX ++ n.toString
final val Conforms = encode("<:<")