diff --git a/compiler/src/dotty/tools/dotc/transform/Splicing.scala b/compiler/src/dotty/tools/dotc/transform/Splicing.scala index 393fe46b8438..deea32dba6ca 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicing.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicing.scala @@ -246,7 +246,7 @@ class Splicing extends MacroTransform: if tree.symbol == defn.QuotedTypeModule_of && containsCapturedType(tpt.tpe) => val newContent = capturedPartTypes(tpt) newContent match - case block: Block => + case block: Block => inContext(ctx.withSource(tree.source)) { Apply(TypeApply(typeof, List(newContent)), List(quotes)).withSpan(tree.span) } @@ -342,7 +342,7 @@ class Splicing extends MacroTransform: val bindingSym = refBindingMap.getOrElseUpdate(tree.symbol, (tree, newBinding))._2 ref(bindingSym) - private def newQuotedTypeClassBinding(tpe: Type)(using Context) = + private def newQuotedTypeClassBinding(tpe: Type)(using Context) = newSymbol( spliceOwner, UniqueName.fresh(nme.Type).toTermName, @@ -361,7 +361,7 @@ class Splicing extends MacroTransform: healedTypes = PCPCheckAndHeal.QuoteTypeTags(tpt.span) val capturePartTypes = new TypeMap { def apply(tp: Type) = tp match { - case typeRef @ TypeRef(prefix, _) if isCaptured(prefix.typeSymbol) || isCaptured(prefix.termSymbol) => + case typeRef: TypeRef if containsCapturedType(typeRef) => val termRef = refBindingMap .getOrElseUpdate(typeRef.symbol, (TypeTree(typeRef), newQuotedTypeClassBinding(typeRef)))._2.termRef val tagRef = healedTypes.nn.getTagRef(termRef) @@ -376,7 +376,7 @@ class Splicing extends MacroTransform: tpt match case block: Block => cpy.Block(block)(newHealedTypes ::: block.stats, TypeTree(captured)) - case _ => + case _ => if newHealedTypes.nonEmpty then cpy.Block(tpt)(newHealedTypes, TypeTree(captured)) else diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 52942ea719f9..5d2d3c7e2df8 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -655,6 +655,11 @@ object TreeChecker { override def typedHole(tree: untpd.Hole, pt: Type)(using Context): Tree = { val tree1 @ Hole(isTermHole, _, args, content, tpt) = super.typedHole(tree, pt): @unchecked + // Check that we only add the captured type `T` instead of a more complex type like `List[T]`. + // If we have `F[T]` with captured `F` and `T`, we should list `F` and `T` separately in the args. + for arg <- args do + assert(arg.isTerm || arg.tpe.isInstanceOf[TypeRef], "Expected TypeRef in Hole type args but got: " + arg.tpe) + // Check result type of the hole if isTermHole then assert(tpt.typeOpt <:< pt) else assert(tpt.typeOpt =:= pt) diff --git a/tests/pos-macros/i12440.scala b/tests/pos-macros/i12440.scala index 4b4c56fef568..02122be28deb 100644 --- a/tests/pos-macros/i12440.scala +++ b/tests/pos-macros/i12440.scala @@ -5,6 +5,12 @@ trait Mirror: class Eq: + def test0(using Quotes): Unit = '{ + type T + ${ summonType[T]; ??? } + ${ summonType[List[T]]; ??? } + } + def test1(using Quotes): Unit = '{ val m: Mirror = ??? ${ summonType[m.ElemTypes]; ??? }