Skip to content

Commit 1fd6034

Browse files
committed
Make type of type hole available quoted patterns
In general, instances of `scala.quoted.Type` are and should not be used explicitly in quotes. ```diff + def f[T](x: T)(using Type[T])(using QuoteContext) = + '{ val y: T = $x; ... } // good code - def f[T](x: T)(using t: Type[T])(using QuoteContext) = - '{ val y: t.T = $x; ... } // bad code - def f[T](x: T)(using t: Type[T])(using QuoteContext) = - '{ val y: $t = $x; ... } // bad code (syntax will be removed) ``` The only exception is on types extracted using quoted patterns as these hide tier type inside an instance of `Type[T]` which must be accessed using it's path. ```diff ??? match case '{ $x: $t } => - '{ val y: t.T = $x; ... } // bad code - '{ val y: $t = $x; ... } // bad code (syntax will be removed) ``` Here `t` is provided as a `given` as if we refer to its type we must be able to summon it. The change is to provide the name of the type that is extracted rather than the `given Type[T]`. `Type[T]` can be summoned were needed as in all other uses of abstract types in quotes. ```diff ??? match case '{ $x: $T } => + '{ val y: T = $x; ... } // good code - val t: Type[T] = summon[Type[T]] - '{ val y: t.T = $x; ... } // bad code - '{ val y: $t = $x; ... } // bad code (syntax will be removed) ``` The pattern will make `T` and a `given Type[T]` available on the right-hand side of the pattern. The `T` can be used the same way it could be used in the implementation of a method with signature: ```scala def f[T](x: T)(using Type[T])(using QuoteContext) = '{ val y: T = $x; ... } ``` ```scala case '{ $x: $T } => '{ val y: T = $x; ... } ``` It is also possible to use lower cases for the type splices `case '{ $x: $t } => '{ val y: t = $x; ... }`. This is similar to the use of type variables in normal patterns `case Some[t](x) =>`. It is preferable to use upper cases as it makes it clearer that this is a type and renders better on the uses in the right-hand side of the pattern.
1 parent 8225502 commit 1fd6034

File tree

23 files changed

+96
-92
lines changed

23 files changed

+96
-92
lines changed

compiler/src/dotty/tools/dotc/core/NameKinds.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -320,6 +320,7 @@ object NameKinds {
320320
val PatMatStdBinderName: UniqueNameKind = new UniqueNameKind("x")
321321
val PatMatAltsName: UniqueNameKind = new UniqueNameKind("matchAlts")
322322
val PatMatResultName: UniqueNameKind = new UniqueNameKind("matchResult")
323+
val PatMatQuoteTypeEv: UniqueNameKind = new UniqueNameKind("tpev$")
323324

324325
val LocalOptInlineLocalObj: UniqueNameKind = new UniqueNameKind("ilo")
325326

compiler/src/dotty/tools/dotc/core/NameOps.scala

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,16 @@ object NameOps {
8080
case _ => false
8181

8282
/** Is name a variable name? */
83-
def isVariableName: Boolean = testSimple { n =>
84-
n.length > 0 && {
85-
val first = n.head
86-
(((first.isLower && first.isLetter) || first == '_')
87-
&& (n != false_)
88-
&& (n != true_)
89-
&& (n != null_))
90-
}
91-
}
83+
def isVariableName: Boolean =
84+
testSimple { n =>
85+
n.length > 0 && {
86+
val first = n.head
87+
(((first.isLower && first.isLetter) || first == '_')
88+
&& (n != false_)
89+
&& (n != true_)
90+
&& (n != null_))
91+
}
92+
} || name.is(PatMatQuoteTypeEv)
9293

9394
def isOpAssignmentName: Boolean = name match {
9495
case raw.NE | raw.LE | raw.GE | EMPTY =>

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import dotty.tools.dotc.core.Constants._
99
import dotty.tools.dotc.core.Contexts._
1010
import dotty.tools.dotc.core.Decorators._
1111
import dotty.tools.dotc.core.Flags._
12-
import dotty.tools.dotc.core.NameKinds.UniqueName
12+
import dotty.tools.dotc.core.NameKinds.{UniqueName, PatMatQuoteTypeEv}
1313
import dotty.tools.dotc.core.Names._
1414
import dotty.tools.dotc.core.StagingContext._
1515
import dotty.tools.dotc.core.StdNames._
@@ -155,19 +155,21 @@ trait QuotesAndSplices {
155155
if ctx.mode.is(Mode.QuotedPattern) && level == 1 then
156156
def spliceOwner(ctx: Context): Symbol =
157157
if (ctx.mode.is(Mode.QuotedPattern)) spliceOwner(ctx.outer) else ctx.owner
158-
val name = tree.expr match {
159-
case Ident(name) => ("$" + name).toTypeName
158+
val (name, expr) = tree.expr match {
159+
case Ident(name) =>
160+
val nameOfSyntheticGiven = PatMatQuoteTypeEv.fresh()
161+
(name.toTypeName, untpd.cpy.Ident(tree.expr)(nameOfSyntheticGiven))
160162
case expr =>
161163
report.error("expected a name binding", expr.srcPos)
162-
"$error".toTypeName
164+
("$error".toTypeName, expr)
163165
}
164166

165167
val typeSymInfo = pt match
166168
case pt: TypeBounds => pt
167169
case _ => TypeBounds.empty
168170
val typeSym = newSymbol(spliceOwner(ctx), name, EmptyFlags, typeSymInfo, NoSymbol, tree.expr.span)
169171
typeSym.addAnnotation(Annotation(New(ref(defn.InternalQuotedPatterns_patternTypeAnnot.typeRef)).withSpan(tree.expr.span)))
170-
val pat = typedPattern(tree.expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))(
172+
val pat = typedPattern(expr, defn.QuotedTypeClass.typeRef.appliedTo(typeSym.typeRef))(
171173
using spliceContext.retractMode(Mode.QuotedPattern).withOwner(spliceOwner(ctx)))
172174
pat.select(tpnme.spliceType)
173175
else
@@ -211,7 +213,7 @@ trait QuotesAndSplices {
211213
def getBinding(sym: Symbol): Bind =
212214
typeBindings.getOrElseUpdate(sym, {
213215
val bindingBounds = sym.info
214-
val bsym = newPatternBoundSymbol(sym.name.toTypeName, bindingBounds, quoted.span)
216+
val bsym = newPatternBoundSymbol(sym.name.toString.stripPrefix("$").toTypeName, bindingBounds, quoted.span)
215217
Bind(bsym, untpd.Ident(nme.WILDCARD).withType(bindingBounds)).withSpan(quoted.span)
216218
})
217219

@@ -260,13 +262,14 @@ trait QuotesAndSplices {
260262
val sym = tree.tpe.dealias.typeSymbol
261263
if sym.exists then
262264
val tdef = TypeDef(sym.asType).withSpan(sym.span)
263-
freshTypeBindingsBuff += transformTypeBindingTypeDef(tdef, freshTypePatBuf)
265+
val nameOfSyntheticGiven = pat.symbol.name.toTermName
266+
freshTypeBindingsBuff += transformTypeBindingTypeDef(nameOfSyntheticGiven, tdef, freshTypePatBuf)
264267
TypeTree(tree.tpe.dealias).withSpan(tree.span)
265268
else
266269
tree
267270
case tdef: TypeDef =>
268271
if tdef.symbol.hasAnnotation(defn.InternalQuotedPatterns_patternTypeAnnot) then
269-
transformTypeBindingTypeDef(tdef, typePatBuf)
272+
transformTypeBindingTypeDef(PatMatQuoteTypeEv.fresh(), tdef, typePatBuf)
270273
else if tdef.symbol.isClass then
271274
val kind = if tdef.symbol.is(Module) then "objects" else "classes"
272275
report.error("Implementation restriction: cannot match " + kind, tree.srcPos)
@@ -302,13 +305,12 @@ trait QuotesAndSplices {
302305
super.transform(tree)
303306
}
304307

305-
private def transformTypeBindingTypeDef(tdef: TypeDef, buff: mutable.Builder[Tree, List[Tree]])(using Context): Tree = {
308+
private def transformTypeBindingTypeDef(nameOfSyntheticGiven: TermName, tdef: TypeDef, buff: mutable.Builder[Tree, List[Tree]])(using Context): Tree = {
306309
if (variance == -1)
307310
tdef.symbol.addAnnotation(Annotation(New(ref(defn.InternalQuotedPatterns_fromAboveAnnot.typeRef)).withSpan(tdef.span)))
308311
val bindingType = getBinding(tdef.symbol).symbol.typeRef
309312
val bindingTypeTpe = AppliedType(defn.QuotedTypeClass.typeRef, bindingType :: Nil)
310-
val bindName = tdef.name.toString.stripPrefix("$").toTermName
311-
val sym = newPatternBoundSymbol(bindName, bindingTypeTpe, tdef.span, flags = ImplicitTerm)(using ctx0)
313+
val sym = newPatternBoundSymbol(nameOfSyntheticGiven, bindingTypeTpe, tdef.span, flags = ImplicitTerm)(using ctx0)
312314
buff += Bind(sym, untpd.Ident(nme.WILDCARD).withType(bindingTypeTpe)).withSpan(tdef.span)
313315
super.transform(tdef)
314316
}

tests/neg-macros/quotedPatterns-5.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import scala.quoted._
22
object Test {
3-
def test(x: quoted.Expr[Int])(using QuoteContext) = x match {
4-
case '{ type $t; poly[$t]($x); 4 } => ??? // error: duplicate pattern variable: $t
5-
case '{ type `$t`; poly[`$t`]($x); 4 } =>
6-
val tt: quoted.Type[_] = t // error
7-
???
3+
def test(x: quoted.Expr[Int])(using QuoteContext): Unit = x match {
4+
case '{ type $T; 4 } => Type[T]
5+
case '{ type $T; poly[$T]($x); 4 } => // error: duplicate pattern variable: T
6+
case '{ type `$T`; poly[`$T`]($x); 4 } =>
7+
Type[T] // error
88
case _ =>
99
}
1010

tests/pos-macros/i6997c.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ inline def mcr(x: => Any): Any = ${mcrImpl('x)}
66

77
def mcrImpl(body: Expr[Any])(using ctx: QuoteContext): Expr[Any] =
88
body match
9-
case '{$x: $t} =>
9+
case '{$x: $T} =>
1010
'{
11-
val tmp: $t = $x
11+
val tmp: T = $x
1212
println(tmp)
1313
tmp
1414
}

tests/pos-macros/i7264.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import scala.quoted._
22
class Foo {
33
def f[T2](t: Type[T2])(using QuoteContext) = t match {
4-
case '[ *:[Int, $t] ] =>
5-
'[ *:[Int, $t] ]
4+
case '[ *:[Int, $T] ] =>
5+
'[ *:[Int, T] ]
66
}
77
}

tests/pos-macros/i7264b.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@ import scala.quoted._
22
class Foo {
33
def f[T2: Type](e: Expr[T2])(using QuoteContext) = e match {
44
case '{ $x: *:[Int, $t] } =>
5-
'[ *:[Int, $t] ]
5+
'[ *:[Int, t] ]
66
}
77
}

tests/pos-macros/i7264c.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import scala.quoted._
22
class Foo {
33
def f[T2: Type](e: Expr[T2])(using QuoteContext) = e match {
4-
case '{ $x: $t0 } =>
5-
t0 match
6-
case '[ *:[Int, $t] ] =>
7-
'[ *:[Int, $t] ]
4+
case '{ $x: $T0 } =>
5+
Type[T0] match
6+
case '[ *:[Int, $T] ] =>
7+
'[ *:[Int, T] ]
88
}
99
}

tests/pos-macros/tasty-constant-type/Macro_1.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ object Macro {
44

55
trait AddInt[A <: Int, B <: Int] { type Out <: Int }
66

7-
transparent inline def ff[A <: Int, B <: Int](): AddInt[A, B] = ${ impl('[A], '[B]) }
7+
transparent inline def ff[A <: Int, B <: Int](): AddInt[A, B] = ${ impl[A, B] }
88

9-
def impl[A <: Int : Type, B <: Int : Type](a: Type[A], b: Type[B])(using qctx: QuoteContext) : Expr[AddInt[A, B]] = {
9+
def impl[A <: Int : Type, B <: Int : Type](using qctx: QuoteContext) : Expr[AddInt[A, B]] = {
1010
import qctx.reflect._
1111

12-
val ConstantType(Constant.Int(v1)) = a.unseal.tpe
13-
val ConstantType(Constant.Int(v2)) = b.unseal.tpe
12+
val ConstantType(Constant.Int(v1)) = Type.of[A]
13+
val ConstantType(Constant.Int(v2)) = Type.of[B]
1414

1515
Literal(Constant.Int(v1 + v2)).tpe.seal match
16-
case '[$t] => '{ null: AddInt[$a, $b] { type Out = $t } }
16+
case '[$T] => '{ null: AddInt[A, B] { type Out = T } }
1717
}
1818
}

tests/run-macros/flops-rewrite-3/Macro_1.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class CheckedTransformation(transform: PartialFunction[Expr[Any], Expr[Any]]) ex
5959
def apply[T: Type](e: Expr[T])(using QuoteContext): Expr[T] = {
6060
transform.applyOrElse(e, identity) match {
6161
case '{ $e2: T } => e2
62-
case '{ $e2: $t } =>
62+
case '{ $e2: $T } =>
6363
throw new Exception(
6464
s"""Transformed
6565
|${e.show}
@@ -69,7 +69,7 @@ class CheckedTransformation(transform: PartialFunction[Expr[Any], Expr[Any]]) ex
6969
|Expected type to be
7070
|${summon[Type[T]].show}
7171
|but was
72-
|${t.show}
72+
|${Type[T].show}
7373
""".stripMargin)
7474
}
7575
}

tests/run-macros/flops-rewrite/Macro_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ private class Rewriter(preTransform: Expr[Any] => Expr[Any], postTransform: Expr
4949
|Expected type to be
5050
|${summon[Type[T]].show}
5151
|but was
52-
|${t.show}
52+
|${Type[t].show}
5353
""".stripMargin)
5454
}
5555
}

tests/run-macros/i7987/Macros_1.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,6 @@ object Macros {
77

88
def macroImpl[T]()(using qctx: QuoteContext): Expr[String] = {
99
Expr.summon[Mirror.Of[Some[Int]]] match
10-
case Some('{ $_ : $t }) => Expr(t.show)
10+
case Some('{ $_ : $T }) => Expr(Type[T].show)
1111
}
1212
}

tests/run-macros/i8007/Macro_1.scala

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import scala.quoted._
44

55
object Macro1 {
66

7-
def mirrorFields[T](t: Type[T])(using qctx: QuoteContext): List[String] =
8-
t match {
9-
case '[$field *: $fields] => field.show :: mirrorFields(fields)
7+
def mirrorFields[T: Type](using qctx: QuoteContext): List[String] =
8+
Type[T] match {
9+
case '[$Field *: $Fields] => Type[Field].show :: mirrorFields[Fields]
1010
case '[EmptyTuple] => Nil
1111
}
1212

@@ -22,8 +22,8 @@ object Macro1 {
2222
val mirrorTpe = '[Mirror.Of[T]]
2323

2424
Expr.summon(using mirrorTpe).get match {
25-
case '{ $m: Mirror.ProductOf[T]{ type MirroredElemLabels = $t } } => {
26-
Expr(mirrorFields(t))
25+
case '{ $m: Mirror.ProductOf[T]{ type MirroredElemLabels = $Elems } } => {
26+
Expr(mirrorFields[Elems])
2727
}
2828
}
2929
}

tests/run-macros/i8007/Macro_2.scala

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import scala.quoted._
44

55
object Macro2 {
66

7-
def mirrorFields[T](t: Type[T])(using qctx: QuoteContext): List[String] =
7+
def mirrorFields[T](using t: Type[T])(using qctx: QuoteContext): List[String] =
88
t match {
9-
case '[$field *: $fields] => field.show.substring(1, field.show.length-1) :: mirrorFields(fields)
9+
case '[$Field *: $Fields] => Type[Field].show.substring(1, Type[Field].show.length-1) :: mirrorFields[Fields]
1010
case '[EmptyTuple] => Nil
1111
}
1212

@@ -24,8 +24,8 @@ object Macro2 {
2424
import qctx.reflect._
2525

2626
val fields = ev match {
27-
case '{ $m: Mirror.ProductOf[T] { type MirroredElemLabels = $t } } =>
28-
mirrorFields(t)
27+
case '{ $m: Mirror.ProductOf[T] { type MirroredElemLabels = $Labels } } =>
28+
mirrorFields[Labels]
2929
}
3030

3131
val body: Expr[T] => Expr[String] = elem =>

tests/run-macros/i8007/Macro_3.scala

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ object Eq {
2525
def eqv(x: T, y: T): Boolean = body(x, y)
2626
}
2727

28-
def summonAll[T](t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match {
29-
case '[String *: $tpes] => '{ summon[Eq[String]] } :: summonAll(tpes)
30-
case '[Int *: $tpes] => '{ summon[Eq[Int]] } :: summonAll(tpes)
31-
case '[$tpe *: $tpes] => derived(using tpe, qctx) :: summonAll(tpes)
28+
def summonAll[T](using t: Type[T])(using qctx: QuoteContext): List[Expr[Eq[_]]] = t match {
29+
case '[String *: $Tpes] => '{ summon[Eq[String]] } :: summonAll[Tpes]
30+
case '[Int *: $Tpes] => '{ summon[Eq[Int]] } :: summonAll[Tpes]
31+
case '[$Tpe *: $Tpes] => derived[Tpe] :: summonAll[Tpes]
3232
case '[EmptyTuple] => Nil
3333
}
3434

@@ -38,8 +38,8 @@ object Eq {
3838
val ev: Expr[Mirror.Of[T]] = Expr.summon(using '[Mirror.Of[T]]).get
3939

4040
ev match {
41-
case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = $elementTypes }} =>
42-
val elemInstances = summonAll(elementTypes)
41+
case '{ $m: Mirror.ProductOf[T] { type MirroredElemTypes = $ElementTypes }} =>
42+
val elemInstances = summonAll[ElementTypes]
4343
val eqProductBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => {
4444
elemInstances.zipWithIndex.foldLeft(Expr(true: Boolean)) {
4545
case (acc, (elem, index)) =>
@@ -53,8 +53,8 @@ object Eq {
5353
eqProduct((x: T, y: T) => ${eqProductBody('x, 'y)})
5454
}
5555

56-
case '{ $m: Mirror.SumOf[T] { type MirroredElemTypes = $elementTypes }} =>
57-
val elemInstances = summonAll(elementTypes)
56+
case '{ $m: Mirror.SumOf[T] { type MirroredElemTypes = $ElementTypes }} =>
57+
val elemInstances = summonAll[ElementTypes]
5858
val eqSumBody: (Expr[T], Expr[T]) => Expr[Boolean] = (x, y) => {
5959
val ordx = '{ $m.ordinal($x) }
6060
val ordy = '{ $m.ordinal($y) }

tests/run-macros/quote-matcher-symantics-3/quoted_1.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ object Macros {
2020
object FromEnv {
2121
def unapply[T](e: Expr[Any])(using env: Env): Option[Expr[R[T]]] =
2222
e match
23-
case '{envVar[$t](${Const(id)})} =>
23+
case '{envVar[$_](${Const(id)})} =>
2424
env.get(id).asInstanceOf[Option[Expr[R[T]]]] // We can only add binds that have the same type as the refs
2525
case _ =>
2626
None
@@ -39,11 +39,11 @@ object Macros {
3939
case '{ ($x: Int) <= ($y: Int) } =>
4040
'{ $sym.leq(${lift(x)}, ${lift(y)}).asInstanceOf[R[T]] }
4141

42-
case '{ ${f}($arg: $t): $u } =>
43-
'{ $sym.app[$t, $u](${lift(f)}, ${lift(arg)}).asInstanceOf[R[T]] }
42+
case '{ ${f}($arg: $A): $B } =>
43+
'{ $sym.app[A, B](${lift(f)}, ${lift(arg)}).asInstanceOf[R[T]] }
4444

45-
case '{ (if ($cond) $thenp else $elsep): $t } =>
46-
'{ $sym.ifThenElse[$t](${lift(cond)}, ${lift(thenp)}, ${lift(elsep)}) }.asInstanceOf[Expr[R[T]]]
45+
case '{ (if ($cond) $thenp else $elsep): $A } =>
46+
'{ $sym.ifThenElse[A](${lift(cond)}, ${lift(thenp)}, ${lift(elsep)}) }.asInstanceOf[Expr[R[T]]]
4747

4848
case '{ (x0: Int) => $bodyFn(x0): Any } =>
4949
val (i, nEnvVar) = freshEnvVar[Int]()
@@ -60,8 +60,8 @@ object Macros {
6060
val body2 = UnsafeExpr.open(bodyFn) { (body1, close) => close(body1)(nEnvVar) }
6161
'{ $sym.lam((x: R[Int => Int]) => ${given Env = envWith(i, 'x)(using env); lift(body2)}).asInstanceOf[R[T]] }
6262

63-
case '{ Symantics.fix[$t, $u]($f) } =>
64-
'{ $sym.fix[$t, $u]((x: R[$t => $u]) => $sym.app(${lift(f)}, x)).asInstanceOf[R[T]] }
63+
case '{ Symantics.fix[$A, $B]($f) } =>
64+
'{ $sym.fix[A, B]((x: R[A => B]) => $sym.app(${lift(f)}, x)).asInstanceOf[R[T]] }
6565

6666
case FromEnv(expr) => expr.asInstanceOf[Expr[R[T]]]
6767

tests/run-macros/quote-matcher-type-bind/Macro_1.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ object Macros {
77

88
private def impl(x: Expr[Unit])(using QuoteContext): Expr[Unit] = {
99
x match {
10-
case '{ DSL.f[$t]($x) } => '{ DSL.g[$t]($x) }
11-
case '{ DSL.g[$t]($x) } => '{ DSL.f[$t]($x) }
10+
case '{ DSL.f[$T]($x) } => '{ DSL.g[T]($x) }
11+
case '{ DSL.g[$T]($x) } => '{ DSL.f[T]($x) }
1212
case _ => x
1313
}
1414
}

tests/run-macros/quote-type-matcher-2/quoted_1.scala

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,17 @@ import scala.quoted._
22

33
object Macros {
44

5-
inline def lift[A]: String = ${ matchesExpr('[A]) }
5+
inline def lift[A]: String = ${ matchesExpr[A] }
66

7-
private def matchesExpr(tp: Type[_])(using QuoteContext): Expr[String] = {
8-
def lift(tp: Type[_]): String = tp match {
7+
private def matchesExpr[A](using tp: Type[A])(using QuoteContext): Expr[String] = {
8+
def lift[T](using tp: Type[T]): String = tp match {
99
case '[Int] => "%Int%"
10-
case '[List[$t]] => s"%List[${lift(t)}]%"
11-
case '[Option[$t]] => s"%Option[${lift(t)}]%"
12-
case '[Function1[$t, $u]] => s"%${lift(t)} => ${lift(u)}%"
10+
case '[List[$T]] => s"%List[${lift[T]}]%"
11+
case '[Option[$T]] => s"%Option[${lift[T]}]%"
12+
case '[Function1[$T, $U]] => s"%${lift[T]} => ${lift[U]}%"
1313
case _ => tp.show
1414
}
15-
Expr(lift(tp))
15+
Expr(lift[A])
1616
}
1717

1818
}

0 commit comments

Comments
 (0)