aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/TypeApplications.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r--src/dotty/tools/dotc/core/TypeApplications.scala223
1 files changed, 137 insertions, 86 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala
index 33aa060b5..12b42642d 100644
--- a/src/dotty/tools/dotc/core/TypeApplications.scala
+++ b/src/dotty/tools/dotc/core/TypeApplications.scala
@@ -56,13 +56,13 @@ object TypeApplications {
def variancesConform(tparams1: List[MemberBinding], tparams2: List[MemberBinding])(implicit ctx: Context): Boolean =
tparams1.corresponds(tparams2)(varianceConforms)
- def fallbackTypeParams(variances: List[Int])(implicit ctx: Context): List[MemberBinding] = {
+ def fallbackTypeParamsOLD(variances: List[Int])(implicit ctx: Context): List[MemberBinding] = {
def memberBindings(vs: List[Int]): Type = vs match {
case Nil => NoType
case v :: vs1 =>
RefinedType(
memberBindings(vs1),
- tpnme.hkArg(vs1.length),
+ tpnme.hkArgOLD(vs1.length),
TypeBounds.empty.withBindingKind(BindingKind.fromVariance(v)))
}
def decompose(t: Type, acc: List[MemberBinding]): List[MemberBinding] = t match {
@@ -78,14 +78,14 @@ object TypeApplications {
* ==>
* ([X_i := this.$hk_i] T) { type v_i $hk_i: (new)B_i }
*/
- object TypeLambda {
+ object TypeLambdaOLD {
def apply(argBindingFns: List[RecType => TypeBounds],
bodyFn: RecType => Type)(implicit ctx: Context): Type = {
- val argNames = argBindingFns.indices.toList.map(tpnme.hkArg)
+ val argNames = argBindingFns.indices.toList.map(tpnme.hkArgOLD)
var idx = 0
RecType.closeOver(rt =>
(bodyFn(rt) /: argBindingFns) { (parent, argBindingFn) =>
- val res = RefinedType(parent, tpnme.hkArg(idx), argBindingFn(rt))
+ val res = RefinedType(parent, tpnme.hkArgOLD(idx), argBindingFn(rt))
idx += 1
res
})
@@ -117,26 +117,33 @@ object TypeApplications {
* @param tycon C
*/
object EtaExpansion {
- def apply(tycon: TypeRef)(implicit ctx: Context) = {
- assert(tycon.isEtaExpandable)
+ def apply(tycon: Type)(implicit ctx: Context) = {
+ if (!Config.newHK) assert(tycon.isEtaExpandableOLD)
tycon.EtaExpand(tycon.typeParamSymbols)
}
- def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] = {
- def argsAreForwarders(args: List[Type], n: Int): Boolean = args match {
- case Nil =>
- n == 0
- case TypeRef(RecThis(rt), sel) :: args1 if false =>
- rt.eq(tp) && sel == tpnme.hkArg(n - 1) && argsAreForwarders(args1, n - 1)
- case _ =>
- false
- }
- tp match {
- case TypeLambda(argBounds, AppliedType(fn: TypeRef, args))
- if argsAreForwarders(args, tp.typeParams.length) => Some(fn)
- case _ => None
+ def unapply(tp: Type)(implicit ctx: Context): Option[TypeRef] =
+ if (Config.newHK)
+ tp match {
+ case tp @ TypeLambda(tparams, AppliedType(fn: TypeRef, args))
+ if (args == tparams.map(_.toArg)) => Some(fn)
+ case _ => None
+ }
+ else {
+ def argsAreForwarders(args: List[Type], n: Int): Boolean = args match {
+ case Nil =>
+ n == 0
+ case TypeRef(RecThis(rt), sel) :: args1 if false =>
+ rt.eq(tp) && sel == tpnme.hkArgOLD(n - 1) && argsAreForwarders(args1, n - 1)
+ case _ =>
+ false
+ }
+ tp match {
+ case TypeLambdaOLD(argBounds, AppliedType(fn: TypeRef, args))
+ if argsAreForwarders(args, tp.typeParams.length) => Some(fn)
+ case _ => None
+ }
}
- }
}
/** Extractor for type application T[U_1, ..., U_n]. This is the refined type
@@ -169,6 +176,8 @@ object TypeApplications {
None
}
collectArgs(tycon.typeParams, refinements, new mutable.ListBuffer[Type])
+ case HKApply(tycon, args) =>
+ Some((tycon, args))
case _ =>
None
}
@@ -187,15 +196,15 @@ object TypeApplications {
}
/** The references `<rt>.this.$hk0, ..., <rt>.this.$hk<n-1>`. */
- def argRefs(rt: RecType, n: Int)(implicit ctx: Context) =
- List.range(0, n).map(i => RecThis(rt).select(tpnme.hkArg(i)))
+ def argRefsOLD(rt: RecType, n: Int)(implicit ctx: Context) =
+ List.range(0, n).map(i => RecThis(rt).select(tpnme.hkArgOLD(i)))
- private class InstMap(fullType: Type)(implicit ctx: Context) extends TypeMap {
+ private class InstMapOLD(fullType: Type)(implicit ctx: Context) extends TypeMap {
var localRecs: Set[RecType] = Set.empty
var keptRefs: Set[Name] = Set.empty
var tyconIsHK: Boolean = true
def apply(tp: Type): Type = tp match {
- case tp @ TypeRef(RecThis(rt), sel) if sel.isHkArgName && localRecs.contains(rt) =>
+ case tp @ TypeRef(RecThis(rt), sel) if sel.isHkArgNameOLD && localRecs.contains(rt) =>
fullType.member(sel).info match {
case TypeAlias(alias) => apply(alias)
case _ => keptRefs += sel; tp
@@ -203,7 +212,7 @@ object TypeApplications {
case tp: TypeVar if !tp.inst.exists =>
val bounds = tp.instanceOpt.orElse(ctx.typeComparer.bounds(tp.origin))
bounds.foreachPart {
- case TypeRef(RecThis(rt), sel) if sel.isHkArgName && localRecs.contains(rt) =>
+ case TypeRef(RecThis(rt), sel) if sel.isHkArgNameOLD && localRecs.contains(rt) =>
keptRefs += sel
case _ =>
}
@@ -329,7 +338,9 @@ class TypeApplications(val self: Type) extends AnyVal {
/** Is self type higher-kinded (i.e. of kind != "*")? */
def isHK(implicit ctx: Context): Boolean = self.dealias match {
case self: TypeRef => self.info.isHK
- case self: RefinedType => self.isTypeParam
+ case self: RefinedType => !Config.newHK && self.isTypeParam
+ case self: TypeLambda => true
+ case self: HKApply => false
case self: SingletonType => false
case self: TypeVar => self.origin.isHK
case self: WildcardType => self.optBounds.isHK
@@ -354,7 +365,9 @@ class TypeApplications(val self: Type) extends AnyVal {
else 0
}
case self: RefinedType =>
- if (self.isTypeParam) 1 else -1
+ if (!Config.newHK && self.isTypeParam) 1 else -1
+ case self: TypeLambda => 1
+ case self: HKApply => -1
case self: SingletonType => -1
case self: TypeVar => self.origin.knownHK
case self: WildcardType => self.optBounds.knownHK
@@ -364,15 +377,14 @@ class TypeApplications(val self: Type) extends AnyVal {
case _ => -1
}
- /** is receiver of the form T#$Apply? */
- def isHKApply(implicit ctx: Context): Boolean = self match {
- case self @ RefinedType(_, name, _) => name.isHkArgName && !self.isTypeParam
+ /** is receiver a higher-kinded application? */
+ def isHKApplyOLD(implicit ctx: Context): Boolean = self match {
+ case self @ RefinedType(_, name, _) => name.isHkArgNameOLD && !self.isTypeParam
case _ => false
}
/** True if it can be determined without forcing that the class symbol
- * of this application exists and is not a lambda trait.
- * Equivalent to
+ * of this application exists. Equivalent to
*
* self.classSymbol.exists
*
@@ -402,11 +414,11 @@ class TypeApplications(val self: Type) extends AnyVal {
/** Replace references to type parameters with references to hk arguments `this.$hk_i`
* Care is needed not to cause cyclic reference errors, hence `SafeSubstMap`.
*/
- def recursify[T <: Type](tparams: List[MemberBinding])(implicit ctx: Context): RecType => T =
+ def recursifyOLD[T <: Type](tparams: List[MemberBinding])(implicit ctx: Context): RecType => T =
tparams match {
case (_: Symbol) :: _ =>
(rt: RecType) =>
- new ctx.SafeSubstMap(tparams.asInstanceOf[List[Symbol]], argRefs(rt, tparams.length))
+ new ctx.SafeSubstMap(tparams.asInstanceOf[List[Symbol]], argRefsOLD(rt, tparams.length))
.apply(self).asInstanceOf[T]
case _ =>
def mapRefs(rt: RecType) = new TypeMap {
@@ -421,23 +433,34 @@ class TypeApplications(val self: Type) extends AnyVal {
/** Lambda abstract `self` with given type parameters. Examples:
*
* type T[X] = U becomes type T = [X] -> U
- * type T[X] >: L <: U becomes type T >: L <: ([X] -> _ <: U)
+ * type T[X] >: L <: U becomes type T >: L <: ([X] -> U)
+ *
+ * TODO: Handle parameterized lower bounds
*/
def LambdaAbstract(tparams: List[Symbol])(implicit ctx: Context): Type = {
def expand(tp: Type) =
- TypeLambda(
- tparams.map(tparam =>
- tparam.memberBoundsAsSeenFrom(self)
- .withBindingKind(BindingKind.fromVariance(tparam.variance))
- .recursify(tparams)),
- tp.recursify(tparams))
+ if (Config.newHK) TypeLambda.fromSymbols(tparams, tp)
+ else
+ TypeLambdaOLD(
+ tparams.map(tparam =>
+ tparam.memberBoundsAsSeenFrom(self)
+ .withBindingKind(BindingKind.fromVariance(tparam.variance))
+ .recursifyOLD(tparams)),
+ tp.recursifyOLD(tparams))
assert(!isHK, self)
- self match {
+ if (Config.newHK) self match {
case self: TypeAlias =>
- self.derivedTypeAlias(expand(self.alias.normalizeHkApply))
+ self.derivedTypeAlias(expand(self.alias))
case self @ TypeBounds(lo, hi) =>
- self.derivedTypeBounds(lo, expand(hi.normalizeHkApply))
+ self.derivedTypeBounds(lo, expand(hi))
+ case _ => expand(self)
+ }
+ else self match {
+ case self: TypeAlias =>
+ self.derivedTypeAlias(expand(self.alias.normalizeHkApplyOLD))
+ case self @ TypeBounds(lo, hi) =>
+ self.derivedTypeBounds(lo, expand(hi.normalizeHkApplyOLD))
case _ => expand(self)
}
}
@@ -470,9 +493,9 @@ class TypeApplications(val self: Type) extends AnyVal {
* - dropping refinements and rec-types
* - going from a wildcard type to its upper bound
*/
- def normalizeHkApply(implicit ctx: Context): Type = self.strictDealias match {
- case self1 @ RefinedType(_, rname, _) if rname.isHkArgName && self1.typeParams.isEmpty =>
- val inst = new InstMap(self)
+ def normalizeHkApplyOLD(implicit ctx: Context): Type = self.strictDealias match {
+ case self1 @ RefinedType(_, rname, _) if rname.isHkArgNameOLD && self1.typeParams.isEmpty =>
+ val inst = new InstMapOLD(self)
def instTop(tp: Type): Type = tp.strictDealias match {
case tp: RecType =>
@@ -480,12 +503,12 @@ class TypeApplications(val self: Type) extends AnyVal {
tp.rebind(instTop(tp.parent))
case tp @ RefinedType(parent, rname, rinfo) =>
rinfo match {
- case TypeAlias(TypeRef(RecThis(rt), sel)) if sel.isHkArgName && inst.localRecs.contains(rt) =>
+ case TypeAlias(TypeRef(RecThis(rt), sel)) if sel.isHkArgNameOLD && inst.localRecs.contains(rt) =>
val bounds @ TypeBounds(_, _) = self.member(sel).info
instTop(tp.derivedRefinedType(parent, rname, bounds.withBindingKind(NoBinding)))
case _ =>
val parent1 = instTop(parent)
- if (rname.isHkArgName &&
+ if (rname.isHkArgNameOLD &&
!inst.tyconIsHK &&
!inst.keptRefs.contains(rname)) parent1
else tp.derivedRefinedType(parent1, rname, inst(rinfo))
@@ -527,7 +550,7 @@ class TypeApplications(val self: Type) extends AnyVal {
* In that case we can look for parameterized base types of the type
* to eta expand them.
*/
- def isEtaExpandable(implicit ctx: Context) = self match {
+ def isEtaExpandableOLD(implicit ctx: Context) = self match {
case self: TypeRef => self.symbol.isClass
case _ => false
}
@@ -603,7 +626,14 @@ class TypeApplications(val self: Type) extends AnyVal {
if (hkParams.isEmpty) self
else {
def adaptArg(arg: Type): Type = arg match {
- case arg @ TypeLambda(tparamBounds, body) if
+ case arg @ TypeLambda(tparams, body) if
+ !tparams.corresponds(hkParams)(_.memberVariance == _.memberVariance) &&
+ tparams.corresponds(hkParams)(varianceConforms) =>
+ TypeLambda(tparams.map(_.memberName), hkParams.map(_.memberVariance))(
+ tl => arg.paramBounds.map(_.subst(arg, tl).bounds),
+ tl => arg.resultType.subst(arg, tl)
+ )
+ case arg @ TypeLambdaOLD(tparamBounds, body) if
!arg.typeParams.corresponds(hkParams)(_.memberVariance == _.memberVariance) &&
arg.typeParams.corresponds(hkParams)(varianceConforms) =>
def adjustVariance(bounds: TypeBounds, tparam: MemberBinding): TypeBounds =
@@ -613,7 +643,7 @@ class TypeApplications(val self: Type) extends AnyVal {
case _ => (x => tp)
}
val adjusted = (tparamBounds, hkParams).zipped.map(adjustVariance)
- TypeLambda(adjusted.map(lift), lift(body))
+ TypeLambdaOLD(adjusted.map(lift), lift(body))
case arg @ TypeAlias(alias) =>
arg.derivedTypeAlias(adaptArg(alias))
case arg @ TypeBounds(lo, hi) =>
@@ -641,22 +671,22 @@ class TypeApplications(val self: Type) extends AnyVal {
* 3. If `T` is a polytype, instantiate it to `U1,...,Un`.
*/
final def appliedTo(args: List[Type])(implicit ctx: Context): Type = /*>|>*/ track("appliedTo") /*<|<*/ {
- def substHkArgs = new TypeMap {
- def apply(tp: Type): Type = tp match {
- case TypeRef(RecThis(rt), name) if rt.eq(self) && name.isHkArgName =>
- args(name.hkArgIndex)
- case _ =>
- mapOver(tp)
- }
- }
if (args.isEmpty || ctx.erasedTypes) self
- else self.stripTypeVar match {
+ else self.stripTypeVar match { // TODO investigate why we can't do safeDealias here
+ case self: PolyType if !args.exists(_.isInstanceOf[TypeBounds]) =>
+ self.instantiate(args)
case EtaExpansion(self1) =>
self1.appliedTo(args)
- case TypeLambda(_, body) if !args.exists(_.isInstanceOf[TypeBounds]) =>
+ case TypeLambdaOLD(_, body) if !args.exists(_.isInstanceOf[TypeBounds]) =>
+ def substHkArgs = new TypeMap {
+ def apply(tp: Type): Type = tp match {
+ case TypeRef(RecThis(rt), name) if rt.eq(self) && name.isHkArgNameOLD =>
+ args(name.hkArgIndexOLD)
+ case _ =>
+ mapOver(tp)
+ }
+ }
substHkArgs(body)
- case self: PolyType =>
- self.instantiate(args)
case self1 =>
self1.safeDealias.appliedTo(args, typeParams)
}
@@ -682,9 +712,10 @@ class TypeApplications(val self: Type) extends AnyVal {
case nil => t
}
assert(args.nonEmpty)
- matchParams(self, typParams, args) match {
- case refined @ RefinedType(_, pname, _) if pname.isHkArgName =>
- refined.betaReduce // TODO Move to matchparams
+ if (Config.newHK && self.isHK) AppliedType(self, args)
+ else matchParams(self, typParams, args) match {
+ case refined @ RefinedType(_, pname, _) if !Config.newHK && pname.isHkArgNameOLD =>
+ refined.betaReduceOLD
case refined =>
refined
}
@@ -698,17 +729,25 @@ class TypeApplications(val self: Type) extends AnyVal {
* up hk type parameters matching the arguments. This is needed when unpickling
* Scala2 files such as `scala.collection.generic.Mapfactory`.
*/
- final def safeAppliedTo(args: List[Type])(implicit ctx: Context) = {
- val safeTypeParams = self match {
- case self: TypeRef if !self.symbol.isClass && self.symbol.isCompleting =>
- // This happens when unpickling e.g. scala$collection$generic$GenMapFactory$$CC
- ctx.warning(i"encountered F-bounded higher-kinded type parameters for ${self.symbol}; assuming they are invariant")
- fallbackTypeParams(args map alwaysZero)
- case _ =>
- typeParams
+ final def safeAppliedTo(args: List[Type])(implicit ctx: Context) =
+ if (Config.newHK)
+ self match {
+ case self: TypeRef if !self.symbol.isClass && self.symbol.isCompleting =>
+ AppliedType(self, args)
+ case _ =>
+ appliedTo(args, typeParams)
+ }
+ else {
+ val safeTypeParams = self match {
+ case self: TypeRef if !self.symbol.isClass && self.symbol.isCompleting =>
+ // This happens when unpickling e.g. scala$collection$generic$GenMapFactory$$CC
+ ctx.warning(i"encountered F-bounded higher-kinded type parameters for ${self.symbol}; assuming they are invariant")
+ fallbackTypeParamsOLD(args map alwaysZero)
+ case _ =>
+ typeParams
+ }
+ appliedTo(args, safeTypeParams)
}
- appliedTo(args, safeTypeParams)
- }
/** Turn this type, which is used as an argument for
* type parameter `tparam`, into a TypeBounds RHS
@@ -731,7 +770,10 @@ class TypeApplications(val self: Type) extends AnyVal {
*/
final def baseArgInfos(base: Symbol)(implicit ctx: Context): List[Type] =
if (self derivesFrom base)
- base.typeParams map (param => self.member(param.name).info.argInfo)
+ self match {
+ case self: HKApply => self.upperBound.baseArgInfos(base)
+ case _ => base.typeParams.map(param => self.member(param.name).info.argInfo)
+ }
else
Nil
@@ -756,7 +798,10 @@ class TypeApplications(val self: Type) extends AnyVal {
/** The first type argument of the base type instance wrt `base` of this type */
final def firstBaseArgInfo(base: Symbol)(implicit ctx: Context): Type = base.typeParams match {
case param :: _ if self derivesFrom base =>
- self.member(param.name).info.argInfo
+ self match {
+ case self: HKApply => self.upperBound.firstBaseArgInfo(base)
+ case _ => self.member(param.name).info.argInfo
+ }
case _ =>
NoType
}
@@ -778,6 +823,8 @@ class TypeApplications(val self: Type) extends AnyVal {
tp.wrapIfMember(parent.baseTypeWithArgs(base))
case tp: TermRef =>
tp.underlying.baseTypeWithArgs(base)
+ case tp: HKApply =>
+ tp.upperBound.baseTypeWithArgs(base)
case AndType(tp1, tp2) =>
tp1.baseTypeWithArgs(base) & tp2.baseTypeWithArgs(base)
case OrType(tp1, tp2) =>
@@ -832,12 +879,16 @@ class TypeApplications(val self: Type) extends AnyVal {
/** The core type without any type arguments.
* @param `typeArgs` must be the type arguments of this type.
*/
- final def withoutArgs(typeArgs: List[Type]): Type = typeArgs match {
- case _ :: typeArgs1 =>
- val RefinedType(tycon, _, _) = self
- tycon.withoutArgs(typeArgs1)
- case nil =>
- self
+ final def withoutArgs(typeArgs: List[Type]): Type = self match {
+ case HKApply(tycon, args) => tycon
+ case _ =>
+ typeArgs match {
+ case _ :: typeArgs1 =>
+ val RefinedType(tycon, _, _) = self
+ tycon.withoutArgs(typeArgs1)
+ case nil =>
+ self
+ }
}
final def typeConstructor(implicit ctx: Context): Type = self.stripTypeVar match {