Skip to content

Commit 20ac708

Browse files
committed
Add MatchTypeCase to Tasty Reflect
1 parent feb8b2e commit 20ac708

File tree

5 files changed

+93
-16
lines changed

5 files changed

+93
-16
lines changed

compiler/src/scala/quoted/runtime/impl/QuotesImpl.scala

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1881,6 +1881,47 @@ class QuotesImpl private (using val ctx: Context) extends Quotes, QuoteUnpickler
18811881
end extension
18821882
end MatchTypeMethods
18831883

1884+
type MatchTypeCase = dotc.core.Types.Type
1885+
1886+
object MatchTypeCaseTypeTest extends TypeTest[TypeRepr, MatchTypeCase]:
1887+
def unapply(x: TypeRepr): Option[MatchTypeCase & x.type] =
1888+
MatchTypeCase.unapply(x.asInstanceOf[MatchTypeCase]).map(_ => x.asInstanceOf[MatchTypeCase & x.type])
1889+
end MatchTypeCaseTypeTest
1890+
1891+
object MatchTypeCase extends MatchTypeCaseModule:
1892+
def apply(pattern: TypeRepr, body: TypeRepr): MatchTypeCase =
1893+
Types.AppliedType(ctx.definitions.MatchCaseClass.typeRef, List(pattern, body))
1894+
1895+
def apply(
1896+
paramNames: List[String],
1897+
boundsFn: TypeLambda => List[TypeBounds],
1898+
patternFn: TypeLambda => TypeRepr,
1899+
bodyFn: TypeLambda => TypeRepr,
1900+
): MatchTypeCase =
1901+
reflect.TypeLambda(paramNames, boundsFn, tl => MatchTypeCase(patternFn(tl), bodyFn(tl)))
1902+
1903+
def unapply(x: MatchTypeCase): Option[(List[String], List[TypeBounds], TypeRepr, TypeRepr)] = x match
1904+
case AppliedType(tycon, Seq(from, to)) if tycon.isRef(ctx.definitions.MatchCaseClass) =>
1905+
Some((Nil, Nil, from, to))
1906+
case TypeLambda(paramNames, paramBounds, AppliedType(tycon, Seq(from, to))) if tycon.isRef(ctx.definitions.MatchCaseClass) =>
1907+
Some((paramNames.map(_.toString), paramBounds, from, to))
1908+
case _ =>
1909+
None
1910+
end MatchTypeCase
1911+
1912+
given MatchTypeCaseMethods: MatchTypeCaseMethods with
1913+
extension (self: MatchTypeCase):
1914+
def paramNames: List[String] = unwrap(self)(0)
1915+
def paramBounds: List[TypeBounds] = unwrap(self)(1)
1916+
def pattern: TypeRepr = unwrap(self)(2)
1917+
def body: TypeRepr = unwrap(self)(3)
1918+
end extension
1919+
1920+
private def unwrap(x: MatchTypeCase) =
1921+
// should never throw within limits of the API
1922+
MatchTypeCase.unapply(x).get
1923+
end MatchTypeCaseMethods
1924+
18841925
type ByNameType = dotc.core.Types.ExprType
18851926

18861927
object ByNameTypeTypeTest extends TypeTest[TypeRepr, ByNameType]:

library/src/scala/quoted/Quotes.scala

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2442,7 +2442,7 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
24422442
/** Methods of the module object `val MatchType` */
24432443
trait MatchTypeModule { this: MatchType.type =>
24442444
def apply(bound: TypeRepr, scrutinee: TypeRepr, cases: List[TypeRepr]): MatchType
2445-
def unapply(x: MatchType): Option[(TypeRepr, TypeRepr, List[TypeRepr])]
2445+
def unapply(x: MatchType): Option[(TypeRepr, TypeRepr, List[MatchTypeCase])]
24462446
}
24472447

24482448
/** Makes extension methods on `MatchType` available without any imports */
@@ -2453,10 +2453,46 @@ trait Quotes { self: runtime.QuoteUnpickler & runtime.QuoteMatching =>
24532453
extension (self: MatchType):
24542454
def bound: TypeRepr
24552455
def scrutinee: TypeRepr
2456-
def cases: List[TypeRepr]
2456+
def cases: List[MatchTypeCase]
24572457
end extension
24582458
end MatchTypeMethods
24592459

2460+
/** Case of a match type `case U => S`. */
2461+
type MatchTypeCase <: TypeRepr
2462+
2463+
/** `TypeTest` that allows testing at runtime in a pattern match if a `TypeRepr` is a `MatchTypeCase` */
2464+
given MatchTypeCaseTypeTest: TypeTest[TypeRepr, MatchTypeCase]
2465+
2466+
/** Module object of `case U => S` */
2467+
val MatchTypeCase: MatchTypeCaseModule
2468+
2469+
/** Methods of the module object of `case U => S` */
2470+
trait MatchTypeCaseModule { this: MatchTypeCase.type =>
2471+
def apply(pattern: TypeRepr, body: TypeRepr): MatchTypeCase
2472+
2473+
def apply(
2474+
paramNames: List[String],
2475+
boundsFn: TypeLambda => List[TypeBounds],
2476+
patternFn: TypeLambda => TypeRepr,
2477+
bodyFn: TypeLambda => TypeRepr,
2478+
): MatchTypeCase
2479+
2480+
def unapply(x: MatchTypeCase): Option[(List[String], List[TypeBounds], TypeRepr, TypeRepr)]
2481+
}
2482+
2483+
/** Makes extension methods on `MatchTypeCase` available without any imports */
2484+
given MatchTypeCaseMethods: MatchTypeCaseMethods
2485+
2486+
/** Extension methods of `MatchTypeCase` */
2487+
trait MatchTypeCaseMethods:
2488+
extension (self: MatchTypeCase):
2489+
def paramNames: List[String]
2490+
def paramBounds: List[TypeBounds]
2491+
def pattern: TypeRepr
2492+
def body: TypeRepr
2493+
end extension
2494+
end MatchTypeCaseMethods
2495+
24602496
/** Type of a by by name parameter */
24612497
type ByNameType <: TypeRepr
24622498

scala3doc/src/dotty/dokka/tasty/SyntheticSupport.scala

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,3 @@ trait SyntheticsSupport:
9696
given dotc.core.Contexts.Context = qctx.asInstanceOf[scala.quoted.runtime.impl.QuotesImpl].ctx
9797
val cSym = c.symbol.asInstanceOf[dotc.core.Symbols.Symbol]
9898
cSym.typeRef.appliedTo(cSym.typeParams.map(_.typeRef)).asInstanceOf[TypeRepr]
99-
100-
object MatchTypeCase:
101-
def unapply(tpe: TypeRepr): Option[(TypeRepr, TypeRepr)] =
102-
tpe match
103-
case AppliedType(t, Seq(from, to)) /*if t == MatchCaseType*/ =>
104-
Some((from, to))
105-
case TypeLambda(paramNames, paramTypes, AppliedType(t, Seq(from, to))) /*if t == MatchCaseType*/ =>
106-
Some((from, to))
107-
case _ =>
108-
None

scala3doc/src/dotty/dokka/tasty/TypesSupport.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ trait TypesSupport:
240240

241241
case MatchType(bond, sc, cases) =>
242242
val casesTexts = cases.flatMap {
243-
case MatchTypeCase(from, to) =>
243+
case MatchTypeCase(_, _, from, to) =>
244244
texts(" case ") ++ inner(from) ++ texts(" => ") ++ inner(to) ++ texts("\n")
245245
}
246246
inner(sc) ++ texts(" match {\n") ++ casesTexts ++ texts("}")

tests/run-macros/tasty-construct-types/Macro_1.scala

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,17 @@ object Macros {
3333
TypeRepr.of[Int],
3434
TypeRepr.of[List[8]],
3535
List(
36-
TypeLambda(
36+
MatchTypeCase(
3737
List("t"),
3838
_ => List(TypeBounds(TypeRepr.of[Nothing], TypeRepr.of[Any])),
39-
tl => TypeRepr.of[scala.runtime.MatchCase].appliedTo(List(TypeRepr.of[List].appliedTo(tl.param(0)), tl.param(0)))))
39+
tl => TypeRepr.of[List].appliedTo(tl.param(0)),
40+
tl => tl.param(0),
41+
),
42+
MatchTypeCase(
43+
TypeRepr.of[Int],
44+
TypeRepr.of[Int],
45+
)
46+
)
4047
)
4148

4249
assert(x1T =:= TypeRepr.of[1])
@@ -46,7 +53,10 @@ object Macros {
4653
assert(x5T =:= TypeRepr.of[RefineMe { type T = Int }])
4754
assert(x6T =:= TypeRepr.of[List[Int]])
4855
assert(x7T =:= TypeRepr.of[7 @TestAnnotation])
49-
assert(x8T =:= TypeRepr.of[List[8] match { case List[t] => t }])
56+
assert(x8T =:= TypeRepr.of[List[8] match {
57+
case List[t] => t
58+
case Int => Int
59+
}])
5060

5161
'{
5262
println("Ok")

0 commit comments

Comments
 (0)