diff --git a/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala b/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala index 728ee9552c81..d21342e54907 100644 --- a/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/PickleQuotes.scala @@ -157,13 +157,20 @@ class PickleQuotes extends MacroTransform { override def apply(tp: Type): Type = tp match case tp: TypeRef if tp.typeSymbol.isTypeSplice => apply(tp.dealias) - case tp @ TypeRef(pre, _) if pre == NoPrefix || pre.termSymbol.isLocal => + case tp @ TypeRef(pre, _) if isLocalPath(pre) => val hiBound = tp.typeSymbol.info match case info: ClassInfo => info.parents.reduce(_ & _) case info => info.hiBound apply(hiBound) + case tp @ TermRef(pre, _) if isLocalPath(pre) => + apply(tp.widenTermRefExpr) case tp => mapOver(tp) + + private def isLocalPath(tp: Type): Boolean = tp match + case NoPrefix => true + case tp: TermRef if !tp.symbol.is(Package) => isLocalPath(tp.prefix) + case tp => false } /** Remove references to local types that will not be defined in this quote */ diff --git a/compiler/src/dotty/tools/dotc/transform/Splicing.scala b/compiler/src/dotty/tools/dotc/transform/Splicing.scala index 7ecde9400445..becee50f25cb 100644 --- a/compiler/src/dotty/tools/dotc/transform/Splicing.scala +++ b/compiler/src/dotty/tools/dotc/transform/Splicing.scala @@ -224,7 +224,7 @@ class Splicing extends MacroTransform: // Dealias references to captured types TypeTree(tree.tpe.dealias) else super.transform(tree) - case tree: TypeTree => + case _: TypeTree | _: SingletonTypeTree => if containsCapturedType(tree.tpe) && level >= 1 then getTagRefFor(tree) else tree case tree @ Assign(lhs: RefTree, rhs) => @@ -353,9 +353,8 @@ class Splicing extends MacroTransform: ) private def capturedType(tree: Tree)(using Context): Symbol = - val tpe = tree.tpe.widenTermRefExpr val bindingSym = refBindingMap - .getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newQuotedTypeClassBinding(tpe)))._2 + .getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newQuotedTypeClassBinding(tree.tpe)))._2 bindingSym private def capturedPartTypes(tpt: Tree)(using Context): Tree = diff --git a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala index 05d3ce5679a3..25eb2af29faf 100644 --- a/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala +++ b/compiler/src/dotty/tools/dotc/transform/TreeChecker.scala @@ -658,7 +658,7 @@ object TreeChecker { // 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) + assert(arg.isTerm || arg.tpe.isInstanceOf[TypeRef] || arg.tpe.isInstanceOf[TermRef], "Expected TypeRef or TermRef in Hole type args but got: " + arg.tpe) // Check result type of the hole if isTermHole then assert(tpt.typeOpt <:< pt) diff --git a/tests/pos-macros/i17103c/Macro_1.scala b/tests/pos-macros/i17103c/Macro_1.scala new file mode 100644 index 000000000000..cb8cf43d44a8 --- /dev/null +++ b/tests/pos-macros/i17103c/Macro_1.scala @@ -0,0 +1,16 @@ +import scala.quoted.* + +inline def test = ${ testExpr } + +def testExpr(using Quotes): Expr[Unit] = + '{ + trait C + val c: C = ??? + ${ + val expr = '{ + val cRef: c.type = ??? + () + } + expr + } + } diff --git a/tests/pos-macros/i17103c/Test_2.scala b/tests/pos-macros/i17103c/Test_2.scala new file mode 100644 index 000000000000..ce2b73e5adf2 --- /dev/null +++ b/tests/pos-macros/i17103c/Test_2.scala @@ -0,0 +1 @@ +def Test = test