aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2017-03-16 15:15:28 +0100
committerMartin Odersky <odersky@gmail.com>2017-04-06 13:15:27 +0200
commitc024a6037f3dd7e7458d936566cd4b653b8b7545 (patch)
treeaae9b2e9b332fc166a04f1b29f1ff4e62fdd6216 /compiler/src/dotty/tools/dotc/core/Types.scala
parent549bd812684e6f269610234ddefe8054dfb42746 (diff)
downloaddotty-c024a6037f3dd7e7458d936566cd4b653b8b7545.tar.gz
dotty-c024a6037f3dd7e7458d936566cd4b653b8b7545.tar.bz2
dotty-c024a6037f3dd7e7458d936566cd4b653b8b7545.zip
Break out functionality from MethodType
and generalize MethodParam to ParamRef, and TypeParamInfo to ParamInfo
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala206
1 files changed, 124 insertions, 82 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 533a8f3f6..17879f168 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -54,7 +54,7 @@ object Types {
* | | +--- ThisType
* | | +--- SuperType
* | | +--- ConstantType
- * | | +--- MethodParam
+ * | | +--- TermParamRef
* | | +----RecThis
* | | +--- SkolemType
* | +- PolyParam
@@ -2317,18 +2317,52 @@ object Types {
trait MethodOrPoly extends MethodicType
- abstract case class MethodType(paramNames: List[TermName])(
- paramTypesExp: MethodType => List[Type],
- resultTypeExp: MethodType => Type)
- extends CachedGroundType with BindingType with TermType with MethodOrPoly with NarrowCached { thisMethodType =>
- import MethodType._
+ /** The lambda type square:
+ *
+ * LambdaType | LambdaOverTerms | LambdaOverTypes
+ * ------------+-------------------+------------------
+ * Proxy (hk) | HKTermLambda | HKTypeLambda
+ * Ground (*) | MethodType | PolyType
+ */
+ trait LambdaType extends BindingType with MethodOrPoly {
+ def paramNames: List[TermName]
+ def paramTypes: List[Type]
+ def resType: Type
+ def newLikeThis(paramNames: List[Name], paramBounds: List[Type], resType: Type)(implicit ctx: Context): LambdaType
+ def newParamRef(n: Int): ParamRef
- def isJava = false
- def isImplicit = false
+ override def resultType(implicit ctx: Context) = resType
- val paramTypes = paramTypesExp(this)
- private[core] val resType = resultTypeExp(this)
- assert(resType.exists)
+ def isDependent(implicit ctx: Context): Boolean
+
+ final def isTermLambda = paramNames.head.isTermName
+ final def isTypeLambda = paramNames.head.isTypeName
+ final def isHigherKinded = isInstanceOf[TypeProxy]
+
+ lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef)
+
+ def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
+ if (isDependent) resultType.substParams(this, argTypes)
+ else resultType
+
+ def derivedLambdaType(paramNames: List[Name] = this.paramNames,
+ paramTypes: List[Type] = this.paramTypes,
+ resType: Type = this.resType)(implicit ctx: Context) =
+ if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this
+ else newLikeThis(paramNames, paramTypes, resType)
+
+ override def equals(that: Any) = that match {
+ case that: LambdaType =>
+ this.paramNames == that.paramNames &&
+ this.paramTypes == that.paramTypes &&
+ this.resType == that.resType
+ case _ =>
+ false
+ }
+ }
+
+ trait LambdaOverTerms extends LambdaType { thisLambdaType =>
+ import LambdaOverTerms._
override def resultType(implicit ctx: Context): Type =
if (dependencyStatus == FalseDeps) { // dealias all false dependencies
@@ -2361,7 +2395,7 @@ object Types {
if (status == TrueDeps) status
else
tp match {
- case MethodParam(`thisMethodType`, _) => TrueDeps
+ case ParamRef(`thisLambdaType`, _) => TrueDeps
case tp: TypeRef =>
val status1 = foldOver(status, tp)
tp.info match { // follow type alias to avoid dependency
@@ -2418,33 +2452,49 @@ object Types {
*/
def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps
+ def newParamRef(n: Int): ParamRef = new TermParamRef(this, n)
+ }
+
+ trait LambdaOverTypes extends LambdaType { thisLambdaType =>
+ }
+
+ object LambdaOverTerms {
+ private type DependencyStatus = Byte
+ private final val Unknown: DependencyStatus = 0 // not yet computed
+ private final val NoDeps: DependencyStatus = 1 // no dependent parameters found
+ private final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types
+ private final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist
+ private final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status
+ private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations
+ }
+
+ abstract case class MethodType(paramNames: List[TermName])(
+ paramTypesExp: MethodType => List[Type],
+ resultTypeExp: MethodType => Type)
+ extends CachedGroundType with TermType with LambdaOverTerms with NarrowCached { thisMethodType =>
+ import MethodType._
+
+ protected def companion: LambdaTypeCompanion[MethodType]
+
+ def isJava = false
+ def isImplicit = false
+
+ val paramTypes = paramTypesExp(this)
+ val resType = resultTypeExp(this)
+ assert(resType.exists)
+
protected def computeSignature(implicit ctx: Context): Signature =
resultSignature.prepend(paramTypes, isJava)
def derivedMethodType(paramNames: List[TermName] = this.paramNames,
paramTypes: List[Type] = this.paramTypes,
resType: Type = this.resType)(implicit ctx: Context) =
- if ((paramNames eq this.paramNames) && (paramTypes eq this.paramTypes) && (resType eq this.resType)) this
- else {
- val paramTypesFn = (x: MethodType) => paramTypes.map(_.subst(this, x))
- val resTypeFn = (x: MethodType) => resType.subst(this, x)
- if (isJava) JavaMethodType(paramNames)(paramTypesFn, resTypeFn)
- else if (isImplicit) ImplicitMethodType(paramNames)(paramTypesFn, resTypeFn)
- else MethodType(paramNames)(paramTypesFn, resTypeFn)
- }
-
- def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
- if (isDependent) resultType.substParams(this, argTypes)
- else resultType
+ derivedLambdaType(paramNames, paramTypes, resType)
- override def equals(that: Any) = that match {
- case that: MethodType =>
- this.paramNames == that.paramNames &&
- this.paramTypes == that.paramTypes &&
- this.resType == that.resType
- case _ =>
- false
- }
+ def newLikeThis(paramNames: List[Name], paramTypes: List[Type], resType: Type)(implicit ctx: Context): MethodType =
+ companion(paramNames.asInstanceOf[List[TermName]])(
+ x => paramTypes.mapConserve(_.subst(this, x)),
+ x => resType.subst(this, x))
override def computeHash = doHash(paramNames, resType, paramTypes)
@@ -2454,11 +2504,13 @@ object Types {
final class CachedMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ def companion = MethodType
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType]
}
final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ def companion = JavaMethodType
override def isJava = true
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[JavaMethodType]
override def computeHash = addDelta(super.computeHash, 1)
@@ -2467,19 +2519,20 @@ object Types {
final class ImplicitMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ def companion = ImplicitMethodType
override def isImplicit = true
override def equals(that: Any) = super.equals(that) && that.isInstanceOf[ImplicitMethodType]
override def computeHash = addDelta(super.computeHash, 2)
override protected def prefixString = "ImplicitMethodType"
}
- abstract class MethodTypeCompanion {
- def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType
- def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
+ abstract class LambdaTypeCompanion[LT <: LambdaType] {
+ def apply(paramNames: List[TermName])(paramTypesExp: LT => List[Type], resultTypeExp: LT => Type)(implicit ctx: Context): LT
+ def apply(paramNames: List[TermName], paramTypes: List[Type], resultType: Type)(implicit ctx: Context): LT =
apply(paramNames)(_ => paramTypes, _ => resultType)
- def apply(paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ def apply(paramTypes: List[Type])(resultTypeExp: LT => Type)(implicit ctx: Context): LT =
apply(nme.syntheticParamNames(paramTypes.length))(_ => paramTypes, resultTypeExp)
- def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
+ def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): LT =
apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType)
/** Produce method type from parameter symbols, with special mappings for repeated
@@ -2501,8 +2554,8 @@ object Types {
case _: ExprType => tp
case _ => AnnotatedType(tp, Annotation(defn.InlineParamAnnot))
}
- def integrate(tp: Type, mt: MethodType) =
- tp.subst(params, (0 until params.length).toList.map(MethodParam(mt, _)))
+ def integrate(tp: Type, mt: LT) =
+ tp.subst(params, params.indices.toList.map(mt.newParamRef))
def paramInfo(param: Symbol): Type = {
val paramType = translateRepeated(param.info)
if (param.is(Inline)) translateInline(paramType) else paramType
@@ -2512,36 +2565,28 @@ object Types {
mt => integrate(resultType, mt))
}
- def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = {
- if (Config.checkMethodTypes)
+ def checkValid(mt: LT)(implicit ctx: Context): mt.type = {
+ if (Config.checkMethodTypes && mt.isTermLambda)
for ((paramType, idx) <- mt.paramTypes.zipWithIndex)
paramType.foreachPart {
- case MethodParam(`mt`, j) => assert(j < idx, mt)
+ case ParamRef(`mt`, j) => assert(j < idx, mt)
case _ =>
}
mt
}
}
- object MethodType extends MethodTypeCompanion {
+ object MethodType extends LambdaTypeCompanion[MethodType] {
def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
checkValid(unique(new CachedMethodType(paramNames)(paramTypesExp, resultTypeExp)))
-
- private type DependencyStatus = Byte
- private final val Unknown: DependencyStatus = 0 // not yet computed
- private final val NoDeps: DependencyStatus = 1 // no dependent parameters found
- private final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types
- private final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist
- private final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status
- private final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations
}
- object JavaMethodType extends MethodTypeCompanion {
+ object JavaMethodType extends LambdaTypeCompanion[MethodType] {
def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp))
}
- object ImplicitMethodType extends MethodTypeCompanion {
+ object ImplicitMethodType extends LambdaTypeCompanion[MethodType] {
def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp)))
}
@@ -2590,7 +2635,7 @@ object Types {
extends CachedProxyType with BindingType with MethodOrPoly {
/** The bounds of the type parameters */
- val paramBounds: List[TypeBounds] = paramBoundsExp(this)
+ val paramTypes: List[Type] = paramBoundsExp(this)
/** The result type of a PolyType / body of a type lambda */
val resType: Type = resultTypeExp(this)
@@ -2600,11 +2645,6 @@ object Types {
protected def computeSignature(implicit ctx: Context) = resultSignature
- def isPolymorphicMethodType: Boolean = resType match {
- case _: MethodType => true
- case _ => false
- }
-
/** PolyParam references to all type parameters of this type */
lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _))
@@ -2619,8 +2659,8 @@ object Types {
resultType.substParams(this, argTypes)
/** Instantiate parameter bounds by substituting parameters with given arguments */
- final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[TypeBounds] =
- paramBounds.mapConserve(_.substParams(this, argTypes).bounds)
+ final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] =
+ paramTypes.mapConserve(_.substParams(this, argTypes))
def newLikeThis(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType =
PolyType.apply(paramNames)(
@@ -2666,7 +2706,7 @@ object Types {
/** The type `[tparams := paramRefs] tp`, where `tparams` can be
* either a list of type parameter symbols or a list of lambda parameters
*/
- def lifted(tparams: List[TypeParamInfo], tp: Type)(implicit ctx: Context): Type =
+ def lifted(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type =
tparams match {
case LambdaParam(poly, _) :: _ => tp.subst(poly, this)
case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs)
@@ -2680,9 +2720,9 @@ object Types {
case _ => false
}
- override def toString = s"PolyType($paramNames, $paramBounds, $resType)"
+ override def toString = s"PolyType($paramNames, $paramTypes, $resType)"
- override def computeHash = doHash(paramNames, resType, paramBounds)
+ override def computeHash = doHash(paramNames, resType, paramTypes)
}
object PolyType {
@@ -2703,12 +2743,12 @@ object Types {
// ----- HK types: LambdaParam, HKApply ---------------------
/** The parameter of a type lambda */
- case class LambdaParam(tl: PolyType, n: Int) extends TypeParamInfo {
- def isTypeParam(implicit ctx: Context) = true
+ case class LambdaParam(tl: PolyType, n: Int) extends ParamInfo {
+ def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName
def paramName(implicit ctx: Context): TypeName = tl.paramNames(n)
- def paramBounds(implicit ctx: Context): TypeBounds = tl.paramBounds(n)
- def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds = paramBounds
- def paramBoundsOrCompleter(implicit ctx: Context): Type = paramBounds
+ def paramInfo(implicit ctx: Context): Type = tl.paramBounds(n)
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type = paramInfo
+ def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo
def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance
def toArg: Type = PolyParam(tl, n)
def paramRef(implicit ctx: Context): Type = PolyParam(tl, n)
@@ -2750,7 +2790,7 @@ object Types {
NoType
}
- def typeParams(implicit ctx: Context): List[TypeParamInfo] = {
+ def typeParams(implicit ctx: Context): List[ParamInfo] = {
val tparams = tycon.typeParams
if (tparams.isEmpty) PolyType.any(args.length).typeParams else tparams
}
@@ -2801,32 +2841,34 @@ object Types {
def paramName: Name
}
- abstract case class MethodParam(binder: MethodType, paramNum: Int) extends ParamType with SingletonType {
- type BT = MethodType
+ abstract case class ParamRef(binder: LambdaType, paramNum: Int) extends ParamType {
+ type BT = LambdaType
def paramName = binder.paramNames(paramNum)
override def underlying(implicit ctx: Context): Type = binder.paramTypes(paramNum)
- def copyBoundType(bt: BT) = new MethodParamImpl(bt, paramNum)
// need to customize hashCode and equals to prevent infinite recursion for dep meth types.
override def computeHash = addDelta(binder.identityHash, paramNum)
override def equals(that: Any) = that match {
- case that: MethodParam =>
+ case that: ParamRef =>
(this.binder eq that.binder) && this.paramNum == that.paramNum
case _ =>
false
}
- override def toString = s"MethodParam($paramName)"
+ override def toString = s"ParamRef($paramName)"
}
- class MethodParamImpl(binder: MethodType, paramNum: Int) extends MethodParam(binder, paramNum)
+ class TermParamRef(binder: LambdaType, paramNum: Int)
+ extends ParamRef(binder, paramNum) with SingletonType {
+ def copyBoundType(bt: BT) = new TermParamRef(bt, paramNum)
+ }
- object MethodParam {
- def apply(binder: MethodType, paramNum: Int)(implicit ctx: Context): MethodParam = {
+ object TermParamRef {
+ def apply(binder: LambdaType, paramNum: Int)(implicit ctx: Context): TermParamRef = {
assertUnerased()
- new MethodParamImpl(binder, paramNum)
+ new TermParamRef(binder, paramNum)
}
}
@@ -3510,7 +3552,7 @@ object Types {
if (inst.exists) apply(inst) else tp
case tp: HKApply =>
- def mapArg(arg: Type, tparam: TypeParamInfo): Type = {
+ def mapArg(arg: Type, tparam: ParamInfo): Type = {
val saved = variance
variance *= tparam.paramVariance
try this(arg)
@@ -3725,7 +3767,7 @@ object Types {
this(x, prefix)
case tp @ HKApply(tycon, args) =>
- @tailrec def foldArgs(x: T, tparams: List[TypeParamInfo], args: List[Type]): T =
+ @tailrec def foldArgs(x: T, tparams: List[ParamInfo], args: List[Type]): T =
if (args.isEmpty) {
assert(tparams.isEmpty)
x
@@ -3815,7 +3857,7 @@ object Types {
apply(x, tp.tref)
case tp: ConstantType =>
apply(x, tp.underlying)
- case tp: MethodParam =>
+ case tp: ParamRef =>
apply(x, tp.underlying)
case tp: PolyParam =>
apply(x, tp.underlying)