aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core
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
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')
-rw-r--r--compiler/src/dotty/tools/dotc/core/ParamInfo.scala (renamed from compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala)8
-rw-r--r--compiler/src/dotty/tools/dotc/core/Symbols.scala10
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeApplications.scala24
-rw-r--r--compiler/src/dotty/tools/dotc/core/TypeComparer.scala16
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala206
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala2
-rw-r--r--compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala2
7 files changed, 155 insertions, 113 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala
index 647c895db..efae24916 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeParamInfo.scala
+++ b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala
@@ -7,7 +7,7 @@ import Types.{Type, TypeBounds}
/** A common super trait of Symbol and LambdaParam.
* Used to capture the attributes of type parameters which can be implemented as either.
*/
-trait TypeParamInfo {
+trait ParamInfo {
/** Is this the info of a type parameter? Will return `false` for symbols
* that are not type parameters.
@@ -18,19 +18,19 @@ trait TypeParamInfo {
def paramName(implicit ctx: Context): TypeName
/** The info of the type parameter */
- def paramBounds(implicit ctx: Context): TypeBounds
+ def paramInfo(implicit ctx: Context): Type
/** The info of the type parameter as seen from a prefix type.
* For type parameter symbols, this is the `memberInfo` as seen from `prefix`.
* For type lambda parameters, it's the same as `paramBounds` as
* `asSeenFrom` has already been applied to the whole type lambda.
*/
- def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context): TypeBounds
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type
/** The parameter bounds, or the completer if the type parameter
* is an as-yet uncompleted symbol.
*/
- def paramBoundsOrCompleter(implicit ctx: Context): Type
+ def paramInfoOrCompleter(implicit ctx: Context): Type
/** The variance of the type parameter */
def paramVariance(implicit ctx: Context): Int
diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala
index 33aba4d13..705b2c133 100644
--- a/compiler/src/dotty/tools/dotc/core/Symbols.scala
+++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala
@@ -384,7 +384,7 @@ object Symbols {
* @param coord The coordinates of the symbol (a position or an index)
* @param id A unique identifier of the symbol (unique per ContextBase)
*/
- class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with TypeParamInfo with printing.Showable {
+ class Symbol private[Symbols] (val coord: Coord, val id: Int) extends DotClass with ParamInfo with printing.Showable {
type ThisName <: Name
@@ -513,12 +513,12 @@ object Symbols {
*/
def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition
- // TypeParamInfo methods
+ // ParamInfo methods
def isTypeParam(implicit ctx: Context) = denot.is(TypeParam)
def paramName(implicit ctx: Context) = name.asTypeName
- def paramBounds(implicit ctx: Context) = denot.info.bounds
- def paramBoundsAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds
- def paramBoundsOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter
+ def paramInfo(implicit ctx: Context) = denot.info.bounds
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this)
+ def paramInfoOrCompleter(implicit ctx: Context): Type = denot.infoOrCompleter
def paramVariance(implicit ctx: Context) = denot.variance
def paramRef(implicit ctx: Context) = denot.typeRef
diff --git a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
index a7ce1ee85..9a1a3359e 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -47,14 +47,14 @@ object TypeApplications {
/** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`?
*/
- def varianceConforms(tparam1: TypeParamInfo, tparam2: TypeParamInfo)(implicit ctx: Context): Boolean =
+ def varianceConforms(tparam1: ParamInfo, tparam2: ParamInfo)(implicit ctx: Context): Boolean =
varianceConforms(tparam1.paramVariance, tparam2.paramVariance)
/** Do the variances of type parameters `tparams1` conform to the variances
* of corresponding type parameters `tparams2`?
* This is only the case of `tparams1` and `tparams2` have the same length.
*/
- def variancesConform(tparams1: List[TypeParamInfo], tparams2: List[TypeParamInfo])(implicit ctx: Context): Boolean =
+ def variancesConform(tparams1: List[ParamInfo], tparams2: List[ParamInfo])(implicit ctx: Context): Boolean =
tparams1.corresponds(tparams2)(varianceConforms)
/** Extractor for
@@ -96,7 +96,7 @@ object TypeApplications {
refinements = rt :: refinements
tycon = rt.parent.stripTypeVar
}
- def collectArgs(tparams: List[TypeParamInfo],
+ def collectArgs(tparams: List[ParamInfo],
refinements: List[RefinedType],
argBuf: mutable.ListBuffer[Type]): Option[(Type, List[Type])] = refinements match {
case Nil if tparams.isEmpty && argBuf.nonEmpty =>
@@ -117,9 +117,9 @@ object TypeApplications {
/** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK
*/
- def EtaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] =
+ def EtaExpandIfHK(tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): List[Type] =
if (tparams.isEmpty) args
- else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramBoundsOrCompleter))
+ else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramInfoOrCompleter))
/** A type map that tries to reduce (part of) the result type of the type lambda `tycon`
* with the given `args`(some of which are wildcard arguments represented by type bounds).
@@ -209,7 +209,7 @@ class TypeApplications(val self: Type) extends AnyVal {
* with the bounds on its hk args. See `LambdaAbstract`, where these
* types get introduced, and see `isBoundedLambda` below for the test.
*/
- final def typeParams(implicit ctx: Context): List[TypeParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ {
+ final def typeParams(implicit ctx: Context): List[ParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ {
self match {
case self: ClassInfo =>
self.cls.typeParams
@@ -236,7 +236,7 @@ class TypeApplications(val self: Type) extends AnyVal {
}
/** If `self` is a higher-kinded type, its type parameters, otherwise Nil */
- final def hkTypeParams(implicit ctx: Context): List[TypeParamInfo] =
+ final def hkTypeParams(implicit ctx: Context): List[ParamInfo] =
if (isHK) typeParams else Nil
/** If `self` is a generic class, its type parameter symbols, otherwise Nil */
@@ -277,12 +277,12 @@ class TypeApplications(val self: Type) extends AnyVal {
*
* TODO: Handle parameterized lower bounds
*/
- def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = {
- def nameWithVariance(tparam: TypeParamInfo) =
+ def LambdaAbstract(tparams: List[ParamInfo])(implicit ctx: Context): Type = {
+ def nameWithVariance(tparam: ParamInfo) =
tparam.paramName.withVariance(tparam.paramVariance)
def expand(tp: Type) =
PolyType(tparams.map(nameWithVariance))(
- tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds),
+ tl => tparams.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds),
tl => tl.lifted(tparams, tp))
if (tparams.isEmpty) self
else self match {
@@ -393,7 +393,7 @@ class TypeApplications(val self: Type) extends AnyVal {
*/
final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ {
val typParams = self.typeParams
- def matchParams(t: Type, tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): Type = args match {
+ def matchParams(t: Type, tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): Type = args match {
case arg :: args1 =>
try {
val tparam :: tparams1 = tparams
@@ -478,7 +478,7 @@ class TypeApplications(val self: Type) extends AnyVal {
/** Turn this type, which is used as an argument for
* type parameter `tparam`, into a TypeBounds RHS
*/
- final def toBounds(tparam: TypeParamInfo)(implicit ctx: Context): TypeBounds = self match {
+ final def toBounds(tparam: ParamInfo)(implicit ctx: Context): TypeBounds = self match {
case self: TypeBounds => // this can happen for wildcard args
self
case _ =>
diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
index a8f92522c..fb16a6772 100644
--- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
+++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala
@@ -447,7 +447,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
def boundsOK =
ctx.scala2Mode ||
tparams1.corresponds(tparams2)((tparam1, tparam2) =>
- isSubType(tparam2.paramBounds.subst(tp2, tp1), tparam1.paramBounds))
+ isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo))
val saved = comparedPolyTypes
comparedPolyTypes += tp1
comparedPolyTypes += tp2
@@ -670,7 +670,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
variancesConform(tparams1, tparams) && {
if (lengthDiff > 0)
tycon1b = PolyType(tparams1.map(_.paramName))(
- tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramBounds).bounds),
+ tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds),
tl => tycon1a.appliedTo(args1.take(lengthDiff) ++
tparams1.indices.toList.map(PolyParam(tl, _))))
(ctx.mode.is(Mode.TypevarsMissContext) ||
@@ -764,7 +764,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
/** Subtype test for corresponding arguments in `args1`, `args2` according to
* variances in type parameters `tparams`.
*/
- def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[TypeParamInfo]): Boolean =
+ def isSubArgs(args1: List[Type], args2: List[Type], tparams: List[ParamInfo]): Boolean =
if (args1.isEmpty) args2.isEmpty
else args2.nonEmpty && {
val v = tparams.head.paramVariance
@@ -783,7 +783,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
* - the type parameters of `B` match one-by-one the variances of `tparams`,
* - `B` satisfies predicate `p`.
*/
- private def testLifted(tp1: Type, tp2: Type, tparams: List[TypeParamInfo], p: Type => Boolean): Boolean = {
+ private def testLifted(tp1: Type, tp2: Type, tparams: List[ParamInfo], p: Type => Boolean): Boolean = {
val classBounds = tp2.classSymbols
def recur(bcs: List[ClassSymbol]): Boolean = bcs match {
case bc :: bcs1 =>
@@ -1276,17 +1276,17 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling {
val tparams2 = tp2.typeParams
if (tparams1.isEmpty)
if (tparams2.isEmpty) op(tp1, tp2)
- else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramBoundsAsSeenFrom(tp2))))
+ else original(tp1, tp2.appliedTo(tp2.typeParams.map(_.paramInfoAsSeenFrom(tp2))))
else if (tparams2.isEmpty)
- original(tp1.appliedTo(tp1.typeParams.map(_.paramBoundsAsSeenFrom(tp1))), tp2)
+ original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2)
else
PolyType(
paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2)
.zipped.map((pname, tparam1, tparam2) =>
pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))(
paramBoundsExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) =>
- tl.lifted(tparams1, tparam1.paramBoundsAsSeenFrom(tp1)).bounds &
- tl.lifted(tparams2, tparam2.paramBoundsAsSeenFrom(tp2)).bounds),
+ tl.lifted(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds &
+ tl.lifted(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds),
resultTypeExp = tl =>
original(tl.lifted(tparams1, tp1).appliedTo(tl.paramRefs),
tl.lifted(tparams2, tp2).appliedTo(tl.paramRefs)))
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)
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
index 871f39838..d0d0e1863 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
@@ -266,7 +266,7 @@ class TreePickler(pickler: TastyPickler) {
case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes)
case _ => assert(false, s"orphan poly parameter: $tpe")
}
- case tpe: MethodParam =>
+ case tpe: ParamRef =>
assert(pickleParamType(tpe), s"orphan method parameter: $tpe")
case tpe: LazyRef =>
pickleType(tpe.ref)
diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
index 6c6ebc0a3..067fd6076 100644
--- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
+++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
@@ -284,7 +284,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle
case PARAMtype =>
readTypeRef() match {
case binder: PolyType => PolyParam(binder, readNat())
- case binder: MethodType => MethodParam(binder, readNat())
+ case binder: MethodType => binder.newParamRef(readNat())
}
case CLASSconst =>
ConstantType(Constant(readType()))