Skip to content

Commit 86ff4f2

Browse files
committed
Split Hole from PrickledHole
1 parent 67b16d0 commit 86ff4f2

File tree

7 files changed

+47
-15
lines changed

7 files changed

+47
-15
lines changed

compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -975,6 +975,23 @@ object Trees {
975975
def genericEmptyValDef[T <: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]]
976976
def genericEmptyTree[T <: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]]
977977

978+
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
979+
* It is only used when encoding pickled quotes. These will be encoded
980+
* as PickledHole when pickled.
981+
*
982+
* @param isTermHole If this hole is a term, otherwise it is a type hole.
983+
* @param idx The index of the hole in it's enclosing level 0 quote.
984+
* @param targs The type arguments of the splice to compute its content
985+
* @param args The term (or type) arguments of the splice to compute its content
986+
* @param tpt Type of the hole
987+
* @param content Lambda that computes the content of the hole. This tree is empty when in a quote pickle.
988+
*/
989+
case class Hole[+T <: Untyped](isTermHole: Boolean, idx: Int, targs: List[Tree[T]], args: List[Tree[T]], content: Tree[T], tpt: Tree[T])(implicit @constructorOnly src: SourceFile) extends Tree[T] {
990+
type ThisTree[+T <: Untyped] <: Hole[T]
991+
override def isTerm: Boolean = isTermHole
992+
override def isType: Boolean = !isTermHole
993+
}
994+
978995
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
979996
* It is only used when picking quotes (will never be in a TASTy file).
980997
*
@@ -986,13 +1003,11 @@ object Trees {
9861003
*
9871004
* @param isTermHole If this hole is a term, otherwise it is a type hole.
9881005
* @param idx The index of the hole in it's enclosing level 0 quote.
989-
* @param targs The type arguments of the splice to compute its content
9901006
* @param args The term (or type) arguments of the splice to compute its content
9911007
* @param tpt Type of the hole
992-
* @param content Lambda that computes the content of the hole. This tree is empty when in a quote pickle.
9931008
*/
994-
case class Hole[+T <: Untyped](isTermHole: Boolean, idx: Int, targs: List[Tree[T]], args: List[Tree[T]], content: Tree[T], tpt: Tree[T])(implicit @constructorOnly src: SourceFile) extends Tree[T] {
995-
type ThisTree[+T <: Untyped] <: Hole[T]
1009+
case class PickledHole[+T <: Untyped](isTermHole: Boolean, idx: Int, args: List[Tree[T]], tpt: Tree[T])(implicit @constructorOnly src: SourceFile) extends Tree[T] {
1010+
type ThisTree[+T <: Untyped] <: PickledHole[T]
9961011
override def isTerm: Boolean = isTermHole
9971012
override def isType: Boolean = !isTermHole
9981013
}
@@ -1119,6 +1134,7 @@ object Trees {
11191134
type Thicket = Trees.Thicket[T]
11201135

11211136
type Hole = Trees.Hole[T]
1137+
type PickledHole = Trees.PickledHole[T]
11221138

11231139
@sharable val EmptyTree: Thicket = genericEmptyTree
11241140
@sharable val EmptyValDef: ValDef = genericEmptyValDef
@@ -1345,9 +1361,13 @@ object Trees {
13451361
case _ => finalize(tree, untpd.Thicket(trees)(sourceFile(tree)))
13461362
}
13471363
def Hole(tree: Tree)(isTerm: Boolean, idx: Int, targs: List[Tree], args: List[Tree], content: Tree, tpt: Tree)(using Context): Hole = tree match {
1348-
case tree: Hole if isTerm == tree.isTerm && idx == tree.idx && targs.eq(tree.targs) && args.eq(tree.args) && content.eq(tree.content) && content.eq(tree.content) => tree
1364+
case tree: Hole if isTerm == tree.isTerm && idx == tree.idx && targs.eq(tree.targs) && args.eq(tree.args) && content.eq(tree.content) && tpt.eq(tree.tpt) => tree
13491365
case _ => finalize(tree, untpd.Hole(isTerm, idx, targs, args, content, tpt)(sourceFile(tree)))
13501366
}
1367+
def PickledHole(tree: Tree)(isTerm: Boolean, idx: Int, args: List[Tree], tpt: Tree)(using Context): PickledHole = tree match {
1368+
case tree: PickledHole if isTerm == tree.isTerm && idx == tree.idx && args.eq(tree.args) && tpt.eq(tree.tpt) => tree
1369+
case _ => finalize(tree, untpd.PickledHole(isTerm, idx, args, tpt)(sourceFile(tree)))
1370+
}
13511371

13521372
// Copier methods with default arguments; these demand that the original tree
13531373
// is of the same class as the copy. We only include trees with more than 2 elements here.
@@ -1371,6 +1391,8 @@ object Trees {
13711391
Template(tree: Tree)(constr, parents, derived, self, body)
13721392
def Hole(tree: Hole)(isTerm: Boolean = tree.isTerm, idx: Int = tree.idx, targs: List[Tree] = tree.targs, args: List[Tree] = tree.args, content: Tree = tree.content, tpt: Tree = tree.tpt)(using Context): Hole =
13731393
Hole(tree: Tree)(isTerm, idx, targs, args, content, tpt)
1394+
def PickledHole(tree: PickledHole)(isTerm: Boolean = tree.isTerm, idx: Int = tree.idx, args: List[Tree] = tree.args, tpt: Tree = tree.tpt)(using Context): PickledHole =
1395+
PickledHole(tree: Tree)(isTerm, idx, args, tpt)
13741396

13751397
}
13761398

@@ -1503,6 +1525,8 @@ object Trees {
15031525
if (trees1 eq trees) tree else Thicket(trees1)
15041526
case tree @ Hole(_, _, targs, args, content, tpt) =>
15051527
cpy.Hole(tree)(targs = transform(targs), args = transform(args), content = transform(content), tpt = transform(tpt))
1528+
case tree @ PickledHole(_, _, args, tpt) =>
1529+
cpy.PickledHole(tree)(args = transform(args), tpt = transform(tpt))
15061530
case _ =>
15071531
transformMoreCases(tree)
15081532
}
@@ -1644,6 +1668,8 @@ object Trees {
16441668
this(x, ts)
16451669
case Hole(_, _, targs, args, content, tpt) =>
16461670
this(this(this(this(x, targs), args), content), tpt)
1671+
case PickledHole(_, _, args, tpt) =>
1672+
this(this(x, args), tpt)
16471673
case _ =>
16481674
foldMoreCases(x, tree)
16491675
}

compiler/src/dotty/tools/dotc/ast/untpd.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
427427
def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats)
428428
def Annotated(arg: Tree, annot: Tree)(implicit src: SourceFile): Annotated = new Annotated(arg, annot)
429429
def Hole(isTermHole: Boolean, idx: Int, targs: List[Tree], args: List[Tree], content: Tree, tpt: Tree)(implicit src: SourceFile): Hole = new Hole(isTermHole, idx, targs, args, content, tpt)
430+
def PickledHole(isTermHole: Boolean, idx: Int, args: List[Tree], tpt: Tree)(implicit src: SourceFile): PickledHole = new PickledHole(isTermHole, idx, args, tpt)
430431

431432
// ------ Additional creation methods for untyped only -----------------
432433

compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,9 +1438,8 @@ class TreeUnpickler(reader: TastyReader,
14381438
case HOLE =>
14391439
val idx = readNat()
14401440
val tpe = readType()
1441-
val targs = Nil // TODO read tags seprately from args
14421441
val args = until(end)(readTerm())
1443-
Hole(true, idx, targs, args, EmptyTree, TypeTree(tpe)).withType(tpe)
1442+
PickledHole(true, idx, args, TypeTree(tpe)).withType(tpe)
14441443
case _ =>
14451444
readPathTerm()
14461445
}
@@ -1473,9 +1472,8 @@ class TreeUnpickler(reader: TastyReader,
14731472
val end = readEnd()
14741473
val idx = readNat()
14751474
val tpe = readType()
1476-
val targs = Nil // TODO read tags seprately from args
14771475
val args = until(end)(readTerm())
1478-
Hole(false, idx, targs, args, EmptyTree, TypeTree(tpe)).withType(tpe)
1476+
PickledHole(false, idx, args, TypeTree(tpe)).withType(tpe)
14791477
case _ =>
14801478
if (isTypeTreeTag(nextByte)) readTerm()
14811479
else {

compiler/src/dotty/tools/dotc/quoted/PickledQuotes.scala

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -100,14 +100,14 @@ object PickledQuotes {
100100
private def spliceTerms(tree: Tree, typeHole: TypeHole, termHole: ExprHole)(using Context): Tree = {
101101
def evaluateHoles = new TreeMap {
102102
override def transform(tree: tpd.Tree)(using Context): tpd.Tree = tree match {
103-
case Hole(isTermHole, idx, targs, args, _, _) =>
103+
case PickledHole(isTermHole, idx, args, _) =>
104104
inContext(SpliceScope.contextWithNewSpliceScope(tree.sourcePos)) {
105105
if isTermHole then
106106
val quotedExpr = termHole match
107107
case ExprHole.V1(evalHole) =>
108-
evalHole.nn.apply(idx, reifyExprHoleV1Args(targs ::: args), QuotesImpl())
108+
evalHole.nn.apply(idx, reifyExprHoleV1Args(args), QuotesImpl())
109109
case ExprHole.V2(evalHole) =>
110-
evalHole.nn.apply(idx, reifyExprHoleV2Args(targs ::: args), QuotesImpl())
110+
evalHole.nn.apply(idx, reifyExprHoleV2Args(args), QuotesImpl())
111111

112112
val filled = PickledQuotes.quotedExprToTree(quotedExpr)
113113

@@ -165,15 +165,15 @@ object PickledQuotes {
165165
val tree = typeHole match
166166
case TypeHole.V1(evalHole) =>
167167
tdef.rhs match
168-
case TypeBoundsTree(_, Hole(_, idx, targs, args, _, _), _) =>
168+
case TypeBoundsTree(_, PickledHole(_, idx, args, _), _) =>
169169
// To keep for backwards compatibility. In some older version holes where created in the bounds.
170-
val quotedType = evalHole.nn.apply(idx, reifyTypeHoleArgs(targs ::: args))
170+
val quotedType = evalHole.nn.apply(idx, reifyTypeHoleArgs(args))
171171
PickledQuotes.quotedTypeToTree(quotedType)
172172
case TypeBoundsTree(_, tpt, _) =>
173173
// To keep for backwards compatibility. In some older version we missed the creation of some holes.
174174
tpt
175175
case TypeHole.V2(types) =>
176-
val Hole(_, idx, _, _, _, _) = tdef.rhs: @unchecked
176+
val PickledHole(_, idx, _, _) = tdef.rhs: @unchecked
177177
PickledQuotes.quotedTypeToTree(types.nn.apply(idx))
178178
(tdef.symbol, tree.tpe)
179179
}.toMap

compiler/src/dotty/tools/dotc/typer/QuotesAndSplices.scala

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,10 @@ trait QuotesAndSplices {
168168
val tpt = typedType(tree.tpt)
169169
assignType(tree, tpt)
170170

171+
def typedPickledHole(tree: untpd.PickledHole, pt: Type)(using Context): Tree =
172+
val tpt = typedType(tree.tpt)
173+
assignType(tree, tpt)
174+
171175
private def checkSpliceOutsideQuote(tree: untpd.Tree)(using Context): Unit =
172176
if (level == 0 && !ctx.owner.ownersIterator.exists(_.isInlineMethod))
173177
report.error("Splice ${...} outside quotes '{...} or inline method", tree.srcPos)

compiler/src/dotty/tools/dotc/typer/TypeAssigner.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,8 @@ trait TypeAssigner {
536536
def assignType(tree: untpd.Hole, tpt: Tree)(using Context): Hole =
537537
tree.withType(tpt.tpe)
538538

539+
def assignType(tree: untpd.PickledHole, tpt: Tree)(using Context): PickledHole =
540+
tree.withType(tpt.tpe)
539541
}
540542

541543
object TypeAssigner extends TypeAssigner:

compiler/src/dotty/tools/dotc/typer/Typer.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3014,6 +3014,7 @@ class Typer(@constructorOnly nestingLevel: Int = 0) extends Namer
30143014
case tree: untpd.Splice => typedSplice(tree, pt)
30153015
case tree: untpd.MacroTree => report.error("Unexpected macro", tree.srcPos); tpd.nullLiteral // ill-formed code may reach here
30163016
case tree: untpd.Hole => typedHole(tree, pt)
3017+
case tree: untpd.PickledHole => typedPickledHole(tree, pt)
30173018
case _ => typedUnadapted(desugar(tree, pt), pt, locked)
30183019
}
30193020

0 commit comments

Comments
 (0)