diff options
Diffstat (limited to 'src/dotty/tools/dotc/core/TypeApplications.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/TypeApplications.scala | 40 |
1 files changed, 32 insertions, 8 deletions
diff --git a/src/dotty/tools/dotc/core/TypeApplications.scala b/src/dotty/tools/dotc/core/TypeApplications.scala index 2411e0bb2..bd115fefb 100644 --- a/src/dotty/tools/dotc/core/TypeApplications.scala +++ b/src/dotty/tools/dotc/core/TypeApplications.scala @@ -22,10 +22,16 @@ object TypeApplicationsNewHK { import TypeApplications._ object TypeLambda { - def apply(argBindingFns: List[RefinedType => TypeBounds], - bodyFn: RefinedType => Type)(implicit ctx: Context): Type = { + def apply(argBindingFns: List[RecType => TypeBounds], + bodyFn: RecType => Type)(implicit ctx: Context): Type = { val argNames = argBindingFns.indices.toList.map(tpnme.hkArg) - RefinedType.recursive(bodyFn, argNames, argBindingFns) + var idx = 0 + RecType.closeOver(rt => + (bodyFn(rt) /: argBindingFns) { (parent, argBindingFn) => + val res = RefinedType(parent, tpnme.hkArg(idx), argBindingFn(rt)) + idx += 1 + res + }) } def unapply(tp: Type)(implicit ctx: Context): Option[(List[TypeBounds], Type)] = { @@ -33,6 +39,8 @@ object TypeApplicationsNewHK { case t @ RefinedType(p, rname, rinfo: TypeBounds) if rname.isHkArgName && rinfo.isBinding => decompose(p, rinfo.bounds :: acc) + case t: RecType => + decompose(t.parent, acc) case _ => (acc, t) } @@ -78,13 +86,13 @@ object TypeApplications { * [v1 X1: B1, ..., vn Xn: Bn] -> T * ==> * ([X_i := this.$hk_i] T) { type v_i $hk_i: (new)B_i } - * + * * [X] -> List[X] - * + * * List { type List$A = this.$hk_0 } { type $hk_0 } - * + * * [X] -> X - * + * * mu(this) this.$hk_0 & { type $hk_0 } */ object TypeLambda { @@ -212,6 +220,10 @@ object TypeApplications { def argRefs(rt: RefinedType, n: Int)(implicit ctx: Context) = List.range(0, n).map(i => RefinedThis(rt).select(tpnme.hkArg(i))) + /** 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))) + /** Merge `tp1` and `tp2` under a common lambda, combining them with `op`. * @param tparams1 The type parameters of `tp1` * @param tparams2 The type parameters of `tp2` @@ -400,7 +412,7 @@ class TypeApplications(val self: Type) extends AnyVal { * but without forcing anything. */ def classNotLambda(implicit ctx: Context): Boolean = self.stripTypeVar match { - case self: RefinedType => + case self: RefinedOrRecType => self.parent.classNotLambda case self: TypeRef => self.denot.exists && { @@ -428,6 +440,14 @@ class TypeApplications(val self: Type) extends AnyVal { new ctx.SafeSubstMap(tparams, argRefs(rt, tparams.length)) .apply(self).asInstanceOf[T] + /** 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[Symbol])(implicit ctx: Context): RecType => T = + (rt: RecType) => + new ctx.SafeSubstMap(tparams, argRefs(rt, tparams.length)) + .apply(self).asInstanceOf[T] + /** Lambda abstract `self` with given type parameters. Examples: * * type T[X] = U becomes type T = [X] -> U @@ -546,6 +566,8 @@ class TypeApplications(val self: Type) extends AnyVal { arg.prefix.select(boundLambda) case arg: RefinedType => arg.derivedRefinedType(adaptArg(arg.parent), arg.refinedName, arg.refinedInfo) + case arg: RecType => + arg.derivedRecType(adaptArg(arg.parent)) case arg @ TypeAlias(alias) => arg.derivedTypeAlias(adaptArg(alias)) case arg @ TypeBounds(lo, hi) => @@ -814,6 +836,8 @@ class TypeApplications(val self: Type) extends AnyVal { } case tp: RefinedType => recur(tp.refinedInfo) || recur(tp.parent) + case tp: RecType => + recur(tp.parent) case tp: TypeBounds => recur(tp.lo) || recur(tp.hi) case tp: AnnotatedType => |