diff options
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.scala | 10 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/TypeApplications.scala | 24 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/TypeComparer.scala | 16 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/Types.scala | 206 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala | 2 | ||||
-rw-r--r-- | compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 2 |
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())) |