diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index c2fa44e0cfa4..339ea20dbae6 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1117,6 +1117,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def TypeBounds_apply(low: Type, hi: Type)(given ctx: Context): TypeBounds = + Types.TypeBounds(low, hi) + def TypeBounds_low(self: TypeBounds)(given Context): Type = self.lo def TypeBounds_hi(self: TypeBounds)(given Context): Type = self.hi @@ -1201,6 +1204,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case tpe: Types.ConstantType => Some(tpe) case _ => None } + + def ConstantType_apply(const: Constant)(given Context): ConstantType = + Types.ConstantType(const) def ConstantType_constant(self: ConstantType)(given Context): Constant = self.value @@ -1305,6 +1311,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def AnnotatedType_apply(underlying: Type, annot: Term)(given Context): AnnotatedType = + Types.AnnotatedType(underlying, Annotations.Annotation(annot)) + def AnnotatedType_underlying(self: AnnotatedType)(given Context): Type = self.underlying.stripTypeVar def AnnotatedType_annot(self: AnnotatedType)(given Context): Term = self.annot.tree @@ -1317,6 +1326,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def AndType_apply(lhs: Type, rhs: Type)(given Context): AndType = + Types.AndType(lhs, rhs) + def AndType_left(self: AndType)(given Context): Type = self.tp1.stripTypeVar def AndType_right(self: AndType)(given Context): Type = self.tp2.stripTypeVar @@ -1329,6 +1341,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def OrType_apply(lhs: Type, rhs: Type)(given Context): OrType = + Types.OrType(lhs, rhs) + def OrType_left(self: OrType)(given Context): Type = self.tp1.stripTypeVar def OrType_right(self: OrType)(given Context): Type = self.tp2.stripTypeVar @@ -1341,6 +1356,9 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def MatchType_apply(bound: Type, scrutinee: Type, cases: List[Type])(given Context): MatchType = + Types.MatchType(bound, scrutinee, cases) + def MatchType_bound(self: MatchType)(given Context): Type = self.bound def MatchType_scrutinee(self: MatchType)(given Context): Type = self.scrutinee def MatchType_cases(self: MatchType)(given Context): List[Type] = self.cases @@ -1445,8 +1463,13 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend case _ => None } + def TypeLambda_apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => Type): TypeLambda = + Types.HKTypeLambda(paramNames.map(_.toTypeName))(boundsFn, bodyFn) + def TypeLambda_paramNames(self: TypeLambda)(given Context): List[String] = self.paramNames.map(_.toString) def TypeLambda_paramBounds(self: TypeLambda)(given Context): List[TypeBounds] = self.paramInfos + def TypeLambda_param(self: TypeLambda, idx: Int)(given Context): Type = + self.newParamRef(idx) def TypeLambda_resType(self: TypeLambda)(given Context): Type = self.resType // diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index e7d731ecacf6..4ec673e9754f 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -797,6 +797,8 @@ trait CompilerInterface { def isInstanceOfTypeBounds(given ctx: Context): IsInstanceOf[TypeBounds] + def TypeBounds_apply(low: Type, hi: Type)(given ctx: Context): TypeBounds + def TypeBounds_low(self: TypeBounds)(given ctx: Context): Type def TypeBounds_hi(self: TypeBounds)(given ctx: Context): Type @@ -887,6 +889,8 @@ trait CompilerInterface { def isInstanceOfConstantType(given ctx: Context): IsInstanceOf[ConstantType] + def ConstantType_apply(const : Constant)(given ctx : Context) : ConstantType + def ConstantType_constant(self: ConstantType)(given ctx: Context): Constant /** Type of a reference to a term symbol */ @@ -941,6 +945,8 @@ trait CompilerInterface { def isInstanceOfAnnotatedType(given ctx: Context): IsInstanceOf[AnnotatedType] + def AnnotatedType_apply(underlying: Type, annot: Term)(given ctx: Context): AnnotatedType + def AnnotatedType_underlying(self: AnnotatedType)(given ctx: Context): Type def AnnotatedType_annot(self: AnnotatedType)(given ctx: Context): Term @@ -949,6 +955,8 @@ trait CompilerInterface { def isInstanceOfAndType(given ctx: Context): IsInstanceOf[AndType] + def AndType_apply(lhs: Type, rhs: Type)(given ctx: Context): AndType + def AndType_left(self: AndType)(given ctx: Context): Type def AndType_right(self: AndType)(given ctx: Context): Type @@ -957,6 +965,8 @@ trait CompilerInterface { def isInstanceOfOrType(given ctx: Context): IsInstanceOf[OrType] + def OrType_apply(lhs : Type, rhs : Type)(given ctx : Context): OrType + def OrType_left(self: OrType)(given ctx: Context): Type def OrType_right(self: OrType)(given ctx: Context): Type @@ -965,6 +975,8 @@ trait CompilerInterface { def isInstanceOfMatchType(given ctx: Context): IsInstanceOf[MatchType] + def MatchType_apply(bound: Type, scrutinee: Type, cases: List[Type])(given ctx: Context): MatchType + def MatchType_bound(self: MatchType)(given ctx: Context): Type def MatchType_scrutinee(self: MatchType)(given ctx: Context): Type def MatchType_cases(self: MatchType)(given ctx: Context): List[Type] @@ -1037,8 +1049,11 @@ trait CompilerInterface { def isInstanceOfTypeLambda(given ctx: Context): IsInstanceOf[TypeLambda] + def TypeLambda_apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => Type): TypeLambda + def TypeLambda_paramNames(self: TypeLambda)(given ctx: Context): List[String] def TypeLambda_paramBounds(self: TypeLambda)(given ctx: Context): List[TypeBounds] + def TypeLambda_param(self: TypeLambda, idx: Int)(given ctx: Context): Type def TypeLambda_resType(self: TypeLambda)(given ctx: Context): Type // diff --git a/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala b/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala index e2a97e06e168..dbf9cd39ee57 100644 --- a/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala +++ b/library/src/scala/tasty/reflect/TypeOrBoundsOps.scala @@ -103,6 +103,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: ConstantType)(given ctx: Context): Option[ConstantType] = Some(x) object ConstantType { + def apply(x : Constant)(given ctx: Context): ConstantType = internal.ConstantType_apply(x) def unapply(x: ConstantType)(given ctx: Context): Option[Constant] = Some(x.constant) } @@ -205,6 +206,8 @@ trait TypeOrBoundsOps extends Core { def unapply(x: AnnotatedType)(given ctx: Context): Option[AnnotatedType] = Some(x) object AnnotatedType { + def apply(underlying: Type, annot: Term)(given ctx: Context): AnnotatedType = + internal.AnnotatedType_apply(underlying, annot) def unapply(x: AnnotatedType)(given ctx: Context): Option[(Type, Term)] = Some((x.underlying, x.annot)) } @@ -221,6 +224,8 @@ trait TypeOrBoundsOps extends Core { def unapply(x: AndType)(given ctx: Context): Option[AndType] = Some(x) object AndType { + def apply(lhs: Type, rhs: Type)(given ctx: Context): AndType = + internal.AndType_apply(lhs, rhs) def unapply(x: AndType)(given ctx: Context): Option[(Type, Type)] = Some((x.left, x.right)) } @@ -237,6 +242,7 @@ trait TypeOrBoundsOps extends Core { def unapply(x: OrType)(given ctx: Context): Option[OrType] = Some(x) object OrType { + def apply(lhs: Type, rhs: Type)(given ctx: Context): OrType = internal.OrType_apply(lhs, rhs) def unapply(x: OrType)(given ctx: Context): Option[(Type, Type)] = Some((x.left, x.right)) } @@ -253,6 +259,8 @@ trait TypeOrBoundsOps extends Core { def unapply(x: MatchType)(given ctx: Context): Option[MatchType] = Some(x) object MatchType { + def apply(bound: Type, scrutinee: Type, cases: List[Type])(given ctx: Context): MatchType = + internal.MatchType_apply(bound, scrutinee, cases) def unapply(x: MatchType)(given ctx: Context): Option[(Type, Type, List[Type])] = Some((x.bound, x.scrutinee, x.cases)) } @@ -263,6 +271,14 @@ trait TypeOrBoundsOps extends Core { def cases(given ctx: Context): List[Type] = internal.MatchType_cases(self) } + /** + * An accessor for `scala.internal.MatchCase[_,_]`, the representation of a `MatchType` case. + */ + def MatchCaseType(given Context): Type = { + import scala.internal.MatchCase + Type(classOf[MatchCase[_,_]]) + } + given (given Context): IsInstanceOf[ByNameType] = internal.isInstanceOfByNameType object IsByNameType @@ -381,6 +397,8 @@ trait TypeOrBoundsOps extends Core { def unapply(x: TypeLambda)(given ctx: Context): Option[TypeLambda] = Some(x) object TypeLambda { + def apply(paramNames: List[String], boundsFn: TypeLambda => List[TypeBounds], bodyFn: TypeLambda => Type): TypeLambda = + internal.TypeLambda_apply(paramNames, boundsFn, bodyFn) def unapply(x: TypeLambda)(given ctx: Context): Option[(List[String], List[TypeBounds], Type)] = Some((x.paramNames, x.paramBounds, x.resType)) } @@ -388,6 +406,7 @@ trait TypeOrBoundsOps extends Core { given TypeLambdaOps: extension (self: TypeLambda) { def paramNames(given ctx: Context): List[String] = internal.TypeLambda_paramNames(self) def paramBounds(given ctx: Context): List[TypeBounds] = internal.TypeLambda_paramBounds(self) + def param(idx: Int)(given ctx: Context) : Type = internal.TypeLambda_param(self, idx) def resType(given ctx: Context): Type = internal.TypeLambda_resType(self) } @@ -400,6 +419,8 @@ trait TypeOrBoundsOps extends Core { def unapply(x: TypeBounds)(given ctx: Context): Option[TypeBounds] = Some(x) object TypeBounds { + def apply(low: Type, hi: Type)(given ctx: Context): TypeBounds = + internal.TypeBounds_apply(low, hi) def unapply(x: TypeBounds)(given ctx: Context): Option[(Type, Type)] = Some((x.low, x.hi)) } diff --git a/tests/run-macros/tasty-construct-types.check b/tests/run-macros/tasty-construct-types.check new file mode 100644 index 000000000000..7326d9603970 --- /dev/null +++ b/tests/run-macros/tasty-construct-types.check @@ -0,0 +1 @@ +Ok diff --git a/tests/run-macros/tasty-construct-types/Macro_1.scala b/tests/run-macros/tasty-construct-types/Macro_1.scala new file mode 100644 index 000000000000..eabf07e8953f --- /dev/null +++ b/tests/run-macros/tasty-construct-types/Macro_1.scala @@ -0,0 +1,57 @@ +import tasty._ +import quoted._ + +object Macros { + inline def theTestBlock : Unit = ${ theTestBlockImpl } + + trait RefineMe { + type T + def foo : T + } + + class TestAnnotation extends scala.annotation.Annotation + + def theTestBlockImpl(given qctx : QuoteContext) : Expr[Unit] = { + import qctx.tasty.{_,given} + + val x1T = ConstantType(Constant(1)) + val x2T = OrType(ConstantType(Constant(1)), ConstantType(Constant(2))) + val x3T = AndType(ConstantType(Constant(3)), typeOf[Any]) + val x4T = + TypeLambda( + List("A","B"), + _ => List(TypeBounds(typeOf[Nothing], typeOf[Any]), TypeBounds(typeOf[Nothing], typeOf[Any])), + (tl : TypeLambda) => tl.param(1)) + val x5T = + Refinement( + typeOf[RefineMe], + "T", + TypeBounds(typeOf[Int], typeOf[Int])) + val x6T = AppliedType(Type(classOf[List[_]]), List(typeOf[Int])) + val x7T = AnnotatedType(ConstantType(Constant(7)), '{ new TestAnnotation }.unseal) + val x8T = + MatchType( + typeOf[Int], + typeOf[List[8]], + List( + TypeLambda( + List("t"), + _ => List(TypeBounds(typeOf[Nothing], typeOf[Any])), + tl => AppliedType(MatchCaseType, List(AppliedType(Type(classOf[List[_]]), List(tl.param(0))), tl.param(0))))) + ) + + assert(x1T =:= '[1].unseal.tpe) + assert(x2T =:= '[1|2].unseal.tpe) + assert(x3T =:= '[3&Any].unseal.tpe) + assert(x4T =:= '[[A,B] =>> B].unseal.tpe) + assert(x5T =:= '[RefineMe { type T = Int }].unseal.tpe) + assert(x6T =:= '[List[Int]].unseal.tpe) + assert(x7T =:= '[7 @TestAnnotation].unseal.tpe) + assert(x8T =:= '[List[8] match { case List[t] => t }].unseal.tpe) + + '{ + println("Ok") + } + } +} + diff --git a/tests/run-macros/tasty-construct-types/Test_2.scala b/tests/run-macros/tasty-construct-types/Test_2.scala new file mode 100644 index 000000000000..ba7ca53e8708 --- /dev/null +++ b/tests/run-macros/tasty-construct-types/Test_2.scala @@ -0,0 +1,6 @@ + +object Test { + def main(args : Array[String]) : Unit = + Macros.theTestBlock +} +