@@ -103,49 +103,52 @@ class PCPCheckAndHeal(@constructorOnly ictx: Context) extends TreeMapWithStages(
103103 if (ctx.property(InAnnotation ).isDefined)
104104 report.error(" Cannot have a quote in an annotation" , quote.srcPos)
105105
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)
111111 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)
114114
115115 if body.isTerm then
116+ val transformedBody = transformBody()
116117 // `quoted.runtime.Expr.quote[T](<body>)` --> `quoted.runtime.Expr.quote[T2](<body2>)`
117118 val TypeApply (fun, targs) = quote.fun: @ unchecked
118119 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 )
120121 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)
142126 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+
147137 }
148138
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+
149152 /** Transform splice
150153 * - If inside a quote, transform the contents of the splice.
151154 * - If inside inlined code, expand the macro code.
0 commit comments