@@ -103,49 +103,52 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
103
103
if (ctx.property(InAnnotation ).isDefined)
104
104
report.error(" Cannot have a quote in an annotation" , quote.srcPos)
105
105
106
- val contextWithQuote =
107
- if level == 0 then contextWithQuoteTypeTags(taggedTypes)( using quoteContext)
108
- else quoteContext
109
- val body1 = transform(body)( using contextWithQuote)
110
- val body2 =
106
+ def transformBody () =
107
+ val contextWithQuote =
108
+ if level == 0 then contextWithQuoteTypeTags(taggedTypes)( using quoteContext)
109
+ else quoteContext
110
+ val transformedBody = transform(body)( using contextWithQuote)
111
111
taggedTypes.getTypeTags match
112
- case Nil => body1
113
- case tags => tpd.Block (tags, body1 ).withSpan(body.span)
112
+ case Nil => transformedBody
113
+ case tags => tpd.Block (tags, transformedBody ).withSpan(body.span)
114
114
115
115
if body.isTerm then
116
+ val transformedBody = transformBody()
116
117
// `quoted.runtime.Expr.quote[T](<body>)` --> `quoted.runtime.Expr.quote[T2](<body2>)`
117
118
val TypeApply (fun, targs) = quote.fun: @ unchecked
118
119
val targs2 = targs.map(targ => TypeTree (healTypeOfTerm(quote.fun.srcPos)(targ.tpe)))
119
- cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, targs2), body2 :: Nil )
120
+ cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, targs2), transformedBody :: Nil )
120
121
else
121
- object DirectTypeOfRef :
122
- def unapply (body : Tree ): Option [Tree ] =
123
- body.tpe match
124
- case tp @ TypeRef (x : TermRef , _) if tp.symbol == defn.QuotedType_splice =>
125
- // Optimization: `quoted.Type.of[x.Underlying](quotes)` --> `x`
126
- Some (ref(x).withSpan(quote.span))
127
- case _ =>
128
- body2 match
129
- case Block (List (tdef : TypeDef ), tpt : TypeTree ) =>
130
- tpt.tpe match
131
- case tpe : TypeRef if tpe.typeSymbol == tdef.symbol =>
132
- tdef.rhs.tpe.hiBound match
133
- case tp @ TypeRef (x : TermRef , _) if tp.symbol == defn.QuotedType_splice =>
134
- // Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
135
- Some (ref(x).withSpan(quote.span))
136
- case _ => None
137
- case _ => None
138
- case _ => None
139
-
140
- body match
141
- case DirectTypeOfRef (ref) => ref
122
+ body.tpe match
123
+ case tp @ TypeRef (x : TermRef , _) if tp.symbol == defn.QuotedType_splice =>
124
+ // Optimization: `quoted.Type.of[x.Underlying](quotes)` --> `x`
125
+ ref(x).withSpan(quote.span)
142
126
case _ =>
143
- val quotes = quote.args.mapConserve(transform)
144
- // `quoted.Type.of[<body>](quotes)` --> `quoted.Type.of[<body2>](quotes)`
145
- val TypeApply (fun, _) = quote.fun: @ unchecked
146
- cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, body2 :: Nil ), quotes)
127
+ transformBody() match
128
+ case HealedDirectQuotedTypeRef (termRef) =>
129
+ // Optimization: `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` --> `x`
130
+ ref(termRef).withSpan(quote.span)
131
+ case transformedBody =>
132
+ val quotes = quote.args.mapConserve(transform)
133
+ // `quoted.Type.of[<body>](quotes)` --> `quoted.Type.of[<body2>](quotes)`
134
+ val TypeApply (fun, _) = quote.fun: @ unchecked
135
+ cpy.Apply (quote)(cpy.TypeApply (quote.fun)(fun, transformedBody :: Nil ), quotes)
136
+
147
137
}
148
138
139
+ private object HealedDirectQuotedTypeRef :
140
+ /** Matches `quoted.Type.of[@SplicedType type T = x.Underlying; T](quotes)` and extracts the TermRef to `x` */
141
+ def unapply (body : Tree )(using Context ): Option [TermRef ] =
142
+ body match
143
+ case Block (List (tdef : TypeDef ), tpt : TypeTree ) =>
144
+ tpt.tpe match
145
+ case tpe : TypeRef if tpe.typeSymbol == tdef.symbol =>
146
+ tdef.rhs.tpe.hiBound match
147
+ case tp @ TypeRef (x : TermRef , _) if tp.symbol == defn.QuotedType_splice => Some (x)
148
+ case _ => None
149
+ case _ => None
150
+ case _ => None
151
+
149
152
/** Transform splice
150
153
* - If inside a quote, transform the contents of the splice.
151
154
* - If inside inlined code, expand the macro code.
0 commit comments