Skip to content

Commit 484ac90

Browse files
committed
Addressed issue 8163 to add opaque type alias information to Reflection API
1 parent c4c847f commit 484ac90

File tree

5 files changed

+57
-0
lines changed

5 files changed

+57
-0
lines changed

compiler/src/dotty/tools/dotc/tastyreflect/ReflectionCompilerInterface.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,10 @@ class ReflectionCompilerInterface(val rootContext: core.Contexts.Context) extend
12451245

12461246
def TypeRef_name(self: TypeRef)(given Context): String = self.name.toString
12471247

1248+
def TypeRef_isOpaqueAlias(self: TypeRef)(given Context): Boolean = self.symbol.isOpaqueAlias
1249+
1250+
def TypeRef_opaqueAliasWrappedType(self: TypeRef)(given Context): Type = self.translucentSuperType
1251+
12481252
type NamedTermRef = Types.NamedType
12491253

12501254
def isInstanceOfNamedTermRef(given ctx: Context): IsInstanceOf[NamedTermRef] = new {

compiler/test/dotty/tools/dotc/BootstrappedOnlyCompilationTests.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ class BootstrappedOnlyCompilationTests extends ParallelTesting {
129129
compileFilesInDir("tests/run-staging", withStagingOptions),
130130
compileFilesInDir("tests/run-custom-args/tasty-inspector", withTastyInspectorOptions),
131131
compileDir("tests/run-custom-args/tasty-interpreter", withTastyInspectorOptions),
132+
compileFile("tests/run-custom-args/i8163.scala", withTastyInspectorOptions),
132133
).checkRuns()
133134
}
134135

library/src/scala/tasty/Reflection.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1702,6 +1702,8 @@ class Reflection(private[scala] val internal: CompilerInterface) { self =>
17021702
extension TypeRefOps on (self: TypeRef) {
17031703
def qualifier(given ctx: Context): TypeOrBounds /* Type | NoPrefix */ = internal.TypeRef_qualifier(self)
17041704
def name(given ctx: Context): String = internal.TypeRef_name(self)
1705+
def isOpaqueAlias(given ctx: Context): Boolean = internal.TypeRef_isOpaqueAlias(self)
1706+
def opaqueAliasWrappedType(given ctx: Context): Type = internal.TypeRef_opaqueAliasWrappedType(self)
17051707
}
17061708

17071709
given (given Context): IsInstanceOf[SuperType] = internal.isInstanceOfSuperType

library/src/scala/tasty/reflect/CompilerInterface.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ trait CompilerInterface {
915915

916916
def TypeRef_qualifier(self: TypeRef)(given ctx: Context): TypeOrBounds
917917
def TypeRef_name(self: TypeRef)(given Context): String
918+
def TypeRef_isOpaqueAlias(self: TypeRef)(given Context): Boolean
919+
def TypeRef_opaqueAliasWrappedType(self: TypeRef)(given Context): Type
918920

919921
/** Type of a `super` reference */
920922
type SuperType <: Type

tests/run-custom-args/i8163.scala

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import scala.tasty.Reflection
2+
import scala.tasty.inspector._
3+
4+
opaque type PhoneNumber = String
5+
6+
case class I8163() {
7+
val phone: PhoneNumber = "555-555-5555".asInstanceOf[PhoneNumber]
8+
val other: String = "not a phone"
9+
}
10+
11+
object Test {
12+
def main(args: Array[String]): Unit = {
13+
new TestInspector().inspect("", List("I8163"))
14+
}
15+
}
16+
17+
class TestInspector() extends TastyInspector
18+
19+
protected def processCompilationUnit(reflect: Reflection)(root: reflect.Tree): Unit =
20+
import reflect._
21+
inspectClass(reflect)(root)
22+
23+
private def inspectClass(reflect: Reflection)(tree: reflect.Tree): Unit =
24+
import reflect.{given,_}
25+
tree match {
26+
case t: reflect.PackageClause =>
27+
t.stats.map( m => inspectClass(reflect)(m) )
28+
case t: reflect.ClassDef if !t.name.endsWith("$") =>
29+
val interestingVals = t.body.collect {
30+
case v: ValDef => v
31+
}
32+
val shouldBePhone = interestingVals.find(_.name == "phone").get
33+
val shouldBePhoneType = shouldBePhone.tpt.tpe match {
34+
case tr: TypeRef => tr
35+
case _ => throw new Exception("unexpected")
36+
}
37+
assert(shouldBePhoneType.isOpaqueAlias)
38+
assert(shouldBePhoneType.opaqueAliasWrappedType.show == "scala.Predef.String")
39+
40+
val shouldNotBePhone = interestingVals.find(_.name == "other").get
41+
val shouldNotBePhoneType = shouldNotBePhone.tpt.tpe match {
42+
case tr: TypeRef => tr
43+
case _ => throw new Exception("unexpected")
44+
}
45+
assert(!shouldNotBePhoneType.isOpaqueAlias)
46+
47+
case x =>
48+
}

0 commit comments

Comments
 (0)