Skip to content

Commit 889eab1

Browse files
committed
Fix crashes of path dependent types in spliced Type.of
Previously it was assumed that the type in Type.of could be captured as a whole, which meant that path dependent types for which a separate @SplicedType hole definitions were included in a block, would end up with missing references. Now when find a block in Type.of, we try to analise all parts of the type separately, adding additional hole definitions to the block as necessary. For types that can be captured as a whole (those which did not have a block generated previously, meaning they do not include any @SplicedType hole definitions), old method is used.
1 parent f545d10 commit 889eab1

File tree

2 files changed

+49
-6
lines changed

2 files changed

+49
-6
lines changed

compiler/src/dotty/tools/dotc/transform/Splicing.scala

Lines changed: 33 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,9 +242,14 @@ class Splicing extends MacroTransform:
242242
else args.mapConserve(arg => transformLevel0QuoteContent(arg)(using quoteContext))
243243
}
244244
cpy.Apply(tree)(cpy.Select(sel)(cpy.Apply(app)(fn, newArgs), nme.apply), quotesArgs)
245-
case Apply(TypeApply(_, List(tpt)), List(quotes))
245+
case Apply(TypeApply(typeof, List(tpt)), List(quotes))
246246
if tree.symbol == defn.QuotedTypeModule_of && containsCapturedType(tpt.tpe) =>
247-
ref(capturedType(tpt))(using ctx.withSource(tree.source)).withSpan(tree.span)
247+
tpt match
248+
case block: Block =>
249+
val newBlock = capturedBlockPartTypes(block)
250+
Apply(TypeApply(typeof, List(newBlock)), List(quotes)).withSpan(tree.span)
251+
case _ =>
252+
ref(capturedType(tpt))(using ctx.withSource(tree.source)).withSpan(tree.span)
248253
case CapturedApplication(fn, argss) =>
249254
transformCapturedApplication(tree, fn, argss)
250255
case _ =>
@@ -335,17 +340,39 @@ class Splicing extends MacroTransform:
335340
val bindingSym = refBindingMap.getOrElseUpdate(tree.symbol, (tree, newBinding))._2
336341
ref(bindingSym)
337342

338-
private def capturedType(tree: Tree)(using Context): Symbol =
339-
val tpe = tree.tpe.widenTermRefExpr
340-
def newBinding = newSymbol(
343+
private def newQuotedTypeClassBinding(tpe: Type)(using Context) =
344+
newSymbol(
341345
spliceOwner,
342346
UniqueName.fresh(nme.Type).toTermName,
343347
Param,
344348
defn.QuotedTypeClass.typeRef.appliedTo(tpe),
345349
)
346-
val bindingSym = refBindingMap.getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newBinding))._2
350+
351+
private def capturedType(tree: Tree)(using Context): Symbol =
352+
val tpe = tree.tpe.widenTermRefExpr
353+
val bindingSym = refBindingMap
354+
.getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newQuotedTypeClassBinding(tpe)))._2
347355
bindingSym
348356

357+
private def capturedBlockPartTypes(block: Block)(using Context): Tree =
358+
val old = healedTypes
359+
healedTypes = PCPCheckAndHeal.QuoteTypeTags(block.span)
360+
val capturePartTypes = new TypeMap {
361+
def apply(tp: Type) = tp match {
362+
case typeRef @ TypeRef(prefix, _) if isCaptured(prefix.typeSymbol) || isCaptured(prefix.termSymbol) =>
363+
val termRef = refBindingMap
364+
.getOrElseUpdate(typeRef.symbol, (TypeTree(typeRef), newQuotedTypeClassBinding(typeRef)))._2.termRef
365+
val tagRef = healedTypes.nn.getTagRef(termRef)
366+
tagRef
367+
case _ =>
368+
mapOver(tp)
369+
}
370+
}
371+
val captured = capturePartTypes(block.tpe.widenTermRefExpr)
372+
val newHealedTypes = healedTypes.nn.getTypeTags
373+
healedTypes = old
374+
Block(newHealedTypes ::: block.stats, TypeTree(captured))
375+
349376
private def getTagRefFor(tree: Tree)(using Context): Tree =
350377
val capturedTypeSym = capturedType(tree)
351378
TypeTree(healedTypes.nn.getTagRef(capturedTypeSym.termRef))

tests/pos-macros/i16615.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import scala.quoted.*
2+
3+
trait Api:
4+
type Reader[E]
5+
6+
def bugImpl[T: Type, Q[_]: Type](using Quotes) =
7+
'{
8+
val p: Api = ???
9+
${
10+
Type.of[p.Reader[T]]
11+
Type.of[Q[p.Reader[T]]]
12+
Type.of[p.Reader[Q[p.Reader[T]]]]
13+
Type.of[p.Reader[Q[T]]]
14+
Expr(1)
15+
}
16+
}

0 commit comments

Comments
 (0)