Skip to content

Commit

Permalink
Splice hole with singleton captures (#18357)
Browse files Browse the repository at this point in the history
When we had a reference to a `x.type` we mistakenly captured `x` instead
of `x.type`. This was caused because `SingletonTypeTree` was not handled
in `Splicing`.

Revisit #17109
  • Loading branch information
nicolasstucki authored Aug 15, 2023
2 parents 6fb7ee9 + df0c16f commit 37a0750
Show file tree
Hide file tree
Showing 4 changed files with 21 additions and 7 deletions.
7 changes: 2 additions & 5 deletions compiler/src/dotty/tools/dotc/transform/Splicing.scala
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,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) =>
Expand Down Expand Up @@ -314,10 +314,7 @@ 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
bindingSym
refBindingMap.getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newQuotedTypeClassBinding(tree.tpe)))._2

private def capturedPartTypes(quote: Quote)(using Context): Tree =
val (tags, body1) = inContextWithQuoteTypeTags {
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -727,7 +727,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 | TermRef | ThisType], "Unexpected type arg in Hole: " + arg.tpe)

// Check result type of the hole
if isTerm then assert(tree1.typeOpt <:< pt)
Expand All @@ -743,7 +743,7 @@ object TreeChecker {
defn.AnyType
case tpe => tpe
defn.QuotedExprClass.typeRef.appliedTo(tpe)
else defn.QuotedTypeClass.typeRef.appliedTo(arg.typeOpt.widenTermRefExpr)
else defn.QuotedTypeClass.typeRef.appliedTo(arg.typeOpt)
}
val expectedResultType =
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tree1.typeOpt)
Expand Down
16 changes: 16 additions & 0 deletions tests/pos-macros/i17103c/Macro_1.scala
Original file line number Diff line number Diff line change
@@ -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
}
}
1 change: 1 addition & 0 deletions tests/pos-macros/i17103c/Test_2.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
def Test = test

0 comments on commit 37a0750

Please sign in to comment.