From 484ac9045f9c551e5278b426655c6ce2d11bff63 Mon Sep 17 00:00:00 2001 From: gzoller Date: Sun, 2 Feb 2020 22:38:23 -0600 Subject: [PATCH 1/2] Addressed issue 8163 to add opaque type alias information to Reflection API --- .../ReflectionCompilerInterface.scala | 4 ++ .../BootstrappedOnlyCompilationTests.scala | 1 + library/src/scala/tasty/Reflection.scala | 2 + .../tasty/reflect/CompilerInterface.scala | 2 + tests/run-custom-args/i8163.scala | 48 +++++++++++++++++++ 5 files changed, 57 insertions(+) create mode 100644 tests/run-custom-args/i8163.scala diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 46441c2cda53..6b6fd82cec6b 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_opaqueAliasWrappedType(self: TypeRef)(given Context): Type = self.translucentSuperType + type NamedTermRef = Types.NamedType def isInstanceOfNamedTermRef(given ctx: Context): IsInstanceOf[NamedTermRef] = new { diff --git a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala index 6f8d4c162b88..dd0cf222251e 100644 --- a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala @@ -129,6 +129,7 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting { compileFilesInDir("tests/run-staging", withStagingOptions), compileFilesInDir("tests/run-custom-args/tasty-inspector", withTastyInspectorOptions), compileDir("tests/run-custom-args/tasty-interpreter", withTastyInspectorOptions), + compileFile("tests/run-custom-args/i8163.scala", withTastyInspectorOptions), ).checkRuns() } diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index 619eed5edbd9..5573c53b7358 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 opaqueAliasWrappedType(given ctx: Context): Type = internal.TypeRef_opaqueAliasWrappedType(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..07d7de8c57cb 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_opaqueAliasWrappedType(self: TypeRef)(given Context): Type /** Type of a `super` reference */ type SuperType <: Type diff --git a/tests/run-custom-args/i8163.scala b/tests/run-custom-args/i8163.scala new file mode 100644 index 000000000000..47c26aa33a72 --- /dev/null +++ b/tests/run-custom-args/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.opaqueAliasWrappedType.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 From 7e243b0b320c89bb04033bfbe53b7396ecd77cbf Mon Sep 17 00:00:00 2001 From: gzoller Date: Mon, 3 Feb 2020 09:28:05 -0600 Subject: [PATCH 2/2] Reflecting requested changes --- .../tools/dotc/tastyreflect/ReflectionCompilerInterface.scala | 2 +- .../dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala | 1 - library/src/scala/tasty/Reflection.scala | 2 +- library/src/scala/tasty/reflect/CompilerInterface.scala | 2 +- tests/run-custom-args/{ => tasty-inspector}/i8163.scala | 2 +- 5 files changed, 4 insertions(+), 5 deletions(-) rename tests/run-custom-args/{ => tasty-inspector}/i8163.scala (94%) diff --git a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala index 6b6fd82cec6b..cde582921258 100644 --- a/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala +++ b/compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala @@ -1247,7 +1247,7 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend def TypeRef_isOpaqueAlias(self: TypeRef)(given Context): Boolean = self.symbol.isOpaqueAlias - def TypeRef_opaqueAliasWrappedType(self: TypeRef)(given Context): Type = self.translucentSuperType + def TypeRef_translucentSuperType(self: TypeRef)(given Context): Type = self.translucentSuperType type NamedTermRef = Types.NamedType diff --git a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala index dd0cf222251e..6f8d4c162b88 100644 --- a/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala +++ b/compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala @@ -129,7 +129,6 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting { compileFilesInDir("tests/run-staging", withStagingOptions), compileFilesInDir("tests/run-custom-args/tasty-inspector", withTastyInspectorOptions), compileDir("tests/run-custom-args/tasty-interpreter", withTastyInspectorOptions), - compileFile("tests/run-custom-args/i8163.scala", withTastyInspectorOptions), ).checkRuns() } diff --git a/library/src/scala/tasty/Reflection.scala b/library/src/scala/tasty/Reflection.scala index 5573c53b7358..3ad5ac7d6172 100644 --- a/library/src/scala/tasty/Reflection.scala +++ b/library/src/scala/tasty/Reflection.scala @@ -1703,7 +1703,7 @@ class Reflection(private[scala] val internal: CompilerInterface) { self => 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 opaqueAliasWrappedType(given ctx: Context): Type = internal.TypeRef_opaqueAliasWrappedType(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 07d7de8c57cb..4297f12667ad 100644 --- a/library/src/scala/tasty/reflect/CompilerInterface.scala +++ b/library/src/scala/tasty/reflect/CompilerInterface.scala @@ -916,7 +916,7 @@ 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_opaqueAliasWrappedType(self: TypeRef)(given Context): Type + def TypeRef_translucentSuperType(self: TypeRef)(given Context): Type /** Type of a `super` reference */ type SuperType <: Type diff --git a/tests/run-custom-args/i8163.scala b/tests/run-custom-args/tasty-inspector/i8163.scala similarity index 94% rename from tests/run-custom-args/i8163.scala rename to tests/run-custom-args/tasty-inspector/i8163.scala index 47c26aa33a72..a4be52728362 100644 --- a/tests/run-custom-args/i8163.scala +++ b/tests/run-custom-args/tasty-inspector/i8163.scala @@ -35,7 +35,7 @@ class TestInspector() extends TastyInspector case _ => throw new Exception("unexpected") } assert(shouldBePhoneType.isOpaqueAlias) - assert(shouldBePhoneType.opaqueAliasWrappedType.show == "scala.Predef.String") + assert(shouldBePhoneType.translucentSuperType.show == "scala.Predef.String") val shouldNotBePhone = interestingVals.find(_.name == "other").get val shouldNotBePhoneType = shouldNotBePhone.tpt.tpe match {