diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/Constraint.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/OrderingConstraint.scala | 48 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TypeComparer.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/TyperState.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 107 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/printing/PlainPrinter.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/FullParameterization.scala | 10 | ||||
-rw-r--r-- | src/dotty/tools/dotc/transform/PostTyper.scala | 4 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Checking.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/ProtoTypes.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/typer/Variances.scala | 2 |
16 files changed, 124 insertions, 102 deletions
diff --git a/src/dotty/tools/dotc/core/Constraint.scala b/src/dotty/tools/dotc/core/Constraint.scala index 19f93ce47..38f714131 100644 --- a/src/dotty/tools/dotc/core/Constraint.scala +++ b/src/dotty/tools/dotc/core/Constraint.scala @@ -23,7 +23,7 @@ abstract class Constraint extends Showable { type This <: Constraint /** Does the constraint's domain contain the type parameters of `pt`? */ - def contains(pt: PolyType): Boolean + def contains(pt: GenericType): Boolean /** Does the constraint's domain contain the type parameter `param`? */ def contains(param: PolyParam): Boolean @@ -79,7 +79,7 @@ abstract class Constraint extends Showable { * satisfiability but will solved to give instances of * type variables. */ - def add(poly: PolyType, tvars: List[TypeVar])(implicit ctx: Context): This + def add(poly: GenericType, tvars: List[TypeVar])(implicit ctx: Context): This /** A new constraint which is derived from this constraint by updating * the entry for parameter `param` to `tp`. @@ -122,13 +122,13 @@ abstract class Constraint extends Showable { * entry array, but is going to be removed at the same step, * or -1 if no such parameter exists. */ - def isRemovable(pt: PolyType, removedParam: Int = -1): Boolean + def isRemovable(pt: GenericType, removedParam: Int = -1): Boolean /** A new constraint with all entries coming from `pt` removed. */ - def remove(pt: PolyType)(implicit ctx: Context): This + def remove(pt: GenericType)(implicit ctx: Context): This /** The polytypes constrained by this constraint */ - def domainPolys: List[PolyType] + def domainPolys: List[GenericType] /** The polytype parameters constrained by this constraint */ def domainParams: List[PolyParam] diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 5db9a6b0d..8d020a428 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -86,17 +86,17 @@ class Definitions { } private def newPolyMethod(cls: ClassSymbol, name: TermName, typeParamCount: Int, - resultTypeFn: PolyType => Type, flags: FlagSet = EmptyFlags) = { + resultTypeFn: GenericType => Type, flags: FlagSet = EmptyFlags) = { val tparamNames = tpnme.syntheticTypeParamNames(typeParamCount) val tparamBounds = tparamNames map (_ => TypeBounds.empty) val ptype = PolyType(tparamNames)(_ => tparamBounds, resultTypeFn) newMethod(cls, name, ptype, flags) } - private def newT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) = + private def newT1ParameterlessMethod(cls: ClassSymbol, name: TermName, resultTypeFn: GenericType => Type, flags: FlagSet) = newPolyMethod(cls, name, 1, resultTypeFn, flags) - private def newT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: PolyType => Type, flags: FlagSet) = + private def newT1EmptyParamsMethod(cls: ClassSymbol, name: TermName, resultTypeFn: GenericType => Type, flags: FlagSet) = newPolyMethod(cls, name, 1, pt => MethodType(Nil, resultTypeFn(pt)), flags) private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[TypeRef] = { diff --git a/src/dotty/tools/dotc/core/OrderingConstraint.scala b/src/dotty/tools/dotc/core/OrderingConstraint.scala index e818862cb..d9f6f5721 100644 --- a/src/dotty/tools/dotc/core/OrderingConstraint.scala +++ b/src/dotty/tools/dotc/core/OrderingConstraint.scala @@ -15,10 +15,10 @@ import reflect.ClassTag object OrderingConstraint { /** The type of `OrderingConstraint#boundsMap` */ - type ParamBounds = SimpleMap[PolyType, Array[Type]] + type ParamBounds = SimpleMap[GenericType, Array[Type]] /** The type of `OrderingConstraint#lowerMap`, `OrderingConstraint#upperMap` */ - type ParamOrdering = SimpleMap[PolyType, Array[List[PolyParam]]] + type ParamOrdering = SimpleMap[GenericType, Array[List[PolyParam]]] /** A new constraint with given maps */ private def newConstraint(boundsMap: ParamBounds, lowerMap: ParamOrdering, upperMap: ParamOrdering)(implicit ctx: Context) : OrderingConstraint = { @@ -30,11 +30,11 @@ object OrderingConstraint { /** A lens for updating a single entry array in one of the three constraint maps */ abstract class ConstraintLens[T <: AnyRef: ClassTag] { - def entries(c: OrderingConstraint, poly: PolyType): Array[T] - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[T])(implicit ctx: Context): OrderingConstraint + def entries(c: OrderingConstraint, poly: GenericType): Array[T] + def updateEntries(c: OrderingConstraint, poly: GenericType, entries: Array[T])(implicit ctx: Context): OrderingConstraint def initial: T - def apply(c: OrderingConstraint, poly: PolyType, idx: Int) = { + def apply(c: OrderingConstraint, poly: GenericType, idx: Int) = { val es = entries(c, poly) if (es == null) initial else es(idx) } @@ -45,7 +45,7 @@ object OrderingConstraint { * parts of `current` which are not shared by `prev`. */ def update(prev: OrderingConstraint, current: OrderingConstraint, - poly: PolyType, idx: Int, entry: T)(implicit ctx: Context): OrderingConstraint = { + poly: GenericType, idx: Int, entry: T)(implicit ctx: Context): OrderingConstraint = { var es = entries(current, poly) if (es != null && (es(idx) eq entry)) current else { @@ -70,7 +70,7 @@ object OrderingConstraint { update(prev, current, param.binder, param.paramNum, entry) def map(prev: OrderingConstraint, current: OrderingConstraint, - poly: PolyType, idx: Int, f: T => T)(implicit ctx: Context): OrderingConstraint = + poly: GenericType, idx: Int, f: T => T)(implicit ctx: Context): OrderingConstraint = update(prev, current, poly, idx, f(apply(current, poly, idx))) def map(prev: OrderingConstraint, current: OrderingConstraint, @@ -79,25 +79,25 @@ object OrderingConstraint { } val boundsLens = new ConstraintLens[Type] { - def entries(c: OrderingConstraint, poly: PolyType): Array[Type] = + def entries(c: OrderingConstraint, poly: GenericType): Array[Type] = c.boundsMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[Type])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: GenericType, entries: Array[Type])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap.updated(poly, entries), c.lowerMap, c.upperMap) def initial = NoType } val lowerLens = new ConstraintLens[List[PolyParam]] { - def entries(c: OrderingConstraint, poly: PolyType): Array[List[PolyParam]] = + def entries(c: OrderingConstraint, poly: GenericType): Array[List[PolyParam]] = c.lowerMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: GenericType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap.updated(poly, entries), c.upperMap) def initial = Nil } val upperLens = new ConstraintLens[List[PolyParam]] { - def entries(c: OrderingConstraint, poly: PolyType): Array[List[PolyParam]] = + def entries(c: OrderingConstraint, poly: GenericType): Array[List[PolyParam]] = c.upperMap(poly) - def updateEntries(c: OrderingConstraint, poly: PolyType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint = + def updateEntries(c: OrderingConstraint, poly: GenericType, entries: Array[List[PolyParam]])(implicit ctx: Context): OrderingConstraint = newConstraint(c.boundsMap, c.lowerMap, c.upperMap.updated(poly, entries)) def initial = Nil } @@ -147,7 +147,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ----------- Contains tests -------------------------------------------------- - def contains(pt: PolyType): Boolean = boundsMap(pt) != null + def contains(pt: GenericType): Boolean = boundsMap(pt) != null def contains(param: PolyParam): Boolean = { val entries = boundsMap(param.binder) @@ -278,7 +278,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, stripParams(tp, paramBuf, isUpper) .orElse(if (isUpper) defn.AnyType else defn.NothingType) - def add(poly: PolyType, tvars: List[TypeVar])(implicit ctx: Context): This = { + def add(poly: GenericType, tvars: List[TypeVar])(implicit ctx: Context): This = { assert(!contains(poly)) val nparams = poly.paramNames.length val entries1 = new Array[Type](nparams * 2) @@ -291,7 +291,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, * Update all bounds to be normalized and update ordering to account for * dependent parameters. */ - private def init(poly: PolyType)(implicit ctx: Context): This = { + private def init(poly: GenericType)(implicit ctx: Context): This = { var current = this val loBuf, hiBuf = new mutable.ListBuffer[PolyParam] var i = 0 @@ -398,7 +398,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, def removeParam(ps: List[PolyParam]) = ps.filterNot(p => p.binder.eq(poly) && p.paramNum == idx) - def replaceParam(tp: Type, atPoly: PolyType, atIdx: Int): Type = tp match { + def replaceParam(tp: Type, atPoly: GenericType, atIdx: Int): Type = tp match { case bounds @ TypeBounds(lo, hi) => def recombine(andor: AndOrType, op: (Type, Boolean) => Type, isUpper: Boolean): Type = { @@ -438,9 +438,9 @@ class OrderingConstraint(private val boundsMap: ParamBounds, } } - def remove(pt: PolyType)(implicit ctx: Context): This = { + def remove(pt: GenericType)(implicit ctx: Context): This = { def removeFromOrdering(po: ParamOrdering) = { - def removeFromBoundss(key: PolyType, bndss: Array[List[PolyParam]]): Array[List[PolyParam]] = { + def removeFromBoundss(key: GenericType, bndss: Array[List[PolyParam]]): Array[List[PolyParam]] = { val bndss1 = bndss.map(_.filterConserve(_.binder ne pt)) if (bndss.corresponds(bndss1)(_ eq _)) bndss else bndss1 } @@ -449,7 +449,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, newConstraint(boundsMap.remove(pt), removeFromOrdering(lowerMap), removeFromOrdering(upperMap)) } - def isRemovable(pt: PolyType, removedParam: Int = -1): Boolean = { + def isRemovable(pt: GenericType, removedParam: Int = -1): Boolean = { val entries = boundsMap(pt) var noneLeft = true var i = paramCount(entries) @@ -467,13 +467,13 @@ class OrderingConstraint(private val boundsMap: ParamBounds, // ---------- Exploration -------------------------------------------------------- - def domainPolys: List[PolyType] = boundsMap.keys + def domainPolys: List[GenericType] = boundsMap.keys def domainParams: List[PolyParam] = for { (poly, entries) <- boundsMap.toList n <- 0 until paramCount(entries) - if isBounds(entries(n)) + if true || isBounds(entries(n)) } yield PolyParam(poly, n) def forallParams(p: PolyParam => Boolean): Boolean = { @@ -484,7 +484,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, true } - def foreachParam(p: (PolyType, Int) => Unit): Unit = + def foreachParam(p: (GenericType, Int) => Unit): Unit = boundsMap.foreachBinding { (poly, entries) => 0.until(poly.paramNames.length).foreach(p(poly, _)) } @@ -501,7 +501,7 @@ class OrderingConstraint(private val boundsMap: ParamBounds, override def checkClosed()(implicit ctx: Context): Unit = { def isFreePolyParam(tp: Type) = tp match { - case PolyParam(binder, _) => !contains(binder) + case PolyParam(binder: GenericType, _) => !contains(binder) case _ => false } def checkClosedType(tp: Type, where: String) = diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 2692f57a2..46d93b753 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -1127,7 +1127,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.paramBounds.exists(hasSkolems) || hasSkolems(tp.resType) + case tp: GenericType => tp.paramBounds.exists(hasSkolems) || hasSkolems(tp.resType) case tp: MethodType => tp.paramTypes.exists(hasSkolems) || hasSkolems(tp.resType) case tp: ExprType => hasSkolems(tp.resType) case tp: HKApply => hasSkolems(tp.tycon) || tp.args.exists(hasSkolems) @@ -1658,6 +1658,8 @@ object SymDenotations { case _ => baseTypeRefOf(tp.underlying) } + case tp: HKApply => + baseTypeRefOf(tp.upperBound) // TODO drop? case tp: TypeProxy => baseTypeRefOf(tp.underlying) case AndType(tp1, tp2) => diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 60d01c125..d7c73c63f 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -687,7 +687,7 @@ class TypeApplications(val self: Type) extends AnyVal { final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ { if (args.isEmpty || ctx.erasedTypes) self else self.stripTypeVar match { // TODO investigate why we can't do safeDealias here - case self: PolyType if !args.exists(_.isInstanceOf[TypeBounds]) => + case self: GenericType if !args.exists(_.isInstanceOf[TypeBounds]) => self.instantiate(args) case EtaExpansion(self1) => self1.appliedTo(args) diff --git a/src/dotty/tools/dotc/core/TypeComparer.scala b/src/dotty/tools/dotc/core/TypeComparer.scala index 9449787c1..68a263dfc 100644 --- a/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/src/dotty/tools/dotc/core/TypeComparer.scala @@ -559,6 +559,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { */ def compareHkApply2(tp1: Type, tp2: Type, tycon2: Type, args2: List[Type]): Boolean = { val tparams = tycon2.typeParams + assert(tparams.nonEmpty) def isMatchingApply(tp1: Type): Boolean = tp1 match { case HKApply(tycon1, args1) => @@ -1087,10 +1088,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { formals2.isEmpty } - /** Do poly types `poly1` and `poly2` have type parameters that + /** Do generic types `poly1` and `poly2` have type parameters that * have the same bounds (after renaming one set to the other)? */ - private def matchingTypeParams(poly1: PolyType, poly2: PolyType): Boolean = + private def matchingTypeParams(poly1: GenericType, poly2: GenericType): Boolean = (poly1.paramBounds corresponds poly2.paramBounds)((b1, b2) => isSameType(b1, b2.subst(poly2, poly1))) @@ -1312,7 +1313,7 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { else if (tparams1.length != tparams2.length) mergeConflict(tp1, tp2) else if (Config.newHK) { val numArgs = tparams1.length - def argRefs(tl: PolyType) = List.range(0, numArgs).map(PolyParam(tl, _)) + def argRefs(tl: GenericType) = List.range(0, numArgs).map(PolyParam(tl, _)) TypeLambda( paramNames = tpnme.syntheticLambdaParamNames(numArgs), variances = (tparams1, tparams2).zipped.map((tparam1, tparam2) => @@ -1382,10 +1383,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => mergeConflict(tp1, tp2) } - case tp1: PolyType => + case tp1: GenericType => tp2 match { - case tp2: PolyType if matchingTypeParams(tp1, tp2) => - tp1.derivedPolyType( + case tp2: GenericType if matchingTypeParams(tp1, tp2) => + tp1.derivedGenericType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), tp1.paramBounds, tp1.resultType & tp2.resultType.subst(tp2, tp1)) case _ => @@ -1438,10 +1439,10 @@ class TypeComparer(initctx: Context) extends DotClass with ConstraintHandling { case _ => mergeConflict(tp1, tp2) } - case tp1: PolyType => + case tp1: GenericType => tp2 match { - case tp2: PolyType if matchingTypeParams(tp1, tp2) => - tp1.derivedPolyType( + case tp2: GenericType if matchingTypeParams(tp1, tp2) => + tp1.derivedGenericType( mergeNames(tp1.paramNames, tp2.paramNames, tpnme.syntheticTypeParamName), tp1.paramBounds, tp1.resultType | tp2.resultType.subst(tp2, tp1)) case _ => diff --git a/src/dotty/tools/dotc/core/TyperState.scala b/src/dotty/tools/dotc/core/TyperState.scala index 36f026107..e64335218 100644 --- a/src/dotty/tools/dotc/core/TyperState.scala +++ b/src/dotty/tools/dotc/core/TyperState.scala @@ -127,7 +127,7 @@ extends TyperState(r) { } override def gc()(implicit ctx: Context): Unit = { - val toCollect = new mutable.ListBuffer[PolyType] + val toCollect = new mutable.ListBuffer[GenericType] constraint foreachTypeVar { tvar => if (!tvar.inst.exists) { val inst = instType(tvar) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index ca60f08a6..ac0048e16 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -67,7 +67,8 @@ object Types { * +- MethodType -----+- ImplicitMethodType * | +- JavaMethodType * +- ClassInfo - * +- PolyType --------- TypeLambda + * +- GenericType ----+- PolyType + * | +- TypeLambda * | * +- NoType * +- NoPrefix @@ -1082,10 +1083,10 @@ object Types { } - /** The parameter types in the first parameter section of a PolyType or MethodType, Empty list for others */ + /** 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 { case mt: MethodType => mt.paramTypes - case pt: PolyType => pt.resultType.firstParamTypes + case pt: GenericType => pt.resultType.firstParamTypes case _ => Nil } @@ -2572,8 +2573,9 @@ object Types { } } - abstract case class PolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends CachedGroundType with BindingType with TermType with MethodOrPoly { + /** A common superclass of PolyType and TypeLambda */ + abstract class GenericType(val paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type) + extends CachedGroundType with BindingType with TermType { val paramBounds = paramBoundsExp(this) val resType = resultTypeExp(this) @@ -2585,32 +2587,17 @@ object Types { /** If this is a type lambda, the variances of its parameters, otherwise Nil.*/ def variances: List[Int] = Nil - protected def computeSignature(implicit ctx: Context) = resultSignature - - def isPolymorphicMethodType: Boolean = resType match { - case _: MethodType => true - case _ => false - } - final def instantiate(argTypes: List[Type])(implicit ctx: Context): Type = resultType.substParams(this, argTypes) def instantiateBounds(argTypes: List[Type])(implicit ctx: Context): List[TypeBounds] = paramBounds.mapConserve(_.substParams(this, argTypes).bounds) - def derivedPolyType(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context) = + def derivedGenericType(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context) = if ((paramNames eq this.paramNames) && (paramBounds eq this.paramBounds) && (resType eq this.resType)) this else duplicate(paramNames, paramBounds, resType) - def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context) = - if (this.variances.isEmpty) - PolyType(paramNames)( - x => paramBounds mapConserve (_.subst(this, x).bounds), - x => resType.subst(this, x)) - else - TypeLambda(paramNames, variances)( - x => paramBounds mapConserve (_.subst(this, x).bounds), - x => resType.subst(this, x)) + def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): GenericType def lifted(tparams: List[MemberBinding], t: Type)(implicit ctx: Context): Type = tparams match { @@ -2621,26 +2608,44 @@ object Types { } override def equals(other: Any) = other match { - case other: PolyType => + case other: GenericType => other.paramNames == this.paramNames && other.paramBounds == this.paramBounds && other.resType == this.resType && other.variances == this.variances case _ => false } + override def computeHash = { doHash(variances ::: paramNames, resType, paramBounds) } + } + + /** A type for polymorphic methods */ + class PolyType(paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type) + extends GenericType(paramNames)(paramBoundsExp, resultTypeExp) with MethodOrPoly { + + protected def computeSignature(implicit ctx: Context) = resultSignature + + def isPolymorphicMethodType: Boolean = resType match { + case _: MethodType => true + case _ => false + } + + def derivedPolyType(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context) = + derivedGenericType(paramNames, paramBounds, resType) + + def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): PolyType = + PolyType(paramNames)( + x => paramBounds mapConserve (_.subst(this, x).bounds), + x => resType.subst(this, x)) override def toString = s"PolyType($paramNames, $paramBounds, $resType)" } - class CachedPolyType(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends PolyType(paramNames)(paramBoundsExp, resultTypeExp) - object PolyType { - def apply(paramNames: List[TypeName])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = { - unique(new CachedPolyType(paramNames)(paramBoundsExp, resultTypeExp)) + def apply(paramNames: List[TypeName])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)(implicit ctx: Context): PolyType = { + unique(new PolyType(paramNames)(paramBoundsExp, resultTypeExp)) } def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) = @@ -2653,16 +2658,24 @@ object Types { // ----- HK types: TypeLambda, LambdaParam, HKApply --------------------- /** A type lambda of the form `[v_0 X_0, ..., v_n X_n] => T` */ - class TypeLambda(paramNames: List[TypeName], override val variances: List[Int])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type) - extends PolyType(paramNames)(paramBoundsExp, resultTypeExp) with ValueType { + class TypeLambda(paramNames: List[TypeName], override val variances: List[Int])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type) + extends GenericType(paramNames)(paramBoundsExp, resultTypeExp) with ValueType { assert(resType.isValueType, this) + assert(paramNames.nonEmpty) lazy val typeParams: List[LambdaParam] = paramNames.indices.toList.map(new LambdaParam(this, _)) - override def toString = s"TypeLambda($variances, $paramNames, $paramBounds, $resType)" + def derivedTypeLambda(paramNames: List[TypeName], paramBounds: List[TypeBounds], resType: Type)(implicit ctx: Context) = + derivedGenericType(paramNames, paramBounds, resType) + def duplicate(paramNames: List[TypeName] = this.paramNames, paramBounds: List[TypeBounds] = this.paramBounds, resType: Type)(implicit ctx: Context): TypeLambda = + TypeLambda(paramNames, variances)( + x => paramBounds mapConserve (_.subst(this, x).bounds), + x => resType.subst(this, x)) + + override def toString = s"TypeLambda($variances, $paramNames, $paramBounds, $resType)" } /** The parameter of a type lambda */ @@ -2676,7 +2689,7 @@ object Types { } object TypeLambda { - def apply(paramNames: List[TypeName], variances: List[Int])(paramBoundsExp: PolyType => List[TypeBounds], resultTypeExp: PolyType => Type)(implicit ctx: Context): PolyType = { + def apply(paramNames: List[TypeName], variances: List[Int])(paramBoundsExp: GenericType => List[TypeBounds], resultTypeExp: GenericType => Type)(implicit ctx: Context): TypeLambda = { unique(new TypeLambda(paramNames, variances)(paramBoundsExp, resultTypeExp)) } def fromSymbols(tparams: List[Symbol], resultType: Type)(implicit ctx: Context) = @@ -2720,9 +2733,14 @@ object Types { */ protected def checkInst(implicit ctx: Context): this.type = { def check(tycon: Type): Unit = tycon.stripTypeVar match { - case _: TypeRef | _: PolyParam | ErrorType => - case tycon: AnnotatedType => check(tycon.underlying) - case _ => assert(false, s"illegal type constructor in $this") + case tycon: TypeRef if !tycon.symbol.isClass => + case _: PolyParam | ErrorType => + case _: TypeLambda => + assert(args.exists(_.isInstanceOf[TypeBounds]), s"unreduced type apply: $this") + case tycon: AnnotatedType => + check(tycon.underlying) + case _ => + assert(false, s"illegal type constructor in $this") } check(tycon) this @@ -2783,8 +2801,8 @@ object Types { } /** TODO Some docs would be nice here! */ - case class PolyParam(binder: PolyType, paramNum: Int) extends ParamType { - type BT = PolyType + case class PolyParam(binder: GenericType, paramNum: Int) extends ParamType { + type BT = GenericType def copyBoundType(bt: BT) = PolyParam(bt, paramNum) /** Looking only at the structure of `bound`, is one of the following true? @@ -2804,7 +2822,7 @@ object Types { override def underlying(implicit ctx: Context): Type = { val bounds = binder.paramBounds - if (bounds == null) NoType // this can happen if the PolyType is not initialized yet + if (bounds == null) NoType // this can happen if the references generic type is not initialized yet else bounds(paramNum) } // no customized hashCode/equals needed because cycle is broken in PolyType @@ -3436,7 +3454,8 @@ object Types { protected def derivedSuperType(tp: SuperType, thistp: Type, supertp: Type): Type = tp.derivedSuperType(thistp, supertp) protected def derivedAppliedType(tp: HKApply, tycon: Type, args: List[Type]): Type = - tp.derivedAppliedType(tycon, args) + if (tycon.typeParams.isEmpty) tycon + else tp.derivedAppliedType(tycon, args) protected def derivedAndOrType(tp: AndOrType, tp1: Type, tp2: Type): Type = tp.derivedAndOrType(tp1, tp2) protected def derivedAnnotatedType(tp: AnnotatedType, underlying: Type, annot: Annotation): Type = @@ -3451,8 +3470,8 @@ object Types { 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) + protected def derivedGenericType(tp: GenericType, pbounds: List[TypeBounds], restpe: Type): Type = + tp.derivedGenericType(tp.paramNames, pbounds, restpe) /** Map this function over given type */ def mapOver(tp: Type): Type = { @@ -3494,12 +3513,12 @@ object Types { case tp: ExprType => derivedExprType(tp, this(tp.resultType)) - case tp: PolyType => + case tp: GenericType => def mapOverPoly = { variance = -variance val bounds1 = tp.paramBounds.mapConserve(this).asInstanceOf[List[TypeBounds]] variance = -variance - derivedPolyType(tp, bounds1, this(tp.resultType)) + derivedGenericType(tp, bounds1, this(tp.resultType)) } mapOverPoly @@ -3713,7 +3732,7 @@ object Types { case ExprType(restpe) => this(x, restpe) - case tp @ PolyType(pnames) => + case tp: GenericType => variance = -variance val y = foldOver(x, tp.paramBounds) variance = -variance diff --git a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 6f0596ac0..c428ac8c0 100644 --- a/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -311,7 +311,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { result case PARAMtype => readTypeRef() match { - case binder: PolyType => PolyParam(binder, readNat()) + case binder: GenericType => PolyParam(binder, readNat()) case binder: MethodType => MethodParam(binder, readNat()) } case CLASSconst => diff --git a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index aa660f73e..239dd4124 100644 --- a/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -82,8 +82,8 @@ object Scala2Unpickler { paramNames, paramTypes.init :+ defn.RepeatedParamType.appliedTo(elemtp), tp.resultType) - case tp @ PolyType(paramNames) => - tp.derivedPolyType(paramNames, tp.paramBounds, arrayToRepeated(tp.resultType)) + case tp: PolyType => + tp.derivedPolyType(tp.paramNames, tp.paramBounds, arrayToRepeated(tp.resultType)) } def ensureConstructor(cls: ClassSymbol, scope: Scope)(implicit ctx: Context) = diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala index e86137c47..d1a0560f2 100644 --- a/src/dotty/tools/dotc/printing/PlainPrinter.scala +++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala @@ -229,7 +229,7 @@ class PlainPrinter(_ctx: Context) extends Printer { protected def simpleNameString(sym: Symbol): String = nameString(sym.name) /** If -uniqid is set, the hashcode of the polytype, after a # */ - protected def polyHash(pt: PolyType): Text = + protected def polyHash(pt: GenericType): Text = "#" + pt.hashCode provided ctx.settings.uniqid.value /** If -uniqid is set, the unique id of symbol, after a # */ diff --git a/src/dotty/tools/dotc/transform/FullParameterization.scala b/src/dotty/tools/dotc/transform/FullParameterization.scala index be64df384..d2052d8cb 100644 --- a/src/dotty/tools/dotc/transform/FullParameterization.scala +++ b/src/dotty/tools/dotc/transform/FullParameterization.scala @@ -95,7 +95,7 @@ trait FullParameterization { */ def fullyParameterizedType(info: Type, clazz: ClassSymbol, abstractOverClass: Boolean = true, liftThisType: Boolean = false)(implicit ctx: Context): Type = { val (mtparamCount, origResult) = info match { - case info @ PolyType(mtnames) => (mtnames.length, info.resultType) + case info: PolyType => (info.paramNames.length, info.resultType) case info: ExprType => (0, info.resultType) case _ => (0, info) } @@ -111,18 +111,18 @@ trait FullParameterization { } /** Replace class type parameters by the added type parameters of the polytype `pt` */ - def mapClassParams(tp: Type, pt: PolyType): Type = { + def mapClassParams(tp: Type, pt: GenericType): Type = { val classParamsRange = (mtparamCount until mtparamCount + ctparams.length).toList tp.substDealias(ctparams, classParamsRange map (PolyParam(pt, _))) } /** The bounds for the added type parameters of the polytype `pt` */ - def mappedClassBounds(pt: PolyType): List[TypeBounds] = + def mappedClassBounds(pt: GenericType): List[TypeBounds] = ctparams.map(tparam => mapClassParams(tparam.info, pt).bounds) info match { - case info @ PolyType(mtnames) => - PolyType(mtnames ++ ctnames)( + case info: PolyType => + PolyType(info.paramNames ++ ctnames)( pt => (info.paramBounds.map(mapClassParams(_, pt).bounds) ++ mappedClassBounds(pt)).mapConserve(_.subst(info, pt).bounds), diff --git a/src/dotty/tools/dotc/transform/PostTyper.scala b/src/dotty/tools/dotc/transform/PostTyper.scala index fcde59b24..6b0b2b073 100644 --- a/src/dotty/tools/dotc/transform/PostTyper.scala +++ b/src/dotty/tools/dotc/transform/PostTyper.scala @@ -178,9 +178,9 @@ class PostTyper extends MacroTransform with IdentityDenotTransformer { thisTran } val (tycon, args) = decompose(tree) tycon.tpe.widen match { - case PolyType(pnames) => + case tp: PolyType => val (namedArgs, otherArgs) = args.partition(isNamedArg) - val args1 = reorderArgs(pnames, namedArgs.asInstanceOf[List[NamedArg]], otherArgs) + val args1 = reorderArgs(tp.paramNames, namedArgs.asInstanceOf[List[NamedArg]], otherArgs) TypeApply(tycon, args1).withPos(tree.pos).withType(tree.tpe) case _ => tree diff --git a/src/dotty/tools/dotc/typer/Checking.scala b/src/dotty/tools/dotc/typer/Checking.scala index cfad4e77e..9f218c3f1 100644 --- a/src/dotty/tools/dotc/typer/Checking.scala +++ b/src/dotty/tools/dotc/typer/Checking.scala @@ -51,7 +51,7 @@ object Checking { * Note: This does not check the bounds of AppliedTypeTrees. These * are handled by method checkBounds in FirstTransform */ - def checkBounds(args: List[tpd.Tree], poly: PolyType)(implicit ctx: Context): Unit = + def checkBounds(args: List[tpd.Tree], poly: GenericType)(implicit ctx: Context): Unit = checkBounds(args, poly.paramBounds, _.substParams(poly, _)) /** Traverse type tree, performing the following checks: diff --git a/src/dotty/tools/dotc/typer/ProtoTypes.scala b/src/dotty/tools/dotc/typer/ProtoTypes.scala index 68fd99b3f..9a1337022 100644 --- a/src/dotty/tools/dotc/typer/ProtoTypes.scala +++ b/src/dotty/tools/dotc/typer/ProtoTypes.scala @@ -286,7 +286,7 @@ object ProtoTypes { override def isMatchedBy(tp: Type)(implicit ctx: Context) = { def isInstantiatable(tp: Type) = tp.widen match { - case PolyType(paramNames) => paramNames.length == targs.length + case tp: GenericType => tp.paramNames.length == targs.length case _ => false } isInstantiatable(tp) || tp.member(nme.apply).hasAltWith(d => isInstantiatable(d.info)) diff --git a/src/dotty/tools/dotc/typer/Variances.scala b/src/dotty/tools/dotc/typer/Variances.scala index 9af11a0f4..a2f9a0f16 100644 --- a/src/dotty/tools/dotc/typer/Variances.scala +++ b/src/dotty/tools/dotc/typer/Variances.scala @@ -94,7 +94,7 @@ object Variances { v } varianceInArgs(varianceInType(tycon)(tparam), args, tycon.typeParams) - case tp @ PolyType(_) => + case tp: GenericType => flip(varianceInTypes(tp.paramBounds)(tparam)) & varianceInType(tp.resultType)(tparam) case AnnotatedType(tp, annot) => varianceInType(tp)(tparam) & varianceInAnnot(annot)(tparam) |