From 68343c1223dbe4f2771d0f1def71be12034fbcf3 Mon Sep 17 00:00:00 2001 From: Nicolas Stucki Date: Tue, 11 Apr 2023 09:47:12 +0200 Subject: [PATCH] Add new HOLETYPES to TASTy format This is a new encoding of HOLE that differentiates between type and term arguments of the hole. ``` HOLE Length idx_Nat tpe_Type (HOLETYPES Length targ_Type*)? arg_Tree* -- Splice hole with index `idx`, the type of the hole `tpe`, type arguments of the hole `targ`s and term arguments of the hole `arg`s ``` --- .../tools/dotc/core/tasty/TreePickler.scala | 6 ++++- .../tools/dotc/core/tasty/TreeUnpickler.scala | 22 ++++++++++++------- tasty/src/dotty/tools/tasty/TastyFormat.scala | 8 +++++-- 3 files changed, 25 insertions(+), 11 deletions(-) diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala index b73e37c3b8c5..311af25379d2 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -670,7 +670,11 @@ class TreePickler(pickler: TastyPickler) { withLength { writeNat(idx) pickleType(tpt.tpe, richTypes = true) - targs.foreach(pickleTree) + if targs.nonEmpty then + writeByte(HOLETYPES) + withLength { + targs.foreach(targ => pickleType(targ.tpe)) + } args.foreach(pickleTree) } } diff --git a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala index 95b94c9342c3..320c0da8e359 100644 --- a/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala @@ -1436,10 +1436,7 @@ class TreeUnpickler(reader: TastyReader, val alias = if currentAddr == end then EmptyTree else readTpt() createNullableTypeBoundsTree(lo, hi, alias) case HOLE => - val idx = readNat() - val tpe = readType() - val args = until(end)(readTerm()) - TastyQuoteHole(true, idx, args, TypeTree(tpe)).withType(tpe) + readHole(end, isTerm = true) case _ => readPathTerm() } @@ -1470,10 +1467,7 @@ class TreeUnpickler(reader: TastyReader, case HOLE => readByte() val end = readEnd() - val idx = readNat() - val tpe = readType() - val args = until(end)(readTerm()) - TastyQuoteHole(false, idx, args, TypeTree(tpe)).withType(tpe) + readHole(end, isTerm = false) case _ => if (isTypeTreeTag(nextByte)) readTerm() else { @@ -1506,6 +1500,18 @@ class TreeUnpickler(reader: TastyReader, setSpan(start, CaseDef(pat, guard, rhs)) } + def readHole(end: Addr, isTerm: Boolean)(using Context): Tree = + val idx = readNat() + val tpe = readType() + val targs = + if nextByte == HOLETYPES then + readByte() + val typesEnd = readEnd() + until(typesEnd)(readType()).map(TypeTree(_)) + else Nil + val args = until(end)(readTerm()) + TastyQuoteHole(true, idx, targs ::: args, TypeTree(tpe)).withType(tpe) + def readLater[T <: AnyRef](end: Addr, op: TreeReader => Context ?=> T)(using Context): Trees.Lazy[T] = readLaterWithOwner(end, op)(ctx.owner) diff --git a/tasty/src/dotty/tools/tasty/TastyFormat.scala b/tasty/src/dotty/tools/tasty/TastyFormat.scala index 226fc14acb39..fcf6932abafa 100644 --- a/tasty/src/dotty/tools/tasty/TastyFormat.scala +++ b/tasty/src/dotty/tools/tasty/TastyFormat.scala @@ -122,8 +122,9 @@ Standard-Section: "ASTs" TopLevelStat* MATCHtpt Length bound_Term? sel_Term CaseDef* -- sel match { CaseDef } where `bound` is optional upper bound of all rhs BYNAMEtpt underlying_Term -- => underlying SHAREDterm term_ASTRef -- Link to previously serialized term - HOLE Length idx_Nat tpe_Type arg_Tree* -- Splice hole with index `idx`, the type of the hole `tpe`, type and term arguments of the hole `arg`s - + HOLE Length idx_Nat tpe_Type (HOLETYPES Length targ_Type*)? arg_Tree* + -- Splice hole with index `idx`, the type of the hole `tpe`, type arguments of the hole `targ`s and term arguments of the hole `arg`s + -- Note: From 3.0 to 3.3 `args` could contain type arguments as well. This is no longer the case. CaseDef = CASEDEF Length pat_Term rhs_Tree guard_Tree? -- case pat if guard => rhs ImplicitArg = IMPLICITARG arg_Term -- implicit unapply argument @@ -586,6 +587,7 @@ object TastyFormat { final val MATCHtpt = 191 final val MATCHCASEtype = 192 + final val HOLETYPES = 254 final val HOLE = 255 final val firstNatTreeTag = SHAREDterm @@ -600,6 +602,7 @@ object TastyFormat { firstASTTreeTag <= tag && tag <= BOUNDED || firstNatASTTreeTag <= tag && tag <= NAMEDARG || firstLengthTreeTag <= tag && tag <= MATCHtpt || + tag == HOLETYPES || tag == HOLE def isParamTag(tag: Int): Boolean = tag == PARAM || tag == TYPEPARAM @@ -804,6 +807,7 @@ object TastyFormat { case PRIVATEqualified => "PRIVATEqualified" case PROTECTEDqualified => "PROTECTEDqualified" case HOLE => "HOLE" + case HOLETYPES => "HOLETYPES" } /** @return If non-negative, the number of leading references (represented as nats) of a length/trees entry.