diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala index 8ffadaa4ffb7..45d7e48c6a27 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/TastyImpl.scala @@ -769,6 +769,12 @@ class TastyImpl(val rootContext: Contexts.Context) extends scala.tasty.Tasty { s // ----- Types ---------------------------------------------------- type Type = Types.Type + + def TypeDeco(tpe: Type): TypeAPI = new TypeAPI { + def =:=(other: Type)(implicit ctx: Context): Boolean = tpe =:= other + def <:<(other: Type)(implicit ctx: Context): Boolean = tpe <:< other + } + type RecursiveType = Types.RecType type LambdaType[ParamInfo <: TypeOrBounds] = Types.LambdaType { type PInfo = ParamInfo } type MethodType = Types.MethodType diff --git a/library/src/scala/tasty/Tasty.scala b/library/src/scala/tasty/Tasty.scala index 32a6955a8d49..9492156f51ab 100644 --- a/library/src/scala/tasty/Tasty.scala +++ b/library/src/scala/tasty/Tasty.scala @@ -591,6 +591,12 @@ abstract class Tasty { tasty => type Type <: TypeOrBounds + trait TypeAPI { + def =:=(other: Type)(implicit ctx: Context): Boolean + def <:<(other: Type)(implicit ctx: Context): Boolean + } + implicit def TypeDeco(tpe: Type): TypeAPI + type RecursiveType <: Type type LambdaType[ParamInfo <: TypeOrBounds] <: Type diff --git a/tests/run/tasty-subtyping.check b/tests/run/tasty-subtyping.check new file mode 100644 index 000000000000..b3209151bf40 --- /dev/null +++ b/tests/run/tasty-subtyping.check @@ -0,0 +1,24 @@ +true +true +true +true +true + +false +false +false +false +false + +true +true +true +true +true +true + +false +false +false +false +false diff --git a/tests/run/tasty-subtyping/quoted_1.scala b/tests/run/tasty-subtyping/quoted_1.scala new file mode 100644 index 000000000000..a9e398984f6e --- /dev/null +++ b/tests/run/tasty-subtyping/quoted_1.scala @@ -0,0 +1,24 @@ +import scala.quoted._ + +import scala.tasty._ + +object Macros { + + transparent def isTypeEqual[T, U]: Boolean = + ~isTypeEqualImpl('[T], '[U])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + + transparent def isSubTypeOf[T, U]: Boolean = + ~isSubTypeOfImpl('[T], '[U])(TopLevelSplice.tastyContext) // FIXME infer TopLevelSplice.tastyContext within top level ~ + + def isTypeEqualImpl[T, U](t: Type[T], u: Type[U])(implicit tasty: Tasty): Expr[Boolean] = { + import tasty._ + val isTypeEqual = t.toTasty.tpe =:= u.toTasty.tpe + isTypeEqual.toExpr + } + + def isSubTypeOfImpl[T, U](t: Type[T], u: Type[U])(implicit tasty: Tasty): Expr[Boolean] = { + import tasty._ + val isTypeEqual = t.toTasty.tpe <:< u.toTasty.tpe + isTypeEqual.toExpr + } +} diff --git a/tests/run/tasty-subtyping/quoted_2.scala b/tests/run/tasty-subtyping/quoted_2.scala new file mode 100644 index 000000000000..1223787c2d1e --- /dev/null +++ b/tests/run/tasty-subtyping/quoted_2.scala @@ -0,0 +1,41 @@ + +import Macros._ + +object Test { + type A + type B <: A + + def main(args: Array[String]): Unit = { + // true + println(isTypeEqual[Int, Int]) + println(isTypeEqual[String, String]) + println(isTypeEqual[Test.type, Test.type]) + println(isTypeEqual[2, 2]) + println(isTypeEqual[A, A]) + println() + + // false + println(isTypeEqual[Int, Double]) + println(isTypeEqual[String, Int]) + println(isTypeEqual[Test.type, Macros.type]) + println(isTypeEqual[2, 1]) + println(isTypeEqual[A, B]) + println() + + // true + println(isSubTypeOf[Int, Int]) + println(isSubTypeOf[String, Object]) + println(isSubTypeOf[Int, AnyVal]) + println(isSubTypeOf[AnyRef, Any]) + println(isSubTypeOf[AnyVal, Any]) + println(isSubTypeOf[B, A]) + println() + + // false + println(isSubTypeOf[Object, Int]) + println(isSubTypeOf[AnyVal, Int]) + println(isSubTypeOf[Any, AnyRef]) + println(isSubTypeOf[Any, AnyVal]) + println(isSubTypeOf[A, B]) + } +}