Skip to content

Commit 52aaeb5

Browse files
committed
Fix captured references to singleton types
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`. Fixing this uncovered some inconsistencies with the types in the encoding of the hole captured types and contents. These have been fixed as well.
1 parent b0ad1e1 commit 52aaeb5

File tree

5 files changed

+37
-4
lines changed

5 files changed

+37
-4
lines changed

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,10 @@ class PickleQuotes extends MacroTransform {
162162
case info: ClassInfo => info.parents.reduce(_ & _)
163163
case info => info.hiBound
164164
apply(hiBound)
165+
case tp @ TermRef(pre, _) if isLocalPath(pre) =>
166+
apply(tp.widenTermRefExpr)
167+
case ThisType(ref @ TypeRef(pre, _)) if isLocalPath(pre) =>
168+
apply(ref)
165169
case tp =>
166170
mapOver(tp)
167171

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ class Splicing extends MacroTransform:
231231
// Dealias references to captured types
232232
TypeTree(tree.tpe.dealias)
233233
else super.transform(tree)
234-
case tree: TypeTree =>
234+
case _: TypeTree | _: SingletonTypeTree =>
235235
if containsCapturedType(tree.tpe) && level >= 1 then getTagRefFor(tree)
236236
else tree
237237
case tree @ Assign(lhs: RefTree, rhs) =>
@@ -360,9 +360,8 @@ class Splicing extends MacroTransform:
360360
)
361361

362362
private def capturedType(tree: Tree)(using Context): Symbol =
363-
val tpe = tree.tpe.widenTermRefExpr
364363
val bindingSym = refBindingMap
365-
.getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newQuotedTypeClassBinding(tpe)))._2
364+
.getOrElseUpdate(tree.symbol, (TypeTree(tree.tpe), newQuotedTypeClassBinding(tree.tpe)))._2
366365
bindingSym
367366

368367
private def capturedPartTypes(tpt: Tree)(using Context): Tree =

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -663,7 +663,7 @@ object TreeChecker {
663663
// Check that we only add the captured type `T` instead of a more complex type like `List[T]`.
664664
// If we have `F[T]` with captured `F` and `T`, we should list `F` and `T` separately in the args.
665665
for arg <- args do
666-
assert(arg.isTerm || arg.tpe.isInstanceOf[TypeRef], "Expected TypeRef in Hole type args but got: " + arg.tpe)
666+
assert(arg.isTerm || arg.tpe.isInstanceOf[TypeRef] || arg.tpe.isInstanceOf[TermRef] || arg.tpe.isInstanceOf[ThisType], "Expected TypeRef or TermRef in Hole type args but got: " + arg.tpe)
667667

668668
// Check result type of the hole
669669
if isTermHole then assert(tpt.typeOpt <:< pt)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import scala.quoted.*
2+
3+
object Macro:
4+
inline def generateCode: Unit = ${ testThisPaths }
5+
6+
def testThisPaths(using Quotes): Expr[Unit] =
7+
'{
8+
trait E extends G:
9+
type V
10+
val f: F
11+
${
12+
val expr = '{
13+
// val _: Any = this // FIXME: this should work
14+
// val _: Any = f // FIXME: this should work
15+
val _: this.type = ???
16+
val _: V = ???
17+
val _: this.V = ???
18+
val _: this.f.V = ???
19+
val _: this.type = ???
20+
val _: this.f.type = ???
21+
}
22+
expr
23+
}
24+
trait F:
25+
type V
26+
}
27+
28+
trait G:
29+
val f: Any
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
@main def test = Macro.generateCode

0 commit comments

Comments
 (0)