aboutsummaryrefslogtreecommitdiff
path: root/compiler/src/dotty/tools/dotc/core/Types.scala
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core/Types.scala')
-rw-r--r--compiler/src/dotty/tools/dotc/core/Types.scala760
1 files changed, 420 insertions, 340 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala
index 3f40f8a06..8ae3aa7ad 100644
--- a/compiler/src/dotty/tools/dotc/core/Types.scala
+++ b/compiler/src/dotty/tools/dotc/core/Types.scala
@@ -54,10 +54,10 @@ object Types {
* | | +--- ThisType
* | | +--- SuperType
* | | +--- ConstantType
- * | | +--- MethodParam
+ * | | +--- TermParamRef
* | | +----RecThis
* | | +--- SkolemType
- * | +- PolyParam
+ * | +- TypeParamRef
* | +- RefinedOrRecType -+-- RefinedType
* | | -+-- RecType
* | +- HKApply
@@ -65,12 +65,13 @@ object Types {
* | +- ExprType
* | +- AnnotatedType
* | +- TypeVar
- * | +- PolyType
+ * | +- HKTypeLambda
* |
* +- GroundType -+- AndType
* +- OrType
- * +- MethodType -----+- ImplicitMethodType
- * | +- JavaMethodType
+ * +- MethodOrPoly ---+-- PolyType
+ * +-- MethodType ---+- ImplicitMethodType
+ * | +- JavaMethodType
* +- ClassInfo
* |
* +- NoType
@@ -103,7 +104,7 @@ object Types {
final def isValueType: Boolean = this.isInstanceOf[ValueType]
/** Is the is value type or type lambda? */
- final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[PolyType]
+ final def isValueTypeOrLambda: Boolean = isValueType || this.isInstanceOf[TypeLambda]
/** Does this type denote a stable reference (i.e. singleton type)? */
@tailrec final def isStable(implicit ctx: Context): Boolean = stripTypeVar match {
@@ -215,17 +216,15 @@ object Types {
/** Is this the type of a method that has a repeated parameter type as
* last parameter type?
*/
- def isVarArgsMethod(implicit ctx: Context): Boolean = this match {
- case tp: PolyType => tp.resultType.isVarArgsMethod
- case mt: MethodType => mt.paramTypes.nonEmpty && mt.paramTypes.last.isRepeatedParam
+ def isVarArgsMethod(implicit ctx: Context): Boolean = stripPoly match {
+ case mt: MethodType => mt.paramInfos.nonEmpty && mt.paramInfos.last.isRepeatedParam
case _ => false
}
/** Is this the type of a method with a leading empty parameter list?
*/
- def isNullaryMethod(implicit ctx: Context): Boolean = this match {
+ def isNullaryMethod(implicit ctx: Context): Boolean = stripPoly match {
case MethodType(Nil) => true
- case tp: PolyType => tp.resultType.isNullaryMethod
case _ => false
}
@@ -443,10 +442,10 @@ object Types {
case tp: TermRef =>
go (tp.underlying match {
case mt: MethodType
- if mt.paramTypes.isEmpty && (tp.symbol is Stable) => mt.resultType
+ if mt.paramInfos.isEmpty && (tp.symbol is Stable) => mt.resultType
case tp1 => tp1
})
- case tp: PolyParam =>
+ case tp: TypeParamRef =>
goParam(tp)
case tp: RecType =>
goRec(tp)
@@ -541,9 +540,9 @@ object Types {
}
def goApply(tp: HKApply) = tp.tycon match {
- case tl: PolyType =>
+ case tl: HKTypeLambda =>
go(tl.resType).mapInfo(info =>
- tl.derivedLambdaAbstraction(tl.paramNames, tl.paramBounds, info).appliedTo(tp.args))
+ tl.derivedLambdaAbstraction(tl.paramNames, tl.paramInfos, info).appliedTo(tp.args))
case _ =>
go(tp.superType)
}
@@ -563,7 +562,7 @@ object Types {
// loadClassWithPrivateInnerAndSubSelf in ShowClassTests
go(tp.cls.typeRef) orElse d
}
- def goParam(tp: PolyParam) = {
+ def goParam(tp: TypeParamRef) = {
val next = tp.underlying
ctx.typerState.constraint.entry(tp) match {
case bounds: TypeBounds if bounds ne next =>
@@ -814,6 +813,12 @@ object Types {
*/
def stripAnnots(implicit ctx: Context): Type = this
+ /** Strip PolyType prefix */
+ def stripPoly(implicit ctx: Context): Type = this match {
+ case tp: PolyType => tp.resType.stripPoly
+ case _ => this
+ }
+
/** Widen from singleton type to its underlying non-singleton
* base type by applying one or more `underlying` dereferences,
* Also go from => T to T.
@@ -1088,43 +1093,38 @@ object Types {
}
/** The parameter types of a PolyType or MethodType, Empty list for others */
- final def paramTypess(implicit ctx: Context): List[List[Type]] = this match {
- case mt: MethodType => mt.paramTypes :: mt.resultType.paramTypess
- case pt: PolyType => pt.resultType.paramTypess
+ final def paramInfoss(implicit ctx: Context): List[List[Type]] = stripPoly match {
+ case mt: MethodType => mt.paramInfos :: mt.resultType.paramInfoss
case _ => Nil
}
/** The parameter names of a PolyType or MethodType, Empty list for others */
- final def paramNamess(implicit ctx: Context): List[List[TermName]] = this match {
+ final def paramNamess(implicit ctx: Context): List[List[TermName]] = stripPoly match {
case mt: MethodType => mt.paramNames :: mt.resultType.paramNamess
- case pt: PolyType => pt.resultType.paramNamess
case _ => Nil
}
/** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */
- @tailrec final def firstParamTypes(implicit ctx: Context): List[Type] = this match {
- case mt: MethodType => mt.paramTypes
- case pt: PolyType => pt.resultType.firstParamTypes
+ final def firstParamTypes(implicit ctx: Context): List[Type] = stripPoly match {
+ case mt: MethodType => mt.paramInfos
case _ => Nil
}
/** Is this either not a method at all, or a parameterless method? */
- @tailrec final def isParameterless(implicit ctx: Context): Boolean = this match {
+ final def isParameterless(implicit ctx: Context): Boolean = stripPoly match {
case mt: MethodType => false
- case pt: PolyType => pt.resultType.isParameterless
case _ => true
}
- /** The resultType of a PolyType, MethodType, or ExprType, the type itself for others */
+ /** The resultType of a LambdaType, or ExprType, the type itself for others */
def resultType(implicit ctx: Context): Type = this
/** The final result type of a PolyType, MethodType, or ExprType, after skipping
* all parameter sections, the type itself for all others.
*/
- def finalResultType(implicit ctx: Context): Type = resultType match {
+ def finalResultType(implicit ctx: Context): Type = resultType.stripPoly match {
case mt: MethodType => mt.resultType.finalResultType
- case pt: PolyType => pt.resultType.finalResultType
case _ => resultType
}
@@ -1180,8 +1180,8 @@ object Types {
final def substDealias(from: List[Symbol], to: List[Type])(implicit ctx: Context): Type =
ctx.substDealias(this, from, to, null)
- /** Substitute all types of the form `PolyParam(from, N)` by
- * `PolyParam(to, N)`.
+ /** Substitute all types of the form `TypeParamRef(from, N)` by
+ * `TypeParamRef(to, N)`.
*/
final def subst(from: BindingType, to: BindingType)(implicit ctx: Context): Type =
ctx.subst(this, from, to, null)
@@ -1199,7 +1199,7 @@ object Types {
ctx.substRecThis(this, binder, tp, null)
/** Substitute a bound type by some other type */
- final def substParam(from: ParamType, to: Type)(implicit ctx: Context): Type =
+ final def substParam(from: ParamRef, to: Type)(implicit ctx: Context): Type =
ctx.substParam(this, from, to, null)
/** Substitute bound types by some other types */
@@ -1220,7 +1220,7 @@ object Types {
*/
def toFunctionType(dropLast: Int = 0)(implicit ctx: Context): Type = this match {
case mt: MethodType if !mt.isDependent || ctx.mode.is(Mode.AllowDependentFunctions) =>
- val formals1 = if (dropLast == 0) mt.paramTypes else mt.paramTypes dropRight dropLast
+ val formals1 = if (dropLast == 0) mt.paramInfos else mt.paramInfos dropRight dropLast
defn.FunctionOf(
formals1 mapConserve (_.underlyingIfRepeated(mt.isJava)), mt.resultType, mt.isImplicit && !ctx.erasedTypes)
}
@@ -1360,7 +1360,7 @@ object Types {
}
/** A marker trait for types that bind other types that refer to them.
- * Instances are: PolyType, MethodType, RefinedType.
+ * Instances are: LambdaType, RecType.
*/
trait BindingType extends Type
@@ -2280,7 +2280,7 @@ object Types {
if (tp1 eq tp2) tp1 else apply(tp1, tp2)
}
- // ----- Method types: MethodType/ExprType/PolyType -------------------------------
+ // ----- ExprType and LambdaTypes -----------------------------------
// Note: method types are cached whereas poly types are not. The reason
// is that most poly types are cyclic via poly params,
@@ -2315,20 +2315,126 @@ object Types {
}
}
- trait MethodOrPoly extends MethodicType
+ /** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
+ abstract case class ExprType(resType: Type)
+ extends CachedProxyType with TermType with MethodicType {
+ override def resultType(implicit ctx: Context): Type = resType
+ override def underlying(implicit ctx: Context): Type = resType
+ protected def computeSignature(implicit ctx: Context): Signature = resultSignature
+ def derivedExprType(resType: Type)(implicit ctx: Context) =
+ if (resType eq this.resType) this else ExprType(resType)
+ override def computeHash = doHash(resType)
+ }
- 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._
+ final class CachedExprType(resultType: Type) extends ExprType(resultType)
+
+ object ExprType {
+ def apply(resultType: Type)(implicit ctx: Context) = {
+ assertUnerased()
+ unique(new CachedExprType(resultType))
+ }
+ }
- def isJava = false
+ /** The lambda type square:
+ *
+ * LambdaType | TermLambda | TypeLambda
+ * -------------+-------------------+------------------
+ * HKLambda | HKTermLambda | HKTypeLambda
+ * MethodOrPoly | MethodType | PolyType
+ */
+ trait LambdaType extends BindingType with MethodicType { self =>
+ type ThisName <: Name
+ type PInfo <: Type
+ type This <: LambdaType{type PInfo = self.PInfo}
+
+ def paramNames: List[ThisName]
+ def paramInfos: List[PInfo]
+ def resType: Type
+ def newParamRef(n: Int): ParamRef
+
+ override def resultType(implicit ctx: Context) = resType
+
+ def isJava: Boolean = false
def isImplicit = false
- val paramTypes = paramTypesExp(this)
- private[core] val resType = resultTypeExp(this)
- assert(resType.exists)
+ def isDependent(implicit ctx: Context): Boolean
+ def isParamDependent(implicit ctx: Context): Boolean
+
+ final def isTermLambda = isInstanceOf[TermLambda]
+ final def isTypeLambda = isInstanceOf[TypeLambda]
+ final def isHigherKinded = isInstanceOf[TypeProxy]
+
+ lazy val paramRefs: List[ParamRef] = paramNames.indices.toList.map(newParamRef)
+
+ protected def computeSignature(implicit ctx: Context) = resultSignature
+
+ final def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
+ if (isDependent) resultType.substParams(this, argTypes)
+ else resultType
+
+ def companion: LambdaTypeCompanion[ThisName, PInfo, This]
+
+ /** The type `[tparams := paramRefs] tp`, where `tparams` can be
+ * either a list of type parameter symbols or a list of lambda parameters
+ */
+ def integrate(tparams: List[ParamInfo], tp: Type)(implicit ctx: Context): Type =
+ tparams match {
+ case LambdaParam(lam, _) :: _ => tp.subst(lam, this)
+ case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs)
+ }
+
+ final def derivedLambdaType(paramNames: List[ThisName] = this.paramNames,
+ paramInfos: List[PInfo] = this.paramInfos,
+ resType: Type = this.resType)(implicit ctx: Context) =
+ if ((paramNames eq this.paramNames) && (paramInfos eq this.paramInfos) && (resType eq this.resType)) this
+ else newLikeThis(paramNames, paramInfos, resType)
+
+ final def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): This =
+ companion(paramNames)(
+ x => paramInfos.mapConserve(_.subst(this, x).asInstanceOf[PInfo]),
+ x => resType.subst(this, x))
+
+ protected def prefixString: String
+ final override def toString = s"$prefixString($paramNames, $paramInfos, $resType)"
+ }
+
+ abstract class HKLambda extends CachedProxyType with LambdaType {
+ final override def underlying(implicit ctx: Context) = resType
+
+ final override def computeHash = doHash(paramNames, resType, paramInfos)
+
+ // Defined here instead of in LambdaType for efficiency
+ final override def equals(that: Any) = that match {
+ case that: HKLambda =>
+ this.paramNames == that.paramNames &&
+ this.paramInfos == that.paramInfos &&
+ this.resType == that.resType &&
+ (this.companion eq that.companion)
+ case _ =>
+ false
+ }
+ }
+
+ abstract class MethodOrPoly extends CachedGroundType with LambdaType with TermType {
+ final override def computeHash = doHash(paramNames, resType, paramInfos)
+
+ // Defined here instead of in LambdaType for efficiency
+ final override def equals(that: Any) = that match {
+ case that: MethodOrPoly =>
+ this.paramNames == that.paramNames &&
+ this.paramInfos == that.paramInfos &&
+ this.resType == that.resType &&
+ (this.companion eq that.companion)
+ case _ =>
+ false
+ }
+ }
+
+ trait TermLambda extends LambdaType { thisLambdaType =>
+ import DepStatus._
+ type ThisName = TermName
+ type PInfo = Type
+ type This <: TermLambda
override def resultType(implicit ctx: Context): Type =
if (dependencyStatus == FalseDeps) { // dealias all false dependencies
@@ -2347,8 +2453,8 @@ object Types {
}
else resType
- var myDependencyStatus: DependencyStatus = Unknown
- var myParamDependencyStatus: DependencyStatus = Unknown
+ private var myDependencyStatus: DependencyStatus = Unknown
+ private var myParamDependencyStatus: DependencyStatus = Unknown
private def depStatus(initial: DependencyStatus, tp: Type)(implicit ctx: Context): DependencyStatus = {
def combine(x: DependencyStatus, y: DependencyStatus) = {
@@ -2361,7 +2467,7 @@ object Types {
if (status == TrueDeps) status
else
tp match {
- case MethodParam(`thisMethodType`, _) => TrueDeps
+ case TermParamRef(`thisLambdaType`, _) => TrueDeps
case tp: TypeRef =>
val status1 = foldOver(status, tp)
tp.info match { // follow type alias to avoid dependency
@@ -2401,8 +2507,8 @@ object Types {
if (myParamDependencyStatus != Unknown) myParamDependencyStatus
else {
val result =
- if (paramTypes.isEmpty) NoDeps
- else (NoDeps /: paramTypes.tail)(depStatus(_, _))
+ if (paramInfos.isEmpty) NoDeps
+ else (NoDeps /: paramInfos.tail)(depStatus(_, _))
if ((result & Provisional) == 0) myParamDependencyStatus = result
(result & StatusMask).toByte
}
@@ -2418,75 +2524,90 @@ object Types {
*/
def isParamDependent(implicit ctx: Context): Boolean = paramDependencyStatus == TrueDeps
- protected def computeSignature(implicit ctx: Context): Signature =
- resultSignature.prepend(paramTypes, isJava)
+ def newParamRef(n: Int) = TermParamRef(this, n)
+ }
- 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)
- }
+ abstract case class MethodType(paramNames: List[TermName])(
+ paramInfosExp: MethodType => List[Type],
+ resultTypeExp: MethodType => Type)
+ extends MethodOrPoly with TermLambda with NarrowCached { thisMethodType =>
+ import MethodType._
- def instantiate(argTypes: => List[Type])(implicit ctx: Context): Type =
- if (isDependent) resultType.substParams(this, argTypes)
- else resultType
+ type This = MethodType
- override def equals(that: Any) = that match {
- case that: MethodType =>
- this.paramNames == that.paramNames &&
- this.paramTypes == that.paramTypes &&
- this.resType == that.resType
- case _ =>
- false
- }
+ val paramInfos = paramInfosExp(this)
+ val resType = resultTypeExp(this)
+ assert(resType.exists)
- override def computeHash = doHash(paramNames, resType, paramTypes)
+ override def computeSignature(implicit ctx: Context): Signature =
+ resultSignature.prepend(paramInfos, isJava)
protected def prefixString = "MethodType"
- override def toString = s"$prefixString($paramNames, $paramTypes, $resType)"
}
- final class CachedMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
- extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
- override def equals(that: Any) = super.equals(that) && that.isInstanceOf[CachedMethodType]
+ final class CachedMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramInfosExp, resultTypeExp) {
+ def companion = MethodType
}
- final class JavaMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
- extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ final class JavaMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramInfosExp, 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)
override protected def prefixString = "JavaMethodType"
}
- final class ImplicitMethodType(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
- extends MethodType(paramNames)(paramTypesExp, resultTypeExp) {
+ final class ImplicitMethodType(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)
+ extends MethodType(paramNames)(paramInfosExp, 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 =
- apply(paramNames)(_ => paramTypes, _ => resultType)
- def apply(paramTypes: List[Type])(resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- apply(nme.syntheticParamNames(paramTypes.length))(_ => paramTypes, resultTypeExp)
- def apply(paramTypes: List[Type], resultType: Type)(implicit ctx: Context): MethodType =
- apply(nme.syntheticParamNames(paramTypes.length), paramTypes, resultType)
+ abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] {
+ def syntheticParamName(n: Int): N
+
+ @sharable private val memoizedNames = new mutable.HashMap[Int, List[N]]
+ def syntheticParamNames(n: Int): List[N] = synchronized {
+ memoizedNames.getOrElseUpdate(n, (0 until n).map(syntheticParamName).toList)
+ }
+
+ def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT
+ def apply(paramNames: List[N], paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT =
+ apply(paramNames)(_ => paramInfos, _ => resultType)
+ def apply(paramInfos: List[PInfo])(resultTypeExp: LT => Type)(implicit ctx: Context): LT =
+ apply(syntheticParamNames(paramInfos.length))(_ => paramInfos, resultTypeExp)
+ def apply(paramInfos: List[PInfo], resultType: Type)(implicit ctx: Context): LT =
+ apply(syntheticParamNames(paramInfos.length), paramInfos, resultType)
+
+ protected def paramName(param: ParamInfo.Of[N])(implicit ctx: Context): N =
+ param.paramName
+
+ def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(implicit ctx: Context): Type =
+ if (params.isEmpty) resultType
+ else apply(params.map(paramName))(
+ tl => params.map(param => tl.integrate(params, param.paramInfo).asInstanceOf[PInfo]),
+ tl => tl.integrate(params, resultType))
+ }
+
+ abstract class TermLambdaCompanion[LT <: TermLambda]
+ extends LambdaTypeCompanion[TermName, Type, LT] {
+ def syntheticParamName(n: Int) = nme.syntheticParamName(n)
+ }
+
+ abstract class TypeLambdaCompanion[LT <: TypeLambda]
+ extends LambdaTypeCompanion[TypeName, TypeBounds, LT] {
+ def syntheticParamName(n: Int) = tpnme.syntheticTypeParamName(n)
+ }
+
+ abstract class MethodTypeCompanion extends TermLambdaCompanion[MethodType] {
/** Produce method type from parameter symbols, with special mappings for repeated
- * and inline parameters.
+ * and inline parameters:
+ * - replace @repeated annotations on Seq or Array types by <repeated> types
+ * - add @inlineParam to inline call-by-value parameters
*/
def fromSymbols(params: List[Symbol], resultType: Type)(implicit ctx: Context) = {
- /** Replace @repeated annotations on Seq or Array types by <repeated> types */
def translateRepeated(tp: Type): Type = tp match {
case tp @ ExprType(tp1) => tp.derivedExprType(translateRepeated(tp1))
case AnnotatedType(tp, annot) if annot matches defn.RepeatedAnnot =>
@@ -2496,27 +2617,25 @@ object Types {
case tp =>
tp
}
- /** Add @inlineParam to inline call-by-value parameters */
def translateInline(tp: Type): Type = tp match {
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 paramInfo(param: Symbol): Type = {
+ def paramInfo(param: Symbol) = {
val paramType = translateRepeated(param.info)
if (param.is(Inline)) translateInline(paramType) else paramType
}
+
apply(params.map(_.name.asTermName))(
- mt => params.map(param => integrate(paramInfo(param), mt)),
- mt => integrate(resultType, mt))
+ tl => params.map(p => tl.integrate(params, paramInfo(p))),
+ tl => tl.integrate(params, resultType))
}
def checkValid(mt: MethodType)(implicit ctx: Context): mt.type = {
if (Config.checkMethodTypes)
- for ((paramType, idx) <- mt.paramTypes.zipWithIndex)
- paramType.foreachPart {
- case MethodParam(`mt`, j) => assert(j < idx, mt)
+ for ((paramInfo, idx) <- mt.paramInfos.zipWithIndex)
+ paramInfo.foreachPart {
+ case TermParamRef(`mt`, j) => assert(j < idx, mt)
case _ =>
}
mt
@@ -2524,114 +2643,97 @@ object Types {
}
object MethodType extends MethodTypeCompanion {
- 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
+ def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new CachedMethodType(paramNames)(paramInfosExp, resultTypeExp)))
}
object JavaMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- unique(new JavaMethodType(paramNames)(paramTypesExp, resultTypeExp))
+ def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ unique(new JavaMethodType(paramNames)(paramInfosExp, resultTypeExp))
}
object ImplicitMethodType extends MethodTypeCompanion {
- def apply(paramNames: List[TermName])(paramTypesExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
- checkValid(unique(new ImplicitMethodType(paramNames)(paramTypesExp, resultTypeExp)))
+ def apply(paramNames: List[TermName])(paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type)(implicit ctx: Context): MethodType =
+ checkValid(unique(new ImplicitMethodType(paramNames)(paramInfosExp, resultTypeExp)))
}
/** A ternary extractor for MethodType */
object MethodTpe {
def unapply(mt: MethodType)(implicit ctx: Context) =
- Some((mt.paramNames, mt.paramTypes, mt.resultType))
- }
-
- /** A by-name parameter type of the form `=> T`, or the type of a method with no parameter list. */
- abstract case class ExprType(resType: Type)
- extends CachedProxyType with TermType with MethodicType {
- override def resultType(implicit ctx: Context): Type = resType
- override def underlying(implicit ctx: Context): Type = resType
- protected def computeSignature(implicit ctx: Context): Signature = resultSignature
- def derivedExprType(resType: Type)(implicit ctx: Context) =
- if (resType eq this.resType) this else ExprType(resType)
- override def computeHash = doHash(resType)
+ Some((mt.paramNames, mt.paramInfos, mt.resultType))
}
- final class CachedExprType(resultType: Type) extends ExprType(resultType)
-
- object ExprType {
- def apply(resultType: Type)(implicit ctx: Context) = {
- assertUnerased()
- unique(new CachedExprType(resultType))
- }
- }
-
- /** A type lambda of the form `[v_0 X_0, ..., v_n X_n] => T` */
- class PolyType(val paramNames: List[TypeName], val variances: List[Int])(
- paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)
- extends CachedProxyType with BindingType with MethodOrPoly {
-
- /** The bounds of the type parameters */
- val paramBounds: List[TypeBounds] = paramBoundsExp(this)
-
- /** The result type of a PolyType / body of a type lambda */
- val resType: Type = resultTypeExp(this)
-
- assert(resType.isInstanceOf[TermType], this)
- assert(paramNames.nonEmpty)
-
- protected def computeSignature(implicit ctx: Context) = resultSignature
+ trait TypeLambda extends LambdaType {
+ type ThisName = TypeName
+ type PInfo = TypeBounds
+ type This <: TypeLambda
- def isPolymorphicMethodType: Boolean = resType match {
- case _: MethodType => true
- case _ => false
- }
+ def isDependent(implicit ctx: Context): Boolean = true
+ def isParamDependent(implicit ctx: Context): Boolean = true
- /** PolyParam references to all type parameters of this type */
- lazy val paramRefs: List[PolyParam] = paramNames.indices.toList.map(PolyParam(this, _))
+ def newParamRef(n: Int) = TypeParamRef(this, n)
lazy val typeParams: List[LambdaParam] =
paramNames.indices.toList.map(new LambdaParam(this, _))
- override def resultType(implicit ctx: Context) = resType
- override def underlying(implicit ctx: Context) = resType
-
- /** Instantiate result type by substituting parameters with given arguments */
- final def instantiate(argTypes: List[Type])(implicit ctx: Context): Type =
- 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)
-
- def newLikeThis(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): PolyType =
- PolyType.apply(paramNames, variances)(
- x => paramBounds mapConserve (_.subst(this, x).bounds),
- x => resType.subst(this, x))
-
- def derivedPolyType(paramNames: List[TypeName] = this.paramNames,
- paramBounds: List[TypeBounds] = this.paramBounds,
- resType: Type = this.resType)(implicit ctx: Context) =
- if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (resType eq this.resType)) this
- else newLikeThis(paramNames, paramBounds, resType)
+ final def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[Type] =
+ paramInfos.mapConserve(_.substParams(this, argTypes))
- def derivedLambdaAbstraction(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context): Type =
+ def derivedLambdaAbstraction(paramNames: List[TypeName], paramInfos: List[TypeBounds], resType: Type)(implicit ctx: Context): Type =
resType match {
case resType @ TypeAlias(alias) =>
- resType.derivedTypeAlias(newLikeThis(paramNames, paramBounds, alias))
+ resType.derivedTypeAlias(newLikeThis(paramNames, paramInfos, alias))
case resType @ TypeBounds(lo, hi) =>
resType.derivedTypeBounds(
- if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramBounds, lo),
- newLikeThis(paramNames, paramBounds, hi))
+ if (lo.isRef(defn.NothingClass)) lo else newLikeThis(paramNames, paramInfos, lo),
+ newLikeThis(paramNames, paramInfos, hi))
case _ =>
- derivedPolyType(paramNames, paramBounds, resType)
+ derivedLambdaType(paramNames, paramInfos, resType)
}
+ }
+
+ /** A type lambda of the form `[X_0 B_0, ..., X_n B_n] => T`
+ * Variances are encoded in parameter names. A name starting with `+`
+ * designates a covariant parameter, a name starting with `-` designates
+ * a contravariant parameter, and every other name designates a non-variant parameter.
+ *
+ * @param paramNames The names `X_0`, ..., `X_n`
+ * @param paramInfosExp A function that, given the polytype itself, returns the
+ * parameter bounds `B_1`, ..., `B_n`
+ * @param resultTypeExp A function that, given the polytype itself, returns the
+ * result type `T`.
+ */
+ class HKTypeLambda(val paramNames: List[TypeName])(
+ paramInfosExp: HKTypeLambda => List[TypeBounds], resultTypeExp: HKTypeLambda => Type)
+ extends HKLambda with TypeLambda {
+ type This = HKTypeLambda
+ def companion = HKTypeLambda
+
+ val paramInfos: List[TypeBounds] = paramInfosExp(this)
+ val resType: Type = resultTypeExp(this)
+
+ assert(resType.isInstanceOf[TermType], this)
+ assert(paramNames.nonEmpty)
+
+ protected def prefixString = "HKTypeLambda"
+ }
+
+ /** The type of a polymorphic method. It has the same form as HKTypeLambda,
+ * except it applies to terms and parameters do not have variances.
+ */
+ class PolyType(val paramNames: List[TypeName])(
+ paramInfosExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)
+ extends MethodOrPoly with TypeLambda {
+
+ type This = PolyType
+ def companion = PolyType
+
+ val paramInfos: List[TypeBounds] = paramInfosExp(this)
+ val resType: Type = resultTypeExp(this)
+
+ assert(resType.isInstanceOf[TermType], this)
+ assert(paramNames.nonEmpty)
/** Merge nested polytypes into one polytype. nested polytypes are normally not supported
* but can arise as temporary data structures.
@@ -2640,67 +2742,95 @@ object Types {
case that: PolyType =>
val shift = new TypeMap {
def apply(t: Type) = t match {
- case PolyParam(`that`, n) => PolyParam(that, n + paramNames.length)
+ case TypeParamRef(`that`, n) => TypeParamRef(that, n + paramNames.length)
case t => mapOver(t)
}
}
- PolyType(paramNames ++ that.paramNames, variances ++ that.variances)(
- x => this.paramBounds.mapConserve(_.subst(this, x).bounds) ++
- that.paramBounds.mapConserve(shift(_).subst(that, x).bounds),
+ PolyType(paramNames ++ that.paramNames)(
+ x => this.paramInfos.mapConserve(_.subst(this, x).bounds) ++
+ that.paramInfos.mapConserve(shift(_).subst(that, x).bounds),
x => shift(that.resultType).subst(that, x).subst(this, x))
case _ => this
}
- /** 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 =
- tparams match {
- case LambdaParam(poly, _) :: _ => tp.subst(poly, this)
- case tparams: List[Symbol @unchecked] => tp.subst(tparams, paramRefs)
- }
+ protected def prefixString = "PolyType"
+ }
- override def equals(other: Any) = other match {
- case other: PolyType =>
- other.paramNames == this.paramNames &&
- other.paramBounds == this.paramBounds &&
- other.resType == this.resType &&
- other.variances == this.variances
- case _ => false
+ object HKTypeLambda extends TypeLambdaCompanion[HKTypeLambda] {
+ def apply(paramNames: List[TypeName])(
+ paramInfosExp: HKTypeLambda => List[TypeBounds],
+ resultTypeExp: HKTypeLambda => Type)(implicit ctx: Context): HKTypeLambda = {
+ unique(new HKTypeLambda(paramNames)(paramInfosExp, resultTypeExp))
}
- override def toString = s"PolyType($variances, $paramNames, $paramBounds, $resType)"
+ def unapply(tl: HKTypeLambda): Some[(List[LambdaParam], Type)] =
+ Some((tl.typeParams, tl.resType))
+
+ def any(n: Int)(implicit ctx: Context) =
+ apply(syntheticParamNames(n))(
+ pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
- override def computeHash = doHash(variances ::: paramNames, resType, paramBounds)
+ override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName =
+ param.paramName.withVariance(param.paramVariance)
+
+ /** Distributes Lambda inside type bounds. Examples:
+ *
+ * type T[X] = U becomes type T = [X] -> U
+ * type T[X] <: U becomes type T >: Nothign <: ([X] -> U)
+ * type T[X] >: L <: U becomes type T >: ([X] -> L) <: ([X] -> U)
+ */
+ override def fromParams[PI <: ParamInfo.Of[TypeName]](params: List[PI], resultType: Type)(implicit ctx: Context): Type = {
+ def expand(tp: Type) = super.fromParams(params, tp)
+ resultType match {
+ case rt: TypeAlias =>
+ rt.derivedTypeAlias(expand(rt.alias))
+ case rt @ TypeBounds(lo, hi) =>
+ rt.derivedTypeBounds(
+ if (lo.isRef(defn.NothingClass)) lo else expand(lo), expand(hi))
+ case rt =>
+ expand(rt)
+ }
+ }
}
- object PolyType {
- def apply(paramNames: List[TypeName], variances: List[Int])(
- paramBoundsExp: PolyType => List[TypeBounds],
+ object PolyType extends TypeLambdaCompanion[PolyType] {
+ def apply(paramNames: List[TypeName])(
+ paramInfosExp: PolyType => List[TypeBounds],
resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = {
- unique(new PolyType(paramNames, variances)(paramBoundsExp, resultTypeExp))
+ unique(new PolyType(paramNames)(paramInfosExp, resultTypeExp))
}
def unapply(tl: PolyType): Some[(List[LambdaParam], Type)] =
Some((tl.typeParams, tl.resType))
def any(n: Int)(implicit ctx: Context) =
- apply(tpnme.syntheticTypeParamNames(n), List.fill(n)(0))(
+ apply(syntheticParamNames(n))(
pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType)
}
+ private object DepStatus {
+ type DependencyStatus = Byte
+ final val Unknown: DependencyStatus = 0 // not yet computed
+ final val NoDeps: DependencyStatus = 1 // no dependent parameters found
+ final val FalseDeps: DependencyStatus = 2 // all dependent parameters are prefixes of non-depended alias types
+ final val TrueDeps: DependencyStatus = 3 // some truly dependent parameters exist
+ final val StatusMask: DependencyStatus = 3 // the bits indicating actual dependency status
+ final val Provisional: DependencyStatus = 4 // set if dependency status can still change due to type variable instantiations
+ }
+
// ----- 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
- 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 paramVariance(implicit ctx: Context): Int = tl.variances(n)
- def toArg: Type = PolyParam(tl, n)
- def paramRef(implicit ctx: Context): Type = PolyParam(tl, n)
+ case class LambdaParam(tl: TypeLambda, n: Int) extends ParamInfo {
+ type ThisName = TypeName
+ def isTypeParam(implicit ctx: Context) = tl.paramNames.head.isTypeName
+ def paramName(implicit ctx: Context) = tl.paramNames(n)
+ def paramInfo(implicit ctx: Context) = tl.paramInfos(n)
+ def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = paramInfo
+ def paramInfoOrCompleter(implicit ctx: Context): Type = paramInfo
+ def paramVariance(implicit ctx: Context): Int = tl.paramNames(n).variance
+ def toArg: Type = TypeParamRef(tl, n)
+ def paramRef(implicit ctx: Context): Type = TypeParamRef(tl, n)
}
/** A higher kinded type application `C[T_1, ..., T_n]` */
@@ -2715,7 +2845,7 @@ object Types {
override def superType(implicit ctx: Context): Type = {
if (ctx.period != validSuper) {
cachedSuper = tycon match {
- case tp: PolyType => defn.AnyType
+ case tp: HKTypeLambda => defn.AnyType
case tp: TypeVar if !tp.inst.exists =>
// supertype not stable, since underlying might change
return tp.underlying.applyIfParameterized(args)
@@ -2739,9 +2869,9 @@ 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
+ if (tparams.isEmpty) HKTypeLambda.any(args.length).typeParams else tparams
}
def derivedAppliedType(tycon: Type, args: List[Type])(implicit ctx: Context): Type =
@@ -2753,8 +2883,8 @@ object Types {
protected def checkInst(implicit ctx: Context): this.type = {
def check(tycon: Type): Unit = tycon.stripTypeVar match {
case tycon: TypeRef if !tycon.symbol.isClass =>
- case _: PolyParam | _: ErrorType | _: WildcardType =>
- case _: PolyType =>
+ case _: TypeParamRef | _: ErrorType | _: WildcardType =>
+ case _: TypeLambda =>
assert(args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this")
case tycon: AnnotatedType =>
check(tycon.underlying)
@@ -2773,92 +2903,61 @@ object Types {
unique(new CachedHKApply(tycon, args)).checkInst
}
- // ----- Bound types: MethodParam, PolyParam --------------------------
+ // ----- BoundTypes: ParamRef, RecThis ----------------------------------------
abstract class BoundType extends CachedProxyType with ValueType {
type BT <: Type
- def binder: BT
- // Dotty deviation: copyBoundType was copy, but
- // dotty generates copy methods always automatically, and therefore
- // does not accept same-named method definitions in subclasses.
- // Scala2x, on the other hand, requires them (not sure why!)
+ val binder: BT
def copyBoundType(bt: BT): Type
}
- abstract class ParamType extends BoundType {
+ abstract class ParamRef extends BoundType {
+ type BT <: LambdaType
def paramNum: Int
- def paramName: Name
- }
-
- abstract case class MethodParam(binder: MethodType, paramNum: Int) extends ParamType with SingletonType {
- type BT = MethodType
-
- def paramName = binder.paramNames(paramNum)
+ def paramName: binder.ThisName = binder.paramNames(paramNum)
- override def underlying(implicit ctx: Context): Type = binder.paramTypes(paramNum)
- def copyBoundType(bt: BT) = new MethodParamImpl(bt, paramNum)
+ override def underlying(implicit ctx: Context): Type = {
+ val infos = binder.paramInfos
+ if (infos == null) NoType // this can happen if the referenced generic type is not initialized yet
+ else infos(paramNum)
+ }
- // need to customize hashCode and equals to prevent infinite recursion for dep meth types.
- override def computeHash = addDelta(binder.identityHash, paramNum)
+ override def computeHash = doHash(paramNum, binder.identityHash)
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 =
+ try s"ParamRef($paramName)"
+ catch {
+ case ex: IndexOutOfBoundsException => s"ParamRef(<bad index: $paramNum>)"
+ }
}
- class MethodParamImpl(binder: MethodType, paramNum: Int) extends MethodParam(binder, paramNum)
-
- object MethodParam {
- def apply(binder: MethodType, paramNum: Int)(implicit ctx: Context): MethodParam = {
- assertUnerased()
- new MethodParamImpl(binder, paramNum)
- }
+ case class TermParamRef(binder: TermLambda, paramNum: Int) extends ParamRef {
+ type BT = TermLambda
+ def copyBoundType(bt: BT) = TermParamRef(bt, paramNum)
}
- /** TODO Some docs would be nice here! */
- case class PolyParam(binder: PolyType, paramNum: Int) extends ParamType {
- type BT = PolyType
- def copyBoundType(bt: BT) = PolyParam(bt, paramNum)
+ case class TypeParamRef(binder: TypeLambda, paramNum: Int) extends ParamRef {
+ type BT = TypeLambda
+ def copyBoundType(bt: BT) = TypeParamRef(bt, paramNum)
/** Looking only at the structure of `bound`, is one of the following true?
* - fromBelow and param <:< bound
* - !fromBelow and param >:> bound
*/
def occursIn(bound: Type, fromBelow: Boolean)(implicit ctx: Context): Boolean = bound.stripTypeVar match {
- case bound: PolyParam => bound == this
+ case bound: ParamRef => bound == this
case bound: AndOrType =>
def occ1 = occursIn(bound.tp1, fromBelow)
def occ2 = occursIn(bound.tp2, fromBelow)
if (fromBelow == bound.isAnd) occ1 && occ2 else occ1 || occ2
case _ => false
}
-
- def paramName = binder.paramNames(paramNum)
-
- override def underlying(implicit ctx: Context): Type = {
- val bounds = binder.paramBounds
- if (bounds == null) NoType // this can happen if the referenced generic type is not initialized yet
- else bounds(paramNum)
- }
- // no customized hashCode/equals needed because cycle is broken in PolyType
- override def toString =
- try s"PolyParam($paramName)"
- catch {
- case ex: IndexOutOfBoundsException => s"PolyParam(<bad index: $paramNum>)"
- }
-
- override def computeHash = doHash(paramNum, binder.identityHash)
-
- override def equals(that: Any) = that match {
- case that: PolyParam =>
- (this.binder eq that.binder) && this.paramNum == that.paramNum
- case _ =>
- false
- }
}
/** a self-reference to an enclosing recursive type. */
@@ -2929,7 +3028,7 @@ object Types {
* `owningTree` and `owner` are used to determine whether a type-variable can be instantiated
* at some given point. See `Inferencing#interpolateUndetVars`.
*/
- final class TypeVar(val origin: PolyParam, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
+ final class TypeVar(val origin: TypeParamRef, creatorState: TyperState, val bindingTree: untpd.Tree, val owner: Symbol) extends CachedProxyType with ValueType {
/** The permanent instance type of the variable, or NoType is none is given yet */
private[core] var inst: Type = NoType
@@ -3341,9 +3440,8 @@ object Types {
object SAMType {
def zeroParamClass(tp: Type)(implicit ctx: Context): Type = tp match {
case tp: ClassInfo =>
- def zeroParams(tp: Type): Boolean = tp match {
- case pt: PolyType => zeroParams(pt.resultType)
- case mt: MethodType => mt.paramTypes.isEmpty && !mt.resultType.isInstanceOf[MethodType]
+ def zeroParams(tp: Type): Boolean = tp.stripPoly match {
+ case mt: MethodType => mt.paramInfos.isEmpty && !mt.resultType.isInstanceOf[MethodType]
case et: ExprType => true
case _ => false
}
@@ -3426,12 +3524,11 @@ object Types {
tp.derivedClassInfo(pre)
protected def derivedJavaArrayType(tp: JavaArrayType, elemtp: Type): Type =
tp.derivedJavaArrayType(elemtp)
- protected def derivedMethodType(tp: MethodType, formals: List[Type], restpe: Type): Type =
- tp.derivedMethodType(tp.paramNames, formals, restpe)
protected def derivedExprType(tp: ExprType, restpe: Type): Type =
tp.derivedExprType(restpe)
- protected def derivedPolyType(tp: PolyType, pbounds: List[TypeBounds], restpe: Type): Type =
- tp.derivedPolyType(tp.paramNames, pbounds, restpe)
+ // note: currying needed because Scala2 does not support param-dependencies
+ protected def derivedLambdaType(tp: LambdaType)(formals: List[tp.PInfo], restpe: Type): Type =
+ tp.derivedLambdaType(tp.paramNames, formals, restpe)
/** Map this function over given type */
def mapOver(tp: Type): Type = {
@@ -3461,29 +3558,34 @@ object Types {
variance = -variance
derivedTypeBounds(tp, lo1, this(tp.hi))
- case tp: MethodType =>
- def mapOverMethod = {
- variance = -variance
- val ptypes1 = tp.paramTypes mapConserve this
- variance = -variance
- derivedMethodType(tp, ptypes1, this(tp.resultType))
+ case tp: RecType =>
+ derivedRecType(tp, this(tp.parent))
+
+ case tp: TypeVar =>
+ val inst = tp.instanceOpt
+ if (inst.exists) apply(inst) else tp
+
+ case tp: HKApply =>
+ def mapArg(arg: Type, tparam: ParamInfo): Type = {
+ val saved = variance
+ variance *= tparam.paramVariance
+ try this(arg)
+ finally variance = saved
}
- mapOverMethod
+ derivedAppliedType(tp, this(tp.tycon),
+ tp.args.zipWithConserve(tp.typeParams)(mapArg))
case tp: ExprType =>
derivedExprType(tp, this(tp.resultType))
- case tp: PolyType =>
- def mapOverPoly = {
+ case tp: LambdaType =>
+ def mapOverLambda = {
variance = -variance
- val bounds1 = tp.paramBounds.mapConserve(this).asInstanceOf[List[TypeBounds]]
+ val ptypes1 = tp.paramInfos.mapConserve(this).asInstanceOf[List[tp.PInfo]]
variance = -variance
- derivedPolyType(tp, bounds1, this(tp.resultType))
+ derivedLambdaType(tp)(ptypes1, this(tp.resultType))
}
- mapOverPoly
-
- case tp: RecType =>
- derivedRecType(tp, this(tp.parent))
+ mapOverLambda
case tp @ SuperType(thistp, supertp) =>
derivedSuperType(tp, this(thistp), this(supertp))
@@ -3494,21 +3596,7 @@ object Types {
case tp: ClassInfo =>
mapClassInfo(tp)
- case tp: TypeVar =>
- val inst = tp.instanceOpt
- if (inst.exists) apply(inst) else tp
-
- case tp: HKApply =>
- def mapArg(arg: Type, tparam: TypeParamInfo): Type = {
- val saved = variance
- variance *= tparam.paramVariance
- try this(arg)
- finally variance = saved
- }
- derivedAppliedType(tp, this(tp.tycon),
- tp.args.zipWithConserve(tp.typeParams)(mapArg))
-
- case tp: AndOrType =>
+ case tp: AndOrType =>
derivedAndOrType(tp, this(tp.tp1), this(tp.tp2))
case tp: SkolemType =>
@@ -3689,23 +3777,14 @@ object Types {
this(y, hi)
}
- case tp: MethodType =>
- variance = -variance
- val y = foldOver(x, tp.paramTypes)
- variance = -variance
- this(y, tp.resultType)
+ case tp: RecType =>
+ this(x, tp.parent)
case ExprType(restpe) =>
this(x, restpe)
- case tp: PolyType =>
- variance = -variance
- val y = foldOver(x, tp.paramBounds)
- variance = -variance
- this(y, tp.resultType)
-
- case tp: RecType =>
- this(x, tp.parent)
+ case tp: TypeVar =>
+ this(x, tp.underlying)
case SuperType(thistp, supertp) =>
this(this(x, thistp), supertp)
@@ -3714,7 +3793,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
@@ -3730,6 +3809,12 @@ object Types {
}
foldArgs(this(x, tycon), tp.typeParams, args)
+ case tp: LambdaType =>
+ variance = -variance
+ val y = foldOver(x, tp.paramInfos)
+ variance = -variance
+ this(y, tp.resultType)
+
case tp: AndOrType =>
this(this(x, tp.tp1), tp.tp2)
@@ -3739,9 +3824,6 @@ object Types {
case AnnotatedType(underlying, annot) =>
this(applyToAnnot(x, annot), underlying)
- case tp: TypeVar =>
- this(x, tp.underlying)
-
case tp: WildcardType =>
this(x, tp.optBounds)
@@ -3804,9 +3886,7 @@ object Types {
apply(x, tp.tref)
case tp: ConstantType =>
apply(x, tp.underlying)
- case tp: MethodParam =>
- apply(x, tp.underlying)
- case tp: PolyParam =>
+ case tp: ParamRef =>
apply(x, tp.underlying)
case _ =>
foldOver(x, tp)