Skip to content

Commit 2d185fc

Browse files
Remove tpt from Hole (#17455)
Now the type is kept in the `Hole` node.
2 parents abed6d9 + 2e71268 commit 2d185fc

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
@@ -746,6 +746,19 @@ object Trees {
746746
s"TypeTree${if (hasType) s"[$typeOpt]" else ""}"
747747
}
748748

749+
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
750+
* It is only used when picking quotes (will never be in a TASTy file).
751+
*
752+
* @param isTerm If this hole is a term, otherwise it is a type hole.
753+
* @param idx The index of the hole in it's enclosing level 0 quote.
754+
* @param args The arguments of the splice to compute its content
755+
* @param content Lambda that computes the content of the hole. This tree is empty when in a quote pickle.
756+
*/
757+
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] {
758+
type ThisTree[+T <: Untyped] <: Hole[T]
759+
override def isType: Boolean = !isTerm
760+
}
761+
749762
/** A type tree whose type is inferred. These trees appear in two contexts
750763
* - as an argument of a TypeApply. In that case its type is always a TypeVar
751764
* - as a (result-)type of an inferred ValDef or DefDef.
@@ -1035,20 +1048,6 @@ object Trees {
10351048
def genericEmptyValDef[T <: Untyped]: ValDef[T] = theEmptyValDef.asInstanceOf[ValDef[T]]
10361049
def genericEmptyTree[T <: Untyped]: Thicket[T] = theEmptyTree.asInstanceOf[Thicket[T]]
10371050

1038-
/** Tree that replaces a level 1 splices in pickled (level 0) quotes.
1039-
* It is only used when picking quotes (will never be in a TASTy file).
1040-
*
1041-
* @param isTerm If this hole is a term, otherwise it is a type hole.
1042-
* @param idx The index of the hole in it's enclosing level 0 quote.
1043-
* @param args The arguments of the splice to compute its content
1044-
* @param content Lambda that computes the content of the hole. This tree is empty when in a quote pickle.
1045-
* @param tpt Type of the hole
1046-
*/
1047-
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] {
1048-
type ThisTree[+T <: Untyped] <: Hole[T]
1049-
override def isType: Boolean = !isTerm
1050-
}
1051-
10521051
def flatten[T <: Untyped](trees: List[Tree[T]]): List[Tree[T]] = {
10531052
def recur(buf: ListBuffer[Tree[T]] | Null, remaining: List[Tree[T]]): ListBuffer[Tree[T]] | Null =
10541053
remaining match {
@@ -1406,9 +1405,9 @@ object Trees {
14061405
case tree: Thicket if (trees eq tree.trees) => tree
14071406
case _ => finalize(tree, untpd.Thicket(trees)(sourceFile(tree)))
14081407
}
1409-
def Hole(tree: Tree)(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree, tpt: Tree)(using Context): Hole = tree match {
1408+
def Hole(tree: Tree)(isTerm: Boolean, idx: Int, args: List[Tree], content: Tree)(using Context): Hole = tree match {
14101409
case tree: Hole if isTerm == tree.isTerm && idx == tree.idx && args.eq(tree.args) && content.eq(tree.content) && content.eq(tree.content) => tree
1411-
case _ => finalize(tree, untpd.Hole(isTerm, idx, args, content, tpt)(sourceFile(tree)))
1410+
case _ => finalize(tree, untpd.Hole(isTerm, idx, args, content)(sourceFile(tree)))
14121411
}
14131412

14141413
// Copier methods with default arguments; these demand that the original tree
@@ -1431,8 +1430,8 @@ object Trees {
14311430
TypeDef(tree: Tree)(name, rhs)
14321431
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 =
14331432
Template(tree: Tree)(constr, parents, derived, self, body)
1434-
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 =
1435-
Hole(tree: Tree)(isTerm, idx, args, content, tpt)
1433+
def Hole(tree: Hole)(isTerm: Boolean = tree.isTerm, idx: Int = tree.idx, args: List[Tree] = tree.args, content: Tree = tree.content)(using Context): Hole =
1434+
Hole(tree: Tree)(isTerm, idx, args, content)
14361435

14371436
}
14381437

@@ -1567,8 +1566,8 @@ object Trees {
15671566
cpy.Quote(tree)(transform(body)(using quoteContext), transform(tags))
15681567
case tree @ Splice(expr) =>
15691568
cpy.Splice(tree)(transform(expr)(using spliceContext))
1570-
case tree @ Hole(isTerm, idx, args, content, tpt) =>
1571-
cpy.Hole(tree)(isTerm, idx, transform(args), transform(content), transform(tpt))
1569+
case tree @ Hole(isTerm, idx, args, content) =>
1570+
cpy.Hole(tree)(isTerm, idx, transform(args), transform(content))
15721571
case _ =>
15731572
transformMoreCases(tree)
15741573
}
@@ -1712,8 +1711,8 @@ object Trees {
17121711
this(this(x, body)(using quoteContext), tags)
17131712
case Splice(expr) =>
17141713
this(x, expr)(using spliceContext)
1715-
case Hole(_, _, args, content, tpt) =>
1716-
this(this(this(x, args), content), tpt)
1714+
case Hole(_, _, args, content) =>
1715+
this(this(x, args), content)
17171716
case _ =>
17181717
foldMoreCases(x, tree)
17191718
}

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
@@ -735,12 +735,12 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
735735
case Splice(expr) =>
736736
val spliceTypeText = (keywordStr("[") ~ toTextGlobal(tree.typeOpt) ~ keywordStr("]")).provided(printDebug && tree.typeOpt.exists)
737737
keywordStr("$") ~ spliceTypeText ~ keywordStr("{") ~ toTextGlobal(expr) ~ keywordStr("}")
738-
case Hole(isTerm, idx, args, content, tpt) =>
738+
case Hole(isTerm, idx, args, content) =>
739739
val (prefix, postfix) = if isTerm then ("{{{", "}}}") else ("[[[", "]]]")
740740
val argsText = toTextGlobal(args, ", ")
741741
val contentText = toTextGlobal(content)
742-
val tptText = toTextGlobal(tpt)
743-
prefix ~~ idx.toString ~~ "|" ~~ tptText ~~ "|" ~~ argsText ~~ "|" ~~ contentText ~~ postfix
742+
val tpeText = toTextGlobal(tree.typeOpt)
743+
prefix ~~ idx.toString ~~ "|" ~~ tpeText ~~ "|" ~~ argsText ~~ "|" ~~ contentText ~~ postfix
744744
case CapturesAndResult(refs, parent) =>
745745
changePrec(GlobalPrec)("^{" ~ Text(refs.map(toText), ", ") ~ "}" ~ toText(parent))
746746
case _ =>

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: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import ast.TreeTypeMap
1414
import SymUtils._
1515
import NameKinds._
1616
import dotty.tools.dotc.ast.tpd
17+
import dotty.tools.dotc.ast.untpd
1718
import dotty.tools.dotc.config.ScalaRelease.*
1819

1920
import scala.collection.mutable
@@ -108,12 +109,12 @@ class PickleQuotes extends MacroTransform {
108109
private val contents = List.newBuilder[Tree]
109110
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
110111
tree match
111-
case tree @ Hole(isTerm, _, _, content, _) =>
112+
case tree @ Hole(isTerm, _, _, content) =>
112113
assert(isTerm)
113114
assert(!content.isEmpty)
114115
contents += content
115116
val holeType = getTermHoleType(tree.tpe)
116-
val hole = cpy.Hole(tree)(content = EmptyTree, TypeTree(holeType))
117+
val hole = untpd.cpy.Hole(tree)(content = EmptyTree).withType(holeType)
117118
cpy.Inlined(tree)(EmptyTree, Nil, hole)
118119
case tree: DefTree =>
119120
val newAnnotations = tree.symbol.annotations.mapconserve { annot =>
@@ -197,7 +198,7 @@ class PickleQuotes extends MacroTransform {
197198

198199
private def mkTagSymbolAndAssignType(typeArg: Tree, idx: Int)(using Context): TypeDef = {
199200
val holeType = getTypeHoleType(typeArg.tpe.select(tpnme.Underlying))
200-
val hole = cpy.Hole(typeArg)(isTerm = false, idx, Nil, EmptyTree, TypeTree(holeType))
201+
val hole = untpd.cpy.Hole(typeArg)(isTerm = false, idx, Nil, EmptyTree).withType(holeType)
201202
val local = newSymbol(
202203
owner = ctx.owner,
203204
name = UniqueName.fresh(hole.tpe.dealias.typeSymbol.name.toTypeName),

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ class Splicing extends MacroTransform:
181181
val ddef = DefDef(meth, List(bindings), newTree.tpe, newTree.changeOwner(ctx.owner, meth))
182182
val fnType = defn.FunctionType(bindings.size, isContextual = false).appliedTo(bindingsTypes :+ newTree.tpe)
183183
val closure = Block(ddef :: Nil, Closure(Nil, ref(meth), TypeTree(fnType)))
184-
tpd.Hole(true, holeIdx, refs, closure, TypeTree(tpe))
184+
tpd.Hole(true, holeIdx, refs, closure, tpe)
185185

186186
override def transform(tree: tpd.Tree)(using Context): tpd.Tree =
187187
tree match

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -688,16 +688,19 @@ object TreeChecker {
688688
super.typedSplice(tree, pt)
689689

690690
override def typedHole(tree: untpd.Hole, pt: Type)(using Context): Tree = {
691-
val tree1 @ Hole(isTerm, _, args, content, tpt) = super.typedHole(tree, pt): @unchecked
691+
val tree1 @ Hole(isTerm, idx, args, content) = super.typedHole(tree, pt): @unchecked
692+
693+
assert(idx >= 0, i"hole should not have negative index: $tree")
694+
assert(isTerm || tree.args.isEmpty, i"type hole should not have arguments: $tree")
692695

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

698701
// Check result type of the hole
699-
if isTerm then assert(tpt.typeOpt <:< pt)
700-
else assert(tpt.typeOpt =:= pt)
702+
if isTerm then assert(tree1.typeOpt <:< pt)
703+
else assert(tree1.typeOpt =:= pt)
701704

702705
// Check that the types of the args conform to the types of the contents of the hole
703706
val argQuotedTypes = args.map { arg =>
@@ -712,8 +715,8 @@ object TreeChecker {
712715
else defn.QuotedTypeClass.typeRef.appliedTo(arg.typeOpt.widenTermRefExpr)
713716
}
714717
val expectedResultType =
715-
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tpt.typeOpt)
716-
else defn.QuotedTypeClass.typeRef.appliedTo(tpt.typeOpt)
718+
if isTerm then defn.QuotedExprClass.typeRef.appliedTo(tree1.typeOpt)
719+
else defn.QuotedTypeClass.typeRef.appliedTo(tree1.typeOpt)
717720
val contextualResult =
718721
defn.FunctionOf(List(defn.QuotesClass.typeRef), expectedResultType, isContextual = true)
719722
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+
throw new UnsupportedOperationException("cannot type check a Hole node")
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
@@ -111,6 +111,9 @@ class ReTyper(nestingLevel: Int = 0) extends Typer(nestingLevel) with ReChecking
111111
val expr1 = typed(tree.expr, quoteType)(using spliceContext)
112112
untpd.cpy.Splice(tree)(expr1).withType(tree.typeOpt)
113113

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

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

0 commit comments

Comments
 (0)