Skip to content

Commit 10bbcd0

Browse files
committed
Remove tpt from Hole
Now the type is kept in the `Hole` node.
1 parent 5a9b616 commit 10bbcd0

File tree

12 files changed

+52
-47
lines changed

12 files changed

+52
-47
lines changed

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

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -741,6 +741,19 @@ object Trees {
741741
s"TypeTree${if (hasType) s"[$typeOpt]" else ""}"
742742
}
743743

744+
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
745+
* It is only used when picking quotes (will never be in a TASTy file).
746+
*
747+
* @param isTerm If this hole is a term, otherwise it is a type hole.
748+
* @param idx The index of the hole in it's enclosing level 0 quote.
749+
* @param args The arguments of the splice to compute its content
750+
* @param content Lambda that computes the content of the hole. This tree is empty when in a quote pickle.
751+
*/
752+
case class Hole[+T <: Untyped](override val isTerm: Boolean, idx: Int, args: List[Tree[T]], content: Tree[T])(implicit @constructorOnly src: SourceFile) extends Tree[T] {
753+
type ThisTree[+T <: Untyped] <: Hole[T]
754+
override def isType: Boolean = !isTerm
755+
}
756+
744757
/** A type tree whose type is inferred. These trees appear in two contexts
745758
* - as an argument of a TypeApply. In that case its type is always a TypeVar
746759
* - as a (result-)type of an inferred ValDef or DefDef.
@@ -1030,20 +1043,6 @@ object Trees {
10301043
def genericEmptyValDef[T <: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]]
10311044
def genericEmptyTree[T <: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]]
10321045

1033-
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
1034-
* It is only used when picking quotes (will never be in a TASTy file).
1035-
*
1036-
* @param isTerm If this hole is a term, otherwise it is a type hole.
1037-
* @param idx The index of the hole in it's enclosing level 0 quote.
1038-
* @param args The arguments of the splice to compute its content
1039-
* @param content Lambda that computes the content of the hole. This tree is empty when in a quote pickle.
1040-
* @param tpt Type of the hole
1041-
*/
1042-
case class Hole[+T <: Untyped](override val isTerm: Boolean, idx: Int, args: List[Tree[T]], content: Tree[T], tpt: Tree[T])(implicit @constructorOnly src: SourceFile) extends Tree[T] {
1043-
type ThisTree[+T <: Untyped] <: Hole[T]
1044-
override def isType: Boolean = !isTerm
1045-
}
1046-
10471046
def flatten[T <: Untyped](trees: List[Tree[T]]): List[Tree[T]] = {
10481047
def recur(buf: ListBuffer[Tree[T]] | Null, remaining: List[Tree[T]]): ListBuffer[Tree[T]] | Null =
10491048
remaining match {
@@ -1401,9 +1400,9 @@ object Trees {
14011400
case tree: Thicket if (trees eq tree.trees) => tree
14021401
case _ => finalize(tree, untpd.Thicket(trees)(sourceFile(tree)))
14031402
}
1404-
def Hole(tree: Tree)(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree, tpt: Tree)(using Context): Hole = tree match {
1403+
def Hole(tree: Tree)(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree)(using Context): Hole = tree match {
14051404
case tree: Hole if isTerm == tree.isTerm && idx == tree.idx && args.eq(tree.args) && content.eq(tree.content) && content.eq(tree.content) => tree
1406-
case _ => finalize(tree, untpd.Hole(isTerm, idx, args, content, tpt)(sourceFile(tree)))
1405+
case _ => finalize(tree, untpd.Hole(isTerm, idx, args, content)(sourceFile(tree)))
14071406
}
14081407

14091408
// Copier methods with default arguments; these demand that the original tree
@@ -1426,8 +1425,8 @@ object Trees {
14261425
TypeDef(tree: Tree)(name, rhs)
14271426
def Template(tree: Template)(using Context)(constr: DefDef = tree.constr, parents: List[Tree] = tree.parents, derived: List[untpd.Tree] = tree.derived, self: ValDef = tree.self, body: LazyTreeList = tree.unforcedBody): Template =
14281427
Template(tree: Tree)(constr, parents, derived, self, body)
1429-
def Hole(tree: Hole)(isTerm: Boolean = tree.isTerm, idx: Int = tree.idx, args: List[Tree] = tree.args, content: Tree = tree.content, tpt: Tree = tree.tpt)(using Context): Hole =
1430-
Hole(tree: Tree)(isTerm, idx, args, content, tpt)
1428+
def Hole(tree: Hole)(isTerm: Boolean = tree.isTerm, idx: Int = tree.idx, args: List[Tree] = tree.args, content: Tree = tree.content)(using Context): Hole =
1429+
Hole(tree: Tree)(isTerm, idx, args, content)
14311430

14321431
}
14331432

@@ -1562,8 +1561,8 @@ object Trees {
15621561
cpy.Quote(tree)(transform(body)(using quoteContext))
15631562
case tree @ Splice(expr) =>
15641563
cpy.Splice(tree)(transform(expr)(using spliceContext))
1565-
case tree @ Hole(isTerm, idx, args, content, tpt) =>
1566-
cpy.Hole(tree)(isTerm, idx, transform(args), transform(content), transform(tpt))
1564+
case tree @ Hole(isTerm, idx, args, content) =>
1565+
cpy.Hole(tree)(isTerm, idx, transform(args), transform(content))
15671566
case _ =>
15681567
transformMoreCases(tree)
15691568
}
@@ -1707,8 +1706,8 @@ object Trees {
17071706
this(x, body)(using quoteContext)
17081707
case Splice(expr) =>
17091708
this(x, expr)(using spliceContext)
1710-
case Hole(_, _, args, content, tpt) =>
1711-
this(this(this(x, args), content), tpt)
1709+
case Hole(_, _, args, content) =>
1710+
this(this(x, args), content)
17121711
case _ =>
17131712
foldMoreCases(x, tree)
17141713
}

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
176176
def Splice(expr: Tree, tpe: Type)(using Context): Splice =
177177
untpd.Splice(expr).withType(tpe)
178178

179+
def Hole(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree, tpe: Type)(using Context): Hole =
180+
untpd.Hole(isTerm, idx, args, content).withType(tpe)
181+
179182
def TypeTree(tp: Type, inferred: Boolean = false)(using Context): TypeTree =
180183
(if inferred then untpd.InferredTypeTree() else untpd.TypeTree()).withType(tp)
181184

@@ -397,9 +400,6 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
397400
def Throw(expr: Tree)(using Context): Tree =
398401
ref(defn.throwMethod).appliedTo(expr)
399402

400-
def Hole(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree, tpt: Tree)(using Context): Hole =
401-
ta.assignType(untpd.Hole(isTerm, idx, args, content, tpt), tpt)
402-
403403
// ------ Making references ------------------------------------------------------
404404

405405
def prefixIsElidable(tp: NamedType)(using Context): Boolean = {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -424,7 +424,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
424424
def Export(expr: Tree, selectors: List[ImportSelector])(implicit src: SourceFile): Export = new Export(expr, selectors)
425425
def PackageDef(pid: RefTree, stats: List[Tree])(implicit src: SourceFile): PackageDef = new PackageDef(pid, stats)
426426
def Annotated(arg: Tree, annot: Tree)(implicit src: SourceFile): Annotated = new Annotated(arg, annot)
427-
def Hole(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree, tpt: Tree)(implicit src: SourceFile): Hole = new Hole(isTerm, idx, args, content, tpt)
427+
def Hole(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree)(implicit src: SourceFile): Hole = new Hole(isTerm, idx, args, content)
428428

429429
// ------ Additional creation methods for untyped only -----------------
430430

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -685,11 +685,11 @@ class TreePickler(pickler: TastyPickler) {
685685
.appliedTo(expr)
686686
.withSpan(tree.span)
687687
)
688-
case Hole(_, idx, args, _, tpt) =>
688+
case Hole(_, idx, args, _) =>
689689
writeByte(HOLE)
690690
withLength {
691691
writeNat(idx)
692-
pickleType(tpt.tpe, richTypes = true)
692+
pickleType(tree.tpe, richTypes = true)
693693
args.foreach(pickleTree)
694694
}
695695
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1457,7 +1457,7 @@ class TreeUnpickler(reader: TastyReader,
14571457
val idx = readNat()
14581458
val tpe = readType()
14591459
val args = until(end)(readTree())
1460-
Hole(true, idx, args, EmptyTree, TypeTree(tpe)).withType(tpe)
1460+
Hole(true, idx, args, EmptyTree, tpe)
14611461
case _ =>
14621462
readPathTree()
14631463
}
@@ -1491,7 +1491,7 @@ class TreeUnpickler(reader: TastyReader,
14911491
val idx = readNat()
14921492
val tpe = readType()
14931493
val args = until(end)(readTree())
1494-
Hole(false, idx, args, EmptyTree, TypeTree(tpe)).withType(tpe)
1494+
Hole(false, idx, args, EmptyTree, tpe)
14951495
case _ =>
14961496
if (isTypeTreeTag(nextByte)) readTree()
14971497
else {

compiler/src/dotty/tools/dotc/printing/RefinedPrinter.scala

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -724,12 +724,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
724724
case Splice(expr) =>
725725
val spliceTypeText = (keywordStr("[") ~ toTextGlobal(tree.typeOpt) ~ keywordStr("]")).provided(printDebug && tree.typeOpt.exists)
726726
keywordStr("$") ~ spliceTypeText ~ keywordStr("{") ~ toTextGlobal(expr) ~ keywordStr("}")
727-
case Hole(isTerm, idx, args, content, tpt) =>
727+
case Hole(isTerm, idx, args, content) =>
728728
val (prefix, postfix) = if isTerm then ("{{{", "}}}") else ("[[[", "]]]")
729729
val argsText = toTextGlobal(args, ", ")
730730
val contentText = toTextGlobal(content)
731-
val tptText = toTextGlobal(tpt)
732-
prefix ~~ idx.toString ~~ "|" ~~ tptText ~~ "|" ~~ argsText ~~ "|" ~~ contentText ~~ postfix
731+
val tpeText = toTextGlobal(tree.typeOpt)
732+
prefix ~~ idx.toString ~~ "|" ~~ tpeText ~~ "|" ~~ argsText ~~ "|" ~~ contentText ~~ postfix
733733
case CapturingTypeTree(refs, parent) =>
734734
parent match
735735
case ImpureByNameTypeTree(bntpt) =>

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ 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(isTerm, idx, args, _, _) =>
103+
case Hole(isTerm, idx, args, _) =>
104104
inContext(SpliceScope.contextWithNewSpliceScope(tree.sourcePos)) {
105105
if isTerm then
106106
val quotedExpr = termHole match
@@ -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, args, _, _), _) =>
168+
case TypeBoundsTree(_, Hole(_, idx, args, _), _) =>
169169
// To keep for backwards compatibility. In some older version holes where created in the bounds.
170170
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 Hole(_, idx, _, _) = tdef.rhs: @unchecked
177177
PickledQuotes.quotedTypeToTree(types.nn.apply(idx))
178178
(tdef.symbol, tree.tpe)
179179
}.toMap

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import ast.TreeTypeMap
1313
import SymUtils._
1414
import NameKinds._
1515
import dotty.tools.dotc.ast.tpd
16+
import dotty.tools.dotc.ast.untpd
1617
import dotty.tools.dotc.config.ScalaRelease.*
1718

1819
import scala.collection.mutable
@@ -113,12 +114,12 @@ class PickleQuotes extends MacroTransform {
113114
private val contents = List.newBuilder[Tree]
114115
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
115116
tree match
116-
case tree @ Hole(isTerm, _, _, content, _) =>
117+
case tree @ Hole(isTerm, _, _, content) =>
117118
if !content.isEmpty then
118119
contents += content
119120
val holeType =
120121
if isTerm then getTermHoleType(tree.tpe) else getTypeHoleType(tree.tpe)
121-
val hole = cpy.Hole(tree)(content = EmptyTree, TypeTree(holeType))
122+
val hole = untpd.cpy.Hole(tree)(content = EmptyTree).withType(holeType)
122123
if isTerm then Inlined(EmptyTree, Nil, hole).withSpan(tree.span) else hole
123124
case tree: DefTree =>
124125
val newAnnotations = tree.symbol.annotations.mapconserve { annot =>

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ class Splicing extends MacroTransform:
124124
case None =>
125125
val holeIdx = numHoles
126126
numHoles += 1
127-
val hole = tpd.Hole(false, holeIdx, Nil, ref(qual), TypeTree(tp))
127+
val hole = tpd.Hole(false, holeIdx, Nil, ref(qual), tp)
128128
typeHoles.put(qual, hole)
129129
hole
130130
cpy.TypeDef(tree)(rhs = hole)
@@ -192,7 +192,7 @@ class Splicing extends MacroTransform:
192192
val ddef = DefDef(meth, List(bindings), newTree.tpe, newTree.changeOwner(ctx.owner, meth))
193193
val fnType = defn.FunctionType(bindings.size, isContextual = false).appliedTo(bindingsTypes :+ newTree.tpe)
194194
val closure = Block(ddef :: Nil, Closure(Nil, ref(meth), TypeTree(fnType)))
195-
tpd.Hole(true, holeIdx, refs, closure, TypeTree(tpe))
195+
tpd.Hole(true, holeIdx, refs, closure, tpe)
196196

197197
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
198198
tree match

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -658,16 +658,19 @@ object TreeChecker {
658658
super.typedPackageDef(tree)
659659

660660
override def typedHole(tree: untpd.Hole, pt: Type)(using Context): Tree = {
661-
val tree1 @ Hole(isTerm, _, args, content, tpt) = super.typedHole(tree, pt): @unchecked
661+
val tree1 @ Hole(isTerm, idx, args, content) = super.typedHole(tree, pt): @unchecked
662+
663+
assert(idx >= 0, i"hole should not have negative index: $tree")
664+
assert(isTerm || tree.args.isEmpty, i"type hole should not have arguments: $tree")
662665

663666
// Check that we only add the captured type `T` instead of a more complex type like `List[T]`.
664667
// If we have `F[T]` with captured `F` and `T`, we should list `F` and `T` separately in the args.
665668
for arg <- args do
666669
assert(arg.isTerm || arg.tpe.isInstanceOf[TypeRef], "Expected TypeRef in Hole type args but got: " + arg.tpe)
667670

668671
// Check result type of the hole
669-
if isTerm then assert(tpt.typeOpt <:< pt)
670-
else assert(tpt.typeOpt =:= pt)
672+
if isTerm then assert(tree1.typeOpt <:< pt)
673+
else assert(tree1.typeOpt =:= pt)
671674

672675
// Check that the types of the args conform to the types of the contents of the hole
673676
val argQuotedTypes = args.map { arg =>
@@ -682,8 +685,8 @@ object TreeChecker {
682685
else defn.QuotedTypeClass.typeRef.appliedTo(arg.typeOpt.widenTermRefExpr)
683686
}
684687
val expectedResultType =
685-
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tpt.typeOpt)
686-
else defn.QuotedTypeClass.typeRef.appliedTo(tpt.typeOpt)
688+
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tree1.typeOpt)
689+
else defn.QuotedTypeClass.typeRef.appliedTo(tree1.typeOpt)
687690
val contextualResult =
688691
defn.FunctionOf(List(defn.QuotesClass.typeRef), expectedResultType, isContextual = true)
689692
val expectedContentType =

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ trait QuotesAndSplices {
116116
}
117117

118118
def typedHole(tree: untpd.Hole, pt: Type)(using Context): Tree =
119-
val tpt = typedType(tree.tpt)
120-
assignType(tree, tpt)
119+
assert(false, "Holes should only be typed by the ReTyper")
121120

122121
/** Types a splice applied to some arguments `$f(arg1, ..., argn)` in a quote pattern.
123122
*

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
110110
val expr1 = typed(tree.expr, quoteType)(using spliceContext)
111111
untpd.cpy.Splice(tree)(expr1).withType(tree.typeOpt)
112112

113+
override def typedHole(tree: untpd.Hole, pt: Type)(using Context): Tree =
114+
promote(tree)
115+
113116
override def localDummy(cls: ClassSymbol, impl: untpd.Template)(using Context): Symbol = impl.symbol
114117

115118
override def retrieveSym(tree: untpd.Tree)(using Context): Symbol = tree.symbol

0 commit comments

Comments
 (0)