diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index f0136716a9ab..63d82eab1047 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -2309,9 +2309,9 @@ object Types { } /** A refined type parent { refinement } - * @param refinedName The name of the refinement declaration - * @param infoFn: A function that produces the info of the refinement declaration, - * given the refined type itself. + * @param parent The type being refined + * @param refinedName The name of the refinement declaration + * @param refinedInfo The info of the refinement declaration */ abstract case class RefinedType(parent: Type, refinedName: Name, refinedInfo: Type) extends RefinedOrRecType { @@ -2370,6 +2370,31 @@ object Types { } } + /** A recursive type. Instances should be constructed via the companion object. + * + * @param parentExp A function that, given a recursive type R, produces a type + * that can refer to R via a `RecThis(R)` node. This is used to + * "tie the knot". + * + * For example, in + * class C { type T1; type T2 } + * type C2 = C { type T1; type T2 = T1 } + * + * The type of `C2` is a recursive type `{(x) => C{T1; T2 = x.T1}}`, written as + * + * RecType( + * RefinedType( + * RefinedType( + * TypeRef(...,class C), + * T1, + * TypeBounds(...)), + * T2, + * TypeBounds( + * TypeRef(RecThis(...),T1), + * TypeRef(RecThis(...),T1)))) + * + * Where `RecThis(...)` points back to the enclosing `RecType`. + */ class RecType(parentExp: RecType => Type) extends RefinedOrRecType with BindingType { // See discussion in findMember#goRec why these vars are needed @@ -2438,7 +2463,7 @@ object Types { * 1. Nested Rec types on the type's spine are merged with the outer one. * 2. Any refinement of the form `type T = z.T` on the spine of the type * where `z` refers to the created rec-type is replaced by - * `type T`. This avoids infinite recursons later when we + * `type T`. This avoids infinite recursions later when we * try to follow these references. * TODO: Figure out how to guarantee absence of cycles * of length > 1 @@ -2459,6 +2484,8 @@ object Types { } unique(rt.derivedRecType(normalize(rt.parent))).checkInst } + + /** Create a `RecType`, but only if the type generated by `parentExp` is indeed recursive. */ def closeOver(parentExp: RecType => Type)(implicit ctx: Context) = { val rt = this(parentExp) if (rt.isReferredToBy(rt.parent)) rt else rt.parent