Skip to content

Commit 528d931

Browse files
Optimize captured type in splice hole (#17070)
If we have a quote that defined a type `T` and use it in the contents of the splice we want to pass a `Type[T]` to the hole. This improves a case where we had a `List[T]` and the hole could end up with a `Type[T]` and `Type[List[T]]`. We should only pass the `Type[T]`.
2 parents 28676ae + eb0d817 commit 528d931

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ class Splicing extends MacroTransform:
246246
if tree.symbol == defn.QuotedTypeModule_of && containsCapturedType(tpt.tpe) =>
247247
val newContent = capturedPartTypes(tpt)
248248
newContent match
249-
case block: Block =>
249+
case block: Block =>
250250
inContext(ctx.withSource(tree.source)) {
251251
Apply(TypeApply(typeof, List(newContent)), List(quotes)).withSpan(tree.span)
252252
}
@@ -342,7 +342,7 @@ class Splicing extends MacroTransform:
342342
val bindingSym = refBindingMap.getOrElseUpdate(tree.symbol, (tree, newBinding))._2
343343
ref(bindingSym)
344344

345-
private def newQuotedTypeClassBinding(tpe: Type)(using Context) =
345+
private def newQuotedTypeClassBinding(tpe: Type)(using Context) =
346346
newSymbol(
347347
spliceOwner,
348348
UniqueName.fresh(nme.Type).toTermName,
@@ -361,7 +361,7 @@ class Splicing extends MacroTransform:
361361
healedTypes = PCPCheckAndHeal.QuoteTypeTags(tpt.span)
362362
val capturePartTypes = new TypeMap {
363363
def apply(tp: Type) = tp match {
364-
case typeRef @ TypeRef(prefix, _) if isCaptured(prefix.typeSymbol) || isCaptured(prefix.termSymbol) =>
364+
case typeRef: TypeRef if containsCapturedType(typeRef) =>
365365
val termRef = refBindingMap
366366
.getOrElseUpdate(typeRef.symbol, (TypeTree(typeRef), newQuotedTypeClassBinding(typeRef)))._2.termRef
367367
val tagRef = healedTypes.nn.getTagRef(termRef)
@@ -376,7 +376,7 @@ class Splicing extends MacroTransform:
376376
tpt match
377377
case block: Block =>
378378
cpy.Block(block)(newHealedTypes ::: block.stats, TypeTree(captured))
379-
case _ =>
379+
case _ =>
380380
if newHealedTypes.nonEmpty then
381381
cpy.Block(tpt)(newHealedTypes, TypeTree(captured))
382382
else

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,11 @@ object TreeChecker {
655655
override def typedHole(tree: untpd.Hole, pt: Type)(using Context): Tree = {
656656
val tree1 @ Hole(isTermHole, _, args, content, tpt) = super.typedHole(tree, pt): @unchecked
657657

658+
// Check that we only add the captured type `T` instead of a more complex type like `List[T]`.
659+
// If we have `F[T]` with captured `F` and `T`, we should list `F` and `T` separately in the args.
660+
for arg <- args do
661+
assert(arg.isTerm || arg.tpe.isInstanceOf[TypeRef], "Expected TypeRef in Hole type args but got: " + arg.tpe)
662+
658663
// Check result type of the hole
659664
if isTermHole then assert(tpt.typeOpt <:< pt)
660665
else assert(tpt.typeOpt =:= pt)

tests/pos-macros/i12440.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,12 @@ trait Mirror:
55

66
class Eq:
77

8+
def test0(using Quotes): Unit = '{
9+
type T
10+
${ summonType[T]; ??? }
11+
${ summonType[List[T]]; ??? }
12+
}
13+
814
def test1(using Quotes): Unit = '{
915
val m: Mirror = ???
1016
${ summonType[m.ElemTypes]; ??? }

0 commit comments

Comments
 (0)