diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 41555b3297b9..fedb3a59152c 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -1165,7 +1165,7 @@ object Types { * these types as a set, otherwise the empty set. * Overridden and cached in OrType. * @param widenOK If type proxies that are upperbounded by types with atoms - * have the same atoms. + * have the same atoms. */ def atoms(widenOK: Boolean = false)(implicit ctx: Context): Set[Type] = dealias match { case tp: SingletonType => @@ -2544,7 +2544,7 @@ object Types { final class CachedSuperType(thistpe: Type, supertpe: Type) extends SuperType(thistpe, supertpe) object SuperType { - def apply(thistpe: Type, supertpe: Type)(implicit ctx: Context): Type = { + def apply(thistpe: Type, supertpe: Type)(implicit ctx: Context): SuperType = { assert(thistpe != NoPrefix) unique(new CachedSuperType(thistpe, supertpe)) } diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index a122af77cfff..a9e555953819 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1274,6 +1274,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def SuperType_apply(thistpe: Type, supertpe: Type)(given ctx: Context): SuperType = + Types.SuperType(thistpe, supertpe) + def SuperType_thistpe(self: SuperType)(given Context): Type = self.thistpe def SuperType_supertpe(self: SuperType)(given Context): Type = self.supertpe @@ -1431,8 +1434,13 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def RecursiveType_apply(parentExp: RecursiveType => Type)(given ctx: Context): RecursiveType = + Types.RecType(parentExp) + def RecursiveType_underlying(self: RecursiveType)(given Context): Type = self.underlying.stripTypeVar + def RecursiveThis_recThis(self: RecursiveType)(given Context): RecursiveThis = self.recThis + type LambdaType[ParamInfo] = Types.LambdaType { type PInfo = ParamInfo } type MethodType = Types.MethodType diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index 8d81c81138aa..4894638541f0 100644 --- a/library/src/scala/tasty/Reflection.scala +++ b/library/src/scala/tasty/Reflection.scala @@ -1738,6 +1738,9 @@ class Reflection(private[scala] val internal: CompilerInterface) { self => given (given Context): IsInstanceOf[SuperType] = internal.isInstanceOfSuperType object SuperType { + def apply(thistpe: Type, supertpe: Type)(given ctx: Context): SuperType = + internal.SuperType_apply(thistpe, supertpe) + def unapply(x: SuperType)(given ctx: Context): Option[(Type, Type)] = Some((x.thistpe, x.supertpe)) } @@ -1887,11 +1890,25 @@ class Reflection(private[scala] val internal: CompilerInterface) { self => given (given Context): IsInstanceOf[RecursiveType] = internal.isInstanceOfRecursiveType object RecursiveType { + + /** Create a RecType, normalizing its contents. This means: + * + * 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 recursions later when we + * try to follow these references. + */ + def apply(parentExp: RecursiveType => Type)(given ctx: Context): RecursiveType = + internal.RecursiveType_apply(parentExp) + def unapply(x: RecursiveType)(given ctx: Context): Option[Type] = Some(x.underlying) + } extension RecursiveTypeOps on (self: RecursiveType) { def underlying(given ctx: Context): Type = internal.RecursiveType_underlying(self) + def recThis(given Context): RecursiveThis = internal.RecursiveThis_recThis(self) } given (given Context): IsInstanceOf[MethodType] = internal.isInstanceOfMethodType diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index 7773798cb2a7..9ad8973f2686 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -923,6 +923,8 @@ trait CompilerInterface { def isInstanceOfSuperType(given ctx: Context): IsInstanceOf[SuperType] + def SuperType_apply(thistpe: Type, supertpe: Type)(given ctx: Context): SuperType + def SuperType_thistpe(self: SuperType)(given ctx: Context): Type def SuperType_supertpe(self: SuperType)(given ctx: Context): Type @@ -1024,8 +1026,20 @@ trait CompilerInterface { def isInstanceOfRecursiveType(given ctx: Context): IsInstanceOf[RecursiveType] + /** Create a RecType, normalizing its contents. This means: + * + * 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 recursions later when we + * try to follow these references. + */ + def RecursiveType_apply(parentExp: RecursiveType => Type)(given ctx: Context): RecursiveType + def RecursiveType_underlying(self: RecursiveType)(given ctx: Context): Type + def RecursiveThis_recThis(self: RecursiveType)(given Context): RecursiveThis + // TODO can we add the bound back without an cake? // TODO is LambdaType really needed? ParamRefExtractor could be split into more precise extractors /** Common abstraction for lambda types (MethodType, PolyType and TypeLambda). */