diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 46441c2cda53..cde582921258 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1245,6 +1245,10 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def TypeRef_name(self: TypeRef)(given Context): String = self.name.toString + def TypeRef_isOpaqueAlias(self: TypeRef)(given Context): Boolean = self.symbol.isOpaqueAlias + + def TypeRef_translucentSuperType(self: TypeRef)(given Context): Type = self.translucentSuperType + type NamedTermRef = Types.NamedType def isInstanceOfNamedTermRef(given ctx: Context): IsInstanceOf[NamedTermRef] = new { diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index 619eed5edbd9..3ad5ac7d6172 100644 --- a/library/src/scala/tasty/Reflection.scala +++ b/library/src/scala/tasty/Reflection.scala @@ -1702,6 +1702,8 @@ class Reflection(private[scala] val internal: CompilerInterface) { self => extension TypeRefOps on (self: TypeRef) { def qualifier(given ctx: Context): TypeOrBounds /* Type | NoPrefix */ = internal.TypeRef_qualifier(self) def name(given ctx: Context): String = internal.TypeRef_name(self) + def isOpaqueAlias(given ctx: Context): Boolean = internal.TypeRef_isOpaqueAlias(self) + def translucentSuperType(given ctx: Context): Type = internal.TypeRef_translucentSuperType(self) } given (given Context): IsInstanceOf[SuperType] = internal.isInstanceOfSuperType diff --git a/library/src/scala/tasty/reflect/CompilerInterface.scala b/library/src/scala/tasty/reflect/CompilerInterface.scala index 72cbe6fe1736..4297f12667ad 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -915,6 +915,8 @@ trait CompilerInterface { def TypeRef_qualifier(self: TypeRef)(given ctx: Context): TypeOrBounds def TypeRef_name(self: TypeRef)(given Context): String + def TypeRef_isOpaqueAlias(self: TypeRef)(given Context): Boolean + def TypeRef_translucentSuperType(self: TypeRef)(given Context): Type /** Type of a `super` reference */ type SuperType <: Type diff --git a/tests/run-custom-args/tasty-inspector/i8163.scala b/tests/run-custom-args/tasty-inspector/i8163.scala new file mode 100644 index 000000000000..a4be52728362 --- /dev/null +++ b/tests/run-custom-args/tasty-inspector/i8163.scala @@ -0,0 +1,48 @@ +import scala.tasty.Reflection +import scala.tasty.inspector._ + +opaque type PhoneNumber = String + +case class I8163() { + val phone: PhoneNumber = "555-555-5555".asInstanceOf[PhoneNumber] + val other: String = "not a phone" +} + +object Test { + def main(args: Array[String]): Unit = { + new TestInspector().inspect("", List("I8163")) + } +} + +class TestInspector() extends TastyInspector + + protected def processCompilationUnit(reflect: Reflection)(root: reflect.Tree): Unit = + import reflect._ + inspectClass(reflect)(root) + + private def inspectClass(reflect: Reflection)(tree: reflect.Tree): Unit = + import reflect.{given,_} + tree match { + case t: reflect.PackageClause => + t.stats.map( m => inspectClass(reflect)(m) ) + case t: reflect.ClassDef if !t.name.endsWith("$") => + val interestingVals = t.body.collect { + case v: ValDef => v + } + val shouldBePhone = interestingVals.find(_.name == "phone").get + val shouldBePhoneType = shouldBePhone.tpt.tpe match { + case tr: TypeRef => tr + case _ => throw new Exception("unexpected") + } + assert(shouldBePhoneType.isOpaqueAlias) + assert(shouldBePhoneType.translucentSuperType.show == "scala.Predef.String") + + val shouldNotBePhone = interestingVals.find(_.name == "other").get + val shouldNotBePhoneType = shouldNotBePhone.tpt.tpe match { + case tr: TypeRef => tr + case _ => throw new Exception("unexpected") + } + assert(!shouldNotBePhoneType.isOpaqueAlias) + + case x => + } \ No newline at end of file