diff options
Diffstat (limited to 'compiler/src/dotty/tools/dotc/core')
12 files changed, 131 insertions, 122 deletions
diff --git a/compiler/src/dotty/tools/dotc/core/Constraint.scala b/compiler/src/dotty/tools/dotc/core/Constraint.scala index 7a0e6dece..a6c21c0d1 100644 --- a/compiler/src/dotty/tools/dotc/core/Constraint.scala +++ b/compiler/src/dotty/tools/dotc/core/Constraint.scala @@ -14,7 +14,7 @@ import config.Printers.constr * over values of the following types: * * - TypeLambda A constraint constrains the type parameters of a set of TypeLambdas - * - TypeParamRef The parameters of the constrained polytypes + * - TypeParamRef The parameters of the constrained type lambdas * - TypeVar Every constrained parameter might be associated with a TypeVar * that has the TypeParamRef as origin. */ @@ -120,10 +120,10 @@ abstract class Constraint extends Showable { /** A new constraint with all entries coming from `pt` removed. */ def remove(pt: TypeLambda)(implicit ctx: Context): This - /** The polytypes constrained by this constraint */ - def domainPolys: List[TypeLambda] + /** The type lambdas constrained by this constraint */ + def domainLambdas: List[TypeLambda] - /** The polytype parameters constrained by this constraint */ + /** The type lambda parameters constrained by this constraint */ def domainParams: List[TypeParamRef] /** Check whether predicate holds for all parameters in constraint */ diff --git a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala index ab176b632..64621ec94 100644 --- a/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala +++ b/compiler/src/dotty/tools/dotc/core/ConstraintHandling.scala @@ -42,10 +42,10 @@ trait ConstraintHandling { */ protected var homogenizeArgs = false - /** We are currently comparing polytypes. Used as a flag for + /** We are currently comparing type lambdas. Used as a flag for * optimization: when `false`, no need to do an expensive `pruneLambdaParams` */ - protected var comparedPolyTypes: Set[PolyType] = Set.empty + protected var comparedTypeLambdas: Set[TypeLambda] = Set.empty private def addOneBound(param: TypeParamRef, bound: Type, isUpper: Boolean): Boolean = !constraint.contains(param) || { @@ -306,21 +306,21 @@ trait ConstraintHandling { if (e.exists) e.bounds else param.binder.paramInfos(param.paramNum) } - /** Add polytype `pt`, possibly with type variables `tvars`, to current constraint + /** Add type lambda `tl`, possibly with type variables `tvars`, to current constraint * and propagate all bounds. * @param tvars See Constraint#add */ - def addToConstraint(pt: PolyType, tvars: List[TypeVar]): Unit = + def addToConstraint(tl: TypeLambda, tvars: List[TypeVar]): Unit = assert { - checkPropagated(i"initialized $pt") { - constraint = constraint.add(pt, tvars) - pt.paramNames.indices.forall { i => - val param = TypeParamRef(pt, i) + checkPropagated(i"initialized $tl") { + constraint = constraint.add(tl, tvars) + tl.paramNames.indices.forall { i => + val param = TypeParamRef(tl, i) val bounds = constraint.nonParamBounds(param) val lower = constraint.lower(param) val upper = constraint.upper(param) if (lower.nonEmpty && !bounds.lo.isRef(defn.NothingClass) || - upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr.println(i"INIT*** $pt") + upper.nonEmpty && !bounds.hi.isRef(defn.AnyClass)) constr.println(i"INIT*** $tl") lower.forall(addOneBound(_, bounds.hi, isUpper = true)) && upper.forall(addOneBound(_, bounds.lo, isUpper = false)) } @@ -357,10 +357,10 @@ trait ConstraintHandling { * missing. */ def pruneLambdaParams(tp: Type) = - if (comparedPolyTypes.nonEmpty) { + if (comparedTypeLambdas.nonEmpty) { val approx = new ApproximatingTypeMap { def apply(t: Type): Type = t match { - case t @ TypeParamRef(pt: PolyType, n) if comparedPolyTypes contains pt => + case t @ TypeParamRef(pt: TypeLambda, n) if comparedTypeLambdas contains pt => val effectiveVariance = if (fromBelow) -variance else variance val bounds = pt.paramInfos(n) if (effectiveVariance > 0) bounds.lo diff --git a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala index 2dff39c37..84b0bfc6d 100644 --- a/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/compiler/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -112,17 +112,17 @@ import OrderingConstraint._ * @param boundsMap a map from TypeLambda to arrays. * Each array contains twice the number of entries as there a type parameters * in the TypeLambda. The first half of the array contains the type bounds that constrain the - * polytype's type parameters. The second half might contain type variables that + * lambda's type parameters. The second half might contain type variables that * track the corresponding parameters, or is left empty (filled with nulls). * An instantiated type parameter is represented by having its instance type in * the corresponding array entry. The dual use of arrays for poly params * and typevars is to save space and hopefully gain some speed. * * @param lowerMap a map from TypeLambdas to arrays. Each array entry corresponds - * to a parameter P of the polytype; it contains all constrained parameters + * to a parameter P of the type lambda; it contains all constrained parameters * Q that are known to be smaller than P, i.e. Q <: P. * @param upperMap a map from TypeLambdas to arrays. Each array entry corresponds - * to a parameter P of the polytype; it contains all constrained parameters + * to a parameter P of the type lambda; it contains all constrained parameters * Q that are known to be greater than P, i.e. P <: Q. */ class OrderingConstraint(private val boundsMap: ParamBounds, @@ -456,7 +456,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ---------- Exploration -------------------------------------------------------- - def domainPolys: List[TypeLambda] = boundsMap.keys + def domainLambdas: List[TypeLambda] = boundsMap.keys def domainParams: List[TypeParamRef] = for { @@ -584,7 +584,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, val uninstVarsText = " uninstVars = " ~ Text(uninstVars map (_.toText(printer)), ", ") ~ ";" val constrainedText = - " constrained types = " ~ Text(domainPolys map (_.toText(printer)), ", ") + " constrained types = " ~ Text(domainLambdas map (_.toText(printer)), ", ") val boundsText = " bounds = " ~ { val assocs = @@ -614,8 +614,8 @@ class OrderingConstraint(private val boundsMap: ParamBounds, case _ =>" := " + tp } val constrainedText = - " constrained types = " + domainPolys.mkString("\n") - val boundsText = + " constrained types = " + domainLambdas.mkString("\n") + val boundsText = domainLambdas " bounds = " + { val assocs = for (param <- domainParams) diff --git a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala index f824c3e9c..46e378fc2 100644 --- a/compiler/src/dotty/tools/dotc/core/ParamInfo.scala +++ b/compiler/src/dotty/tools/dotc/core/ParamInfo.scala @@ -1,21 +1,23 @@ package dotty.tools.dotc.core -import Names.TypeName +import Names.Name import Contexts.Context -import Types.{Type, TypeBounds} +import Types.Type /** A common super trait of Symbol and LambdaParam. * Used to capture the attributes of type parameters which can be implemented as either. */ trait ParamInfo { + type ThisName <: Name + /** Is this the info of a type parameter? Will return `false` for symbols * that are not type parameters. */ def isTypeParam(implicit ctx: Context): Boolean /** The name of the type parameter */ - def paramName(implicit ctx: Context): TypeName + def paramName(implicit ctx: Context): ThisName /** The info of the type parameter */ def paramInfo(implicit ctx: Context): Type @@ -37,4 +39,8 @@ trait ParamInfo { /** A type that refers to the parameter */ def paramRef(implicit ctx: Context): Type +} + +object ParamInfo { + type Of[N] = ParamInfo { type ThisName = N } }
\ No newline at end of file diff --git a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala index c126b5500..0ce61de95 100644 --- a/compiler/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/compiler/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1146,7 +1146,7 @@ object SymDenotations { case tp: NamedType => hasSkolems(tp.prefix) case tp: RefinedType => hasSkolems(tp.parent) || hasSkolems(tp.refinedInfo) case tp: RecType => hasSkolems(tp.parent) - case tp: PolyType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: TypeLambda => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: MethodType => tp.paramInfos.exists(hasSkolems) || hasSkolems(tp.resType) case tp: ExprType => hasSkolems(tp.resType) case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems) diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 705b2c133..a3c8e54b2 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -513,11 +513,11 @@ object Symbols { */ def pos: Position = if (coord.isPosition) coord.toPosition else NoPosition - // ParamInfo methods + // ParamInfo types and methods def isTypeParam(implicit ctx: Context) = denot.is(TypeParam) - def paramName(implicit ctx: Context) = name.asTypeName + def paramName(implicit ctx: Context) = name.asInstanceOf[ThisName] def paramInfo(implicit ctx: Context) = denot.info.bounds - def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this) + def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context) = pre.memberInfo(this).bounds 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 3a63c16db..82b184dbc 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeApplications.scala @@ -21,6 +21,8 @@ import java.util.NoSuchElementException object TypeApplications { + type TypeParamInfo = ParamInfo.Of[TypeName] + /** Assert type is not a TypeBounds instance and return it unchanged */ val noBounds = (tp: Type) => tp match { case tp: TypeBounds => throw new AssertionError("no TypeBounds allowed") @@ -47,14 +49,14 @@ object TypeApplications { /** Does the variance of type parameter `tparam1` conform to the variance of type parameter `tparam2`? */ - def varianceConforms(tparam1: ParamInfo, tparam2: ParamInfo)(implicit ctx: Context): Boolean = + def varianceConforms(tparam1: TypeParamInfo, tparam2: TypeParamInfo)(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[ParamInfo], tparams2: List[ParamInfo])(implicit ctx: Context): Boolean = + def variancesConform(tparams1: List[TypeParamInfo], tparams2: List[TypeParamInfo])(implicit ctx: Context): Boolean = tparams1.corresponds(tparams2)(varianceConforms) /** Extractor for @@ -73,7 +75,7 @@ object TypeApplications { } def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = tp match { - case tp @ PolyType(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) + case tp @ PolyType/*###*/(tparams, AppliedType(fn: TypeRef, args)) if (args == tparams.map(_.toArg)) => Some(fn) case _ => None } } @@ -96,7 +98,7 @@ object TypeApplications { refinements = rt :: refinements tycon = rt.parent.stripTypeVar } - def collectArgs(tparams: List[ParamInfo], + def collectArgs(tparams: List[TypeParamInfo], refinements: List[RefinedType], argBuf: mutable.ListBuffer[Type]): Option[(Type, List[Type])] = refinements match { case Nil if tparams.isEmpty && argBuf.nonEmpty => @@ -117,7 +119,7 @@ object TypeApplications { /** Adapt all arguments to possible higher-kinded type parameters using etaExpandIfHK */ - def EtaExpandIfHK(tparams: List[ParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = + def EtaExpandIfHK(tparams: List[TypeParamInfo], args: List[Type])(implicit ctx: Context): List[Type] = if (tparams.isEmpty) args else args.zipWithConserve(tparams)((arg, tparam) => arg.EtaExpandIfHK(tparam.paramInfoOrCompleter)) @@ -160,7 +162,7 @@ object TypeApplications { * result type. Using this mode, we can guarantee that `appliedTo` will never * produce a higher-kinded application with a type lambda as type constructor. */ - class Reducer(tycon: PolyType, args: List[Type])(implicit ctx: Context) extends TypeMap { + class Reducer(tycon: TypeLambda, args: List[Type])(implicit ctx: Context) extends TypeMap { private var available = (0 until args.length).toSet var allReplaced = true def hasWildcardArg(p: TypeParamRef) = @@ -209,11 +211,11 @@ 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[ParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { + final def typeParams(implicit ctx: Context): List[TypeParamInfo] = /*>|>*/ track("typeParams") /*<|<*/ { self match { case self: ClassInfo => self.cls.typeParams - case self: PolyType => + case self: TypeLambda => self.typeParams case self: TypeRef => val tsym = self.symbol @@ -236,7 +238,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[ParamInfo] = + final def hkTypeParams(implicit ctx: Context): List[TypeParamInfo] = if (isHK) typeParams else Nil /** If `self` is a generic class, its type parameter symbols, otherwise Nil */ @@ -251,7 +253,7 @@ class TypeApplications(val self: Type) extends AnyVal { def isHK(implicit ctx: Context): Boolean = self.dealias match { case self: TypeRef => self.info.isHK case self: RefinedType => false - case self: PolyType => true + case self: TypeLambda => true case self: SingletonType => false case self: TypeVar => // Using `origin` instead of `underlying`, as is done for typeParams, @@ -274,16 +276,9 @@ class TypeApplications(val self: Type) extends AnyVal { * * type T[X] = U becomes type T = [X] -> U * type T[X] >: L <: U becomes type T >: L <: ([X] -> U) - * - * TODO: Handle parameterized lower bounds */ - 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.paramInfo).bounds), - tl => tl.lifted(tparams, tp)) + def LambdaAbstract(tparams: List[TypeParamInfo])(implicit ctx: Context): Type = { + def expand(tp: Type) = PolyType/*HKTypeLambda*/.fromParams(tparams, tp) if (tparams.isEmpty) self else self match { case self: TypeAlias => @@ -363,10 +358,10 @@ class TypeApplications(val self: Type) extends AnyVal { if (hkParams.isEmpty) self else { def adaptArg(arg: Type): Type = arg match { - case arg @ PolyType(tparams, body) if + case arg @ PolyType(tparams, body) if /*###*/ !tparams.corresponds(hkParams)(_.paramVariance == _.paramVariance) && tparams.corresponds(hkParams)(varianceConforms) => - PolyType( + PolyType(/*###*/ (tparams, hkParams).zipped.map((tparam, hkparam) => tparam.paramName.withVariance(hkparam.paramVariance)))( tl => arg.paramInfos.map(_.subst(arg, tl).bounds), @@ -410,7 +405,7 @@ class TypeApplications(val self: Type) extends AnyVal { val dealiased = stripped.safeDealias if (args.isEmpty || ctx.erasedTypes) self else dealiased match { - case dealiased: PolyType => + case dealiased: TypeLambda => def tryReduce = if (!args.exists(_.isInstanceOf[TypeBounds])) { val followAlias = Config.simplifyApplications && { diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index a4ea1d28f..7698986d5 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -428,9 +428,9 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { compareRec case tp2 @ HKApply(tycon2, args2) => compareHkApply2(tp1, tp2, tycon2, args2) - case tp2 @ PolyType(tparams2, body2) => + case tp2 @ PolyType(tparams2, body2) =>/*###*/ def compareHkLambda: Boolean = tp1.stripTypeVar match { - case tp1 @ PolyType(tparams1, body1) => + case tp1 @ PolyType(tparams1, body1) =>/*###*/ /* Don't compare bounds of lambdas under language:Scala2, or t2994 will fail * The issue is that, logically, bounds should compare contravariantly, * but that would invalidate a pattern exploited in t2994: @@ -448,14 +448,14 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { ctx.scala2Mode || tparams1.corresponds(tparams2)((tparam1, tparam2) => isSubType(tparam2.paramInfo.subst(tp2, tp1), tparam1.paramInfo)) - val saved = comparedPolyTypes - comparedPolyTypes += tp1 - comparedPolyTypes += tp2 + val saved = comparedTypeLambdas + comparedTypeLambdas += tp1 + comparedTypeLambdas += tp2 try variancesConform(tparams1, tparams2) && boundsOK && isSubType(body1, body2.subst(tp2, tp1)) - finally comparedPolyTypes = saved + finally comparedTypeLambdas = saved case _ => if (!tp1.isHK) { tp2 match { @@ -669,8 +669,8 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { val tparams1 = tparams1a.drop(lengthDiff) variancesConform(tparams1, tparams) && { if (lengthDiff > 0) - tycon1b = PolyType(tparams1.map(_.paramName))( - tl => tparams1.map(tparam => tl.lifted(tparams, tparam.paramInfo).bounds), + tycon1b = PolyType(tparams1.map(_.paramName))(/*###*/ + tl => tparams1.map(tparam => tl.integrate(tparams, tparam.paramInfo).bounds), tl => tycon1a.appliedTo(args1.take(lengthDiff) ++ tparams1.indices.toList.map(TypeParamRef(tl, _)))) (ctx.mode.is(Mode.TypevarsMissContext) || @@ -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[ParamInfo], p: Type => Boolean): Boolean = { + private def testLifted(tp1: Type, tp2: Type, tparams: List[TypeParamInfo], p: Type => Boolean): Boolean = { val classBounds = tp2.classSymbols def recur(bcs: List[ClassSymbol]): Boolean = bcs match { case bc :: bcs1 => @@ -1216,7 +1216,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Form a normalized conjunction of two types. * Note: For certain types, `&` is distributed inside the type. This holds for * all types which are not value types (e.g. TypeBounds, ClassInfo, - * ExprType, MethodType, PolyType). Also, when forming an `&`, + * ExprType, LambdaType). Also, when forming an `&`, * instantiated TypeVars are dereferenced and annotations are stripped. * Finally, refined types with the same refined name are * opportunistically merged. @@ -1245,7 +1245,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { /** Form a normalized conjunction of two types. * Note: For certain types, `|` is distributed inside the type. This holds for * all types which are not value types (e.g. TypeBounds, ClassInfo, - * ExprType, MethodType, PolyType). Also, when forming an `|`, + * ExprType, LambdaType). Also, when forming an `|`, * instantiated TypeVars are dereferenced and annotations are stripped. * * Sometimes, the disjunction of two types cannot be formed because @@ -1280,16 +1280,16 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { else if (tparams2.isEmpty) original(tp1.appliedTo(tp1.typeParams.map(_.paramInfoAsSeenFrom(tp1))), tp2) else - PolyType( + PolyType(/*###*/ paramNames = (tpnme.syntheticTypeParamNames(tparams1.length), tparams1, tparams2) .zipped.map((pname, tparam1, tparam2) => pname.withVariance((tparam1.paramVariance + tparam2.paramVariance) / 2)))( paramInfosExp = tl => (tparams1, tparams2).zipped.map((tparam1, tparam2) => - tl.lifted(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds & - tl.lifted(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds), + tl.integrate(tparams1, tparam1.paramInfoAsSeenFrom(tp1)).bounds & + tl.integrate(tparams2, tparam2.paramInfoAsSeenFrom(tp2)).bounds), resultTypeExp = tl => - original(tl.lifted(tparams1, tp1).appliedTo(tl.paramRefs), - tl.lifted(tparams2, tp2).appliedTo(tl.paramRefs))) + original(tl.integrate(tparams1, tp1).appliedTo(tl.paramRefs), + tl.integrate(tparams2, tp2).appliedTo(tl.paramRefs))) } /** Try to distribute `&` inside type, detect and handle conflicts diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 6c9046c20..a7401f6f9 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -65,12 +65,12 @@ object Types { * | +- ExprType * | +- AnnotatedType * | +- TypeVar - * | +- PolyType + * | +- HKLambda --------- PolyType * | * +- GroundType -+- AndType * +- OrType - * +- MethodType -----+- ImplicitMethodType - * | +- JavaMethodType + * +- MethodOrPoly ----- MethodType ---+- ImplicitMethodType + * | +- JavaMethodType * +- ClassInfo * | * +- NoType @@ -814,6 +814,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,31 +1094,27 @@ object Types { } /** The parameter types of a PolyType or MethodType, Empty list for others */ - final def paramInfoss(implicit ctx: Context): List[List[Type]] = this match { + final def paramInfoss(implicit ctx: Context): List[List[Type]] = stripPoly match { case mt: MethodType => mt.paramInfos :: mt.resultType.paramInfoss - case pt: TypeLambda => pt.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: TypeLambda => pt.resultType.paramNamess case _ => Nil } /** The parameter types in the first parameter section of a generic type or MethodType, Empty list for others */ - final def firstParamTypes(implicit ctx: Context): List[Type] = this match { + final def firstParamTypes(implicit ctx: Context): List[Type] = stripPoly match { case mt: MethodType => mt.paramInfos - case pt: TypeLambda => pt.resultType.firstParamTypes case _ => Nil } /** Is this either not a method at all, or a parameterless method? */ - final def isParameterless(implicit ctx: Context): Boolean = this match { + final def isParameterless(implicit ctx: Context): Boolean = stripPoly match { case mt: MethodType => false - case pt: TypeLambda => pt.resultType.isParameterless case _ => true } @@ -1122,9 +1124,8 @@ object Types { /** 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 } @@ -2337,10 +2338,10 @@ object Types { /** The lambda type square: * - * LambdaType | TermLambda | TypeLambda - * ------------+-------------------+------------------ - * HKLambda | HKTermLambda | HKTypeLambda - * StarLambda | MethodType | PolyType + * LambdaType | TermLambda | TypeLambda + * -------------+-------------------+------------------ + * HKLambda | HKTermLambda | HKTypeLambda + * MethodOrPoly | MethodType | PolyType */ trait LambdaType extends BindingType with MethodicType { self => type ThisName <: Name @@ -2370,6 +2371,15 @@ object Types { protected 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) = @@ -2400,7 +2410,7 @@ object Types { final override def underlying(implicit ctx: Context) = resType } - abstract class StarLambda extends CachedGroundType with LambdaType with TermType { + abstract class MethodOrPoly extends CachedGroundType with LambdaType with TermType { final override def computeHash = doHash(paramNames, resType, paramInfos) } @@ -2504,7 +2514,7 @@ object Types { abstract case class MethodType(paramNames: List[TermName])( paramInfosExp: MethodType => List[Type], resultTypeExp: MethodType => Type) - extends StarLambda with TermLambda with NarrowCached { thisMethodType => + extends MethodOrPoly with TermLambda with NarrowCached { thisMethodType => import MethodType._ type This = MethodType @@ -2544,14 +2554,25 @@ object Types { } abstract class LambdaTypeCompanion[N <: Name, PInfo <: Type, LT <: LambdaType] { - def apply(paramNames: List[N])(paramInfosExp: LT => List[PInfo], resultTypeExp: LT => Type)(implicit ctx: Context): LT def syntheticParamNames(n: Int): List[N] + + 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 + protected def paramInfo(param: ParamInfo.Of[N])(implicit ctx: Context): Type = + param.paramInfo + + def fromParams[PI <: ParamInfo.Of[N]](params: List[PI], resultType: Type)(implicit ctx: Context): LT = + apply(params.map(paramName))( + tl => params.map(param => tl.integrate(params, paramInfo(param)).asInstanceOf[PInfo]), + tl => tl.integrate(params, resultType)) } abstract class TermLambdaCompanion[LT <: TermLambda] @@ -2567,10 +2588,11 @@ object Types { 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 => @@ -2580,21 +2602,18 @@ 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): Type = - tp.subst(params, params.indices.toList.map(mt.newParamRef)) - - 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 = { @@ -2670,15 +2689,6 @@ object Types { assert(resType.isInstanceOf[TermType], this) assert(paramNames.nonEmpty) - /** 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[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) - } - protected def prefixString = "HKTypeLambda" } @@ -2726,15 +2736,6 @@ object Types { 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[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) - } - protected def prefixString = "PolyType" } @@ -2751,6 +2752,9 @@ object Types { def any(n: Int)(implicit ctx: Context) = apply(syntheticParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) + + override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName = + param.paramName.withVariance(param.paramVariance) } object PolyType extends TypeLambdaCompanion[PolyType] { @@ -2766,6 +2770,9 @@ object Types { def any(n: Int)(implicit ctx: Context) = apply(syntheticParamNames(n))( pt => List.fill(n)(TypeBounds.empty), pt => defn.AnyType) + + override def paramName(param: ParamInfo.Of[TypeName])(implicit ctx: Context): TypeName = + param.paramName.withVariance(param.paramVariance) //### } private object DepStatus { @@ -2782,10 +2789,11 @@ object Types { /** The parameter of a type lambda */ 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): TypeName = tl.paramNames(n) - def paramInfo(implicit ctx: Context): Type = tl.paramInfos(n) - def paramInfoAsSeenFrom(pre: Type)(implicit ctx: Context): Type = paramInfo + 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) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index 3ab984209..4c600564d 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -253,7 +253,7 @@ class TreePickler(pickler: TastyPickler) { case tpe: ExprType => writeByte(BYNAMEtype) pickleType(tpe.underlying) - case tpe: PolyType => + case tpe: TypeLambda => writeByte(POLYtype) pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramInfos) case tpe: MethodType if richTypes => diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index db3ca83b9..e751e99fe 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -38,7 +38,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle /** A map from addresses of type entries to the types they define. * Currently only populated for types that might be recursively referenced - * from within themselves (i.e. RefinedTypes, PolyTypes, MethodTypes). + * from within themselves (i.e. RecTypes, LambdaTypes). */ private val typeAtAddr = new mutable.HashMap[Addr, Type] @@ -283,7 +283,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table, posUnpickle result case PARAMtype => readTypeRef() match { - case binder: PolyType => TypeParamRef(binder, readNat()) + case binder: TypeLambda => binder.newParamRef(readNat()) case binder: MethodType => binder.newParamRef(readNat()) } case CLASSconst => diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index d34bc240f..34cbf4677 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -42,7 +42,7 @@ object Scala2Unpickler { /** Convert temp poly type to poly type and leave other types alone. */ def translateTempPoly(tp: Type)(implicit ctx: Context): Type = tp match { - case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams) + case TempPolyType(tparams, restpe) => restpe.LambdaAbstract(tparams) // PolyType.fromParams(tparams, restpe) case tp => tp } @@ -745,7 +745,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas TempClassInfoType(until(end, readTypeRef), symScope(clazz), clazz) case METHODtpe | IMPLICITMETHODtpe => val restpe = readTypeRef() - val params = until(end, readSymbolRef) + val params = until(end, readSymbolRef).asInstanceOf[List[TermSymbol]] def isImplicit = tag == IMPLICITMETHODtpe || params.nonEmpty && (params.head is Implicit) |