Skip to content

Commit 0acaa36

Browse files
committed
Switch to AssumeInfo
1 parent ec5a86c commit 0acaa36

31 files changed

+221
-188
lines changed

compiler/src/dotty/tools/backend/jvm/BCodeBodyBuilder.scala

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -441,10 +441,6 @@ trait BCodeBodyBuilder extends BCodeSkelBuilder {
441441
genBlockTo(blck, expectedType, dest)
442442
generatedDest = dest
443443

444-
case GadtExpr(_, expr) =>
445-
genLoadTo(expr, expectedType, dest)
446-
generatedDest = dest
447-
448444
case Typed(Super(_, _), _) =>
449445
genLoadTo(tpd.This(claszSymbol.asClass), expectedType, dest)
450446
generatedDest = dest

compiler/src/dotty/tools/backend/sjs/JSCodeGen.scala

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1851,9 +1851,6 @@ class JSCodeGen()(using genCtx: Context) {
18511851
}
18521852
js.Block(genStatsAndExpr)
18531853

1854-
case GadtExpr(_, expr) =>
1855-
genStatOrExpr(expr, isStat)
1856-
18571854
case Typed(expr, _) =>
18581855
expr match {
18591856
case _: Super => genThis()

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,8 +336,8 @@ object desugar {
336336
// Propagate down the expected type to the leafs of the expression
337337
case Block(stats, expr) =>
338338
cpy.Block(tree)(stats, adaptToExpectedTpt(expr))
339-
case GadtExpr(gadt, expr) =>
340-
cpy.GadtExpr(tree)(gadt, adaptToExpectedTpt(expr))
339+
case AssumeInfo(sym, nestingLevel, info, body) =>
340+
cpy.AssumeInfo(tree)(sym, nestingLevel, info, adaptToExpectedTpt(body))
341341
case If(cond, thenp, elsep) =>
342342
cpy.If(tree)(cond, adaptToExpectedTpt(thenp), adaptToExpectedTpt(elsep))
343343
case untpd.Parens(expr) =>
@@ -1632,7 +1632,7 @@ object desugar {
16321632
case Tuple(trees) => (pats corresponds trees)(isIrrefutable)
16331633
case Parens(rhs1) => matchesTuple(pats, rhs1)
16341634
case Block(_, rhs1) => matchesTuple(pats, rhs1)
1635-
case GadtExpr(_, rhs1) => matchesTuple(pats, rhs1)
1635+
case AssumeInfo(_, _, _, rhs1) => matchesTuple(pats, rhs1)
16361636
case If(_, thenp, elsep) => matchesTuple(pats, thenp) && matchesTuple(pats, elsep)
16371637
case Match(_, cases) => cases forall (matchesTuple(pats, _))
16381638
case CaseDef(_, _, rhs1) => matchesTuple(pats, rhs1)

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
309309
case If(_, thenp, elsep) => forallResults(thenp, p) && forallResults(elsep, p)
310310
case Match(_, cases) => cases forall (c => forallResults(c.body, p))
311311
case Block(_, expr) => forallResults(expr, p)
312-
case GadtExpr(_, expr) => forallResults(expr, p)
312+
case AssumeInfo(_, _, _, body) => forallResults(body, p)
313313
case _ => p(tree)
314314
}
315315
}
@@ -1040,7 +1040,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
10401040
case Typed(expr, _) => unapply(expr)
10411041
case Inlined(_, Nil, expr) => unapply(expr)
10421042
case Block(Nil, expr) => unapply(expr)
1043-
case GadtExpr(_, expr) => unapply(expr)
1043+
case AssumeInfo(_, _, _, body) => unapply(body)
10441044
case _ =>
10451045
tree.tpe.widenTermRefExpr.normalized match
10461046
case ConstantType(Constant(x)) => Some(x)

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

Lines changed: 14 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -123,17 +123,20 @@ class TreeTypeMap(
123123
cpy.Block(blk)(stats1, expr1)
124124
case inlined: Inlined =>
125125
transformInlined(inlined)
126-
case GadtExpr(gadt, expr) =>
127-
cpy.GadtExpr(expr)(gadt, transform(expr))
128-
case cdef @ CaseDef(pat, guard, expr @ GadtExpr(gadt, rhs)) =>
129-
val patVars1 = patVars(pat)
130-
val tmap = withMappedSyms(patVars1 ::: gadt.symbols.diff(substFrom).diff(patVars1))
131-
val gadt1 = tmap.rebuild(gadt)
132-
inContext(ctx.withGadt(gadt1)) {
133-
val pat1 = tmap.transform(pat)
134-
val guard1 = tmap.transform(guard)
135-
val rhs1 = cpy.GadtExpr(expr)(gadt1, tmap.transform(rhs))
136-
cpy.CaseDef(cdef)(pat1, guard1, rhs1)
126+
case tree1: AssumeInfo =>
127+
def mapBody(body: Tree) = body match
128+
case tree @ AssumeInfo(_, _, _, _) =>
129+
val tree1 = treeMap(tree)
130+
tree1.withType(mapType(tree1.tpe))
131+
case _ => body
132+
ctx.gadt.withAssumeInfosIn(tree1, mapBody)(transform) { (assumeInfo, body) =>
133+
val AssumeInfo(sym, _, info, _) = assumeInfo
134+
mapType(sym.typeRef) match
135+
case tp: TypeRef if tp eq sym.typeRef =>
136+
val sym1 = sym.subst(substFrom, substTo)
137+
val info1 = mapType(info)
138+
cpy.AssumeInfo(assumeInfo)(sym = sym1, info = info1, body = body)
139+
case _ => body // if the AssumeInfo symbol maps (as a type) to another type, we lose the associated info
137140
}
138141
case cdef @ CaseDef(pat, guard, rhs) =>
139142
val tmap = withMappedSyms(patVars(pat))
@@ -158,29 +161,6 @@ class TreeTypeMap(
158161
}
159162
}
160163

161-
private def rebuild(gadt: GadtConstraint)(using Context): GadtConstraint =
162-
val constraints = for sym <- gadt.symbols yield
163-
val TypeBounds(lo, hi) = gadt.fullBounds(sym).nn
164-
(sym, lo, hi)
165-
val constraints1 = constraints.mapConserve { triple =>
166-
val (sym, lo, hi) = triple
167-
val sym1 = mapOwner(sym)
168-
val lo1 = mapType(lo)
169-
val hi1 = mapType(hi)
170-
if (sym eq sym1) && (lo eq lo1) && (hi eq hi1)
171-
then triple
172-
else (sym1, lo1, hi1)
173-
}
174-
if constraints eq constraints1 then
175-
gadt
176-
else
177-
val gadt = EmptyGadtConstraint.fresh
178-
for (sym, lo, hi) <- constraints1 do
179-
gadt.addToConstraint(sym)
180-
gadt.addBound(sym, lo, false)
181-
gadt.addBound(sym, hi, true)
182-
gadt
183-
184164
override def transformStats(trees: List[tpd.Tree], exprOwner: Symbol)(using Context): List[Tree] =
185165
transformDefs(trees)._2
186166

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

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -569,10 +569,19 @@ object Trees {
569569
override def isTerm: Boolean = !isType // this will classify empty trees as terms, which is necessary
570570
}
571571

572-
case class GadtExpr[-T >: Untyped] private[ast] (gadt: GadtConstraint, expr: Tree[T])(implicit @constructorOnly src: SourceFile)
572+
case class AssumeInfo[-T >: Untyped] private[ast] (sym: Symbol, nestingLevel: Int, info: Type, body: Tree[T])(implicit @constructorOnly src: SourceFile)
573573
extends ProxyTree[T] {
574-
type ThisTree[-T >: Untyped] <: GadtExpr[T]
575-
def forwardTo: Tree[T] = expr
574+
type ThisTree[-T >: Untyped] <: AssumeInfo[T]
575+
def forwardTo: Tree[T] = body
576+
577+
/** Un-nests AssumeInfo trees, returning them in a list, along with the last non-AssumeInfo body.
578+
* On each recursion, the body is first mapped with `mapBody`. */
579+
def unnest[U <: T](mapBody: Tree[U] => Tree[U] = (body: Tree[U]) => body): (List[AssumeInfo[U]], Tree[U]) =
580+
val acc = scala.collection.mutable.ListBuffer.empty[AssumeInfo[U]]
581+
def rec(tree: Tree[U]): (List[AssumeInfo[U]], Tree[U]) = tree match
582+
case tree @ AssumeInfo(_, _, _, body) => acc += tree; rec(mapBody(body))
583+
case _ => (acc.toList, tree)
584+
rec(this)
576585
}
577586

578587
/** if cond then thenp else elsep */
@@ -1077,7 +1086,7 @@ object Trees {
10771086
type NamedArg = Trees.NamedArg[T]
10781087
type Assign = Trees.Assign[T]
10791088
type Block = Trees.Block[T]
1080-
type GadtExpr = Trees.GadtExpr[T]
1089+
type AssumeInfo = Trees.AssumeInfo[T]
10811090
type If = Trees.If[T]
10821091
type InlineIf = Trees.InlineIf[T]
10831092
type Closure = Trees.Closure[T]
@@ -1216,9 +1225,9 @@ object Trees {
12161225
case tree: Block if (stats eq tree.stats) && (expr eq tree.expr) => tree
12171226
case _ => finalize(tree, untpd.Block(stats, expr)(sourceFile(tree)))
12181227
}
1219-
def GadtExpr(tree: Tree)(gadt: GadtConstraint, expr: Tree)(using Context): GadtExpr = tree match
1220-
case tree: GadtExpr if (gadt eq tree.gadt) && (expr eq tree.expr) => tree
1221-
case _ => finalize(tree, untpd.GadtExpr(gadt, expr)(sourceFile(tree)))
1228+
def AssumeInfo(tree: Tree)(sym: Symbol, nestingLevel: Int, info: Type, body: Tree)(using Context): AssumeInfo = tree match
1229+
case tree: AssumeInfo if (sym eq tree.sym) && (info eq tree.info) && (body eq tree.body) && (nestingLevel == tree.nestingLevel) => tree
1230+
case _ => finalize(tree, untpd.AssumeInfo(sym, nestingLevel, info, body)(sourceFile(tree)))
12221231
def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(using Context): If = tree match {
12231232
case tree: If if (cond eq tree.cond) && (thenp eq tree.thenp) && (elsep eq tree.elsep) => tree
12241233
case tree: InlineIf => finalize(tree, untpd.InlineIf(cond, thenp, elsep)(sourceFile(tree)))
@@ -1351,6 +1360,8 @@ object Trees {
13511360

13521361
// Copier methods with default arguments; these demand that the original tree
13531362
// is of the same class as the copy. We only include trees with more than 2 elements here.
1363+
def AssumeInfo(tree: AssumeInfo)(sym: Symbol = tree.sym, nestingLevel: Int = tree.nestingLevel, info: Type = tree.info, body: Tree = tree.body)(using Context): AssumeInfo =
1364+
AssumeInfo(tree: Tree)(sym, nestingLevel, info, body)
13541365
def If(tree: If)(cond: Tree = tree.cond, thenp: Tree = tree.thenp, elsep: Tree = tree.elsep)(using Context): If =
13551366
If(tree: Tree)(cond, thenp, elsep)
13561367
def Closure(tree: Closure)(env: List[Tree] = tree.env, meth: Tree = tree.meth, tpt: Tree = tree.tpt)(using Context): Closure =
@@ -1440,8 +1451,10 @@ object Trees {
14401451
cpy.Closure(tree)(transform(env), transform(meth), transform(tpt))
14411452
case Match(selector, cases) =>
14421453
cpy.Match(tree)(transform(selector), transformSub(cases))
1443-
case GadtExpr(gadt, expr) =>
1444-
inContext(ctx.withGadt(gadt))(cpy.GadtExpr(tree)(gadt, transform(expr)))
1454+
case tree @ AssumeInfo(sym, nestingLevel, info, body) =>
1455+
ctx.gadt.withAssumeInfosIn(tree)(transform) { (assumeInfo, body) =>
1456+
cpy.AssumeInfo(assumeInfo)(body = body)
1457+
}
14451458
case CaseDef(pat, guard, body) =>
14461459
cpy.CaseDef(tree)(transform(pat), transform(guard), transform(body))
14471460
case Labeled(bind, expr) =>
@@ -1578,8 +1591,8 @@ object Trees {
15781591
this(this(this(x, env), meth), tpt)
15791592
case Match(selector, cases) =>
15801593
this(this(x, selector), cases)
1581-
case GadtExpr(gadt, expr) =>
1582-
inContext(ctx.withGadt(gadt))(this(x, expr))
1594+
case tree @ AssumeInfo(sym, _, info, body) =>
1595+
ctx.gadt.withAssumeInfosIn(tree)(this(x, _))((_, x) => x)
15831596
case CaseDef(pat, guard, body) =>
15841597
this(this(this(x, pat), guard), body)
15851598
case Labeled(bind, expr) =>

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

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
9292
Block(stats, expr)
9393
}
9494

95-
def GadtExpr(gadt: GadtConstraint, expr: Tree)(using Context): GadtExpr =
96-
ta.assignType(untpd.GadtExpr(gadt, expr), gadt, expr)
95+
def AssumeInfo(sym: Symbol, nestingLevel: Int, info: Type, body: Tree)(using Context): AssumeInfo =
96+
ta.assignType(untpd.AssumeInfo(sym, nestingLevel, info, body), body)
9797

9898
def If(cond: Tree, thenp: Tree, elsep: Tree)(using Context): If =
9999
ta.assignType(untpd.If(cond, thenp, elsep), thenp, elsep)
@@ -676,11 +676,11 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
676676
}
677677
}
678678

679-
override def GadtExpr(tree: Tree)(gadt: GadtConstraint, expr: Tree)(using Context): GadtExpr =
680-
val tree1 = untpdCpy.GadtExpr(tree)(gadt, expr)
679+
override def AssumeInfo(tree: Tree)(sym: Symbol, nestingLevel: Int, info: Type, body: Tree)(using Context): AssumeInfo =
680+
val tree1 = untpdCpy.AssumeInfo(tree)(sym, nestingLevel, info, body)
681681
tree match
682-
case tree: GadtExpr if expr.tpe eq tree.expr.tpe => tree1.withTypeUnchecked(tree.tpe)
683-
case _ => ta.assignType(tree1, gadt, expr)
682+
case tree: AssumeInfo if body.tpe eq tree.body.tpe => tree1.withTypeUnchecked(tree.tpe)
683+
case _ => ta.assignType(tree1, body)
684684

685685
override def If(tree: Tree)(cond: Tree, thenp: Tree, elsep: Tree)(using Context): If = {
686686
val tree1 = untpdCpy.If(tree)(cond, thenp, elsep)
@@ -766,6 +766,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
766766
}
767767
}
768768

769+
override def AssumeInfo(tree: AssumeInfo)(sym: Symbol = tree.sym, nestingLevel: Int = tree.nestingLevel, info: Type = tree.info, body: Tree = tree.body)(using Context): AssumeInfo =
770+
AssumeInfo(tree: Tree)(sym, nestingLevel, info, body)
769771
override def If(tree: If)(cond: Tree = tree.cond, thenp: Tree = tree.thenp, elsep: Tree = tree.elsep)(using Context): If =
770772
If(tree: Tree)(cond, thenp, elsep)
771773
override def Closure(tree: Closure)(env: List[Tree] = tree.env, meth: Tree = tree.meth, tpt: Tree = tree.tpt)(using Context): Closure =
@@ -1305,7 +1307,7 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
13051307
else if (tree.tpe.widen isRef numericCls)
13061308
tree
13071309
else {
1308-
report.warning(i"conversion from ${tree.tpe.widen} to ${numericCls.typeRef} will always fail at runtime.", tree.srcPos)
1310+
report.warning(i"conversion from ${tree.tpe.widen} to ${numericCls.typeRef} will always fail at runtime.")
13091311
Throw(New(defn.ClassCastExceptionClass.typeRef, Nil)).withSpan(tree.span)
13101312
}
13111313
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
382382
def NamedArg(name: Name, arg: Tree)(implicit src: SourceFile): NamedArg = new NamedArg(name, arg)
383383
def Assign(lhs: Tree, rhs: Tree)(implicit src: SourceFile): Assign = new Assign(lhs, rhs)
384384
def Block(stats: List[Tree], expr: Tree)(implicit src: SourceFile): Block = new Block(stats, expr)
385-
def GadtExpr(gadt: GadtConstraint, expr: Tree)(implicit src: SourceFile): GadtExpr = new GadtExpr(gadt, expr)
385+
def AssumeInfo(sym: Symbol, nestingLevel: Int, info: Type, body: Tree)(implicit src: SourceFile): AssumeInfo = new AssumeInfo(sym, nestingLevel, info, body)
386386
def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceFile): If = new If(cond, thenp, elsep)
387387
def InlineIf(cond: Tree, thenp: Tree, elsep: Tree)(implicit src: SourceFile): If = new InlineIf(cond, thenp, elsep)
388388
def Closure(env: List[Tree], meth: Tree, tpt: Tree)(implicit src: SourceFile): Closure = new Closure(env, meth, tpt)

compiler/src/dotty/tools/dotc/core/GadtConstraint.scala

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import Decorators._
66
import Contexts._
77
import Types._
88
import Symbols._
9+
import ast.*, Trees.*
910
import util.{SimpleIdentitySet, SimpleIdentityMap}
1011
import collection.mutable
1112
import printing._
@@ -38,6 +39,38 @@ sealed abstract class GadtConstraint extends Showable {
3839
/** Further constrain a symbol already present in the constraint. */
3940
def addBound(sym: Symbol, bound: Type, isUpper: Boolean)(using Context): Boolean
4041

42+
/** Rebuild and return a GadtConstraint using the given AssumeInfo trees. */
43+
def withAssumeInfos[T >: Untyped](assumeInfos: List[AssumeInfo[T]])(using Context): GadtConstraint =
44+
val assumeInfos1 = assumeInfos.filterConserve(t => isBounds(t.info))
45+
if assumeInfos1.isEmpty then this
46+
else
47+
val gadt = fresh
48+
49+
for case AssumeInfo(sym, nestingLevel, _, _) <- assumeInfos1 do
50+
gadt.addToConstraint(List(sym), nestingLevel)
51+
52+
for case AssumeInfo(sym, _, TypeBounds(lo, hi), _) <- assumeInfos1 do
53+
if (sym.typeRef <:< lo)(using ctx.withGadt(gadt)) then
54+
// add in reverse order so that unification runs in the right direction (keep sym)
55+
// for a counter-example: say the symbol is c: b and the bound is b
56+
// if we add c >: b it will unify to b: c not c: b
57+
gadt.addBound(sym, hi, isUpper = true)
58+
gadt.addBound(sym, lo, isUpper = false)
59+
else
60+
gadt.addBound(sym, lo, isUpper = false)
61+
gadt.addBound(sym, hi, isUpper = true)
62+
gadt
63+
64+
/** Un-nest AssumeInfo trees, build a GadtConstraint, and fold everything, starting from the last body.
65+
* Reuses `AssumeInfo#unnest` and `withAssumeInfos`. */
66+
def withAssumeInfosIn[T >: Untyped <: Type, A](
67+
tree: AssumeInfo[T], mapBody: Tree[T] => Tree[T] = (body: Tree[T]) => body,
68+
)(start: Context ?=> Tree[T] => A)(combine: Context ?=> (AssumeInfo[T], A) => A)(using Context): A =
69+
val (assumeInfos, body) = tree.unnest(mapBody)
70+
inContext(ctx.withGadt(withAssumeInfos(assumeInfos))) {
71+
assumeInfos.foldRight(start(body))(combine)
72+
}
73+
4174
/** Is the symbol registered in the constraint?
4275
*
4376
* @note this is true even if the symbol is constrained to be equal to another type, unlike [[Constraint.contains]].
@@ -51,7 +84,7 @@ sealed abstract class GadtConstraint extends Showable {
5184
def approximation(sym: Symbol, fromBelow: Boolean, maxLevel: Int = Int.MaxValue)(using Context): Type
5285

5386
def symbols: List[Symbol]
54-
def inputs: List[(List[Symbol], Int)]
87+
def inputs: List[(Symbol, Int)]
5588

5689
def fresh: GadtConstraint
5790

@@ -225,12 +258,7 @@ final class ProperGadtConstraint private(
225258
}
226259

227260
override def symbols: List[Symbol] = mapping.keys
228-
229-
override def inputs: List[(List[Symbol], Int)] =
230-
constraint.domainLambdas.flatMap { tl =>
231-
val syms = tl.paramRefs.flatMap(reverseMapping(_).toOption)
232-
syms.headOption.map(sym1 => (syms, mapping(sym1).nn.initNestingLevel))
233-
}
261+
override def inputs: List[(Symbol, Int)] = mapping.map2((sym, tvar) => (sym, tvar.initNestingLevel))
234262

235263
override def fresh: GadtConstraint = new ProperGadtConstraint(
236264
myConstraint,
@@ -331,7 +359,7 @@ final class ProperGadtConstraint private(
331359
override def approximation(sym: Symbol, fromBelow: Boolean, maxLevel: Int)(using Context): Type = unsupported("EmptyGadtConstraint.approximation")
332360

333361
override def symbols: List[Symbol] = Nil
334-
override def inputs: List[(List[Symbol], Int)] = Nil
362+
override def inputs: List[(Symbol, Int)] = Nil
335363

336364
override def fresh = new ProperGadtConstraint
337365
override def restore(other: GadtConstraint): Unit =

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,8 @@ class TastyPrinter(bytes: Array[Byte]) {
140140
printTrees()
141141
case PARAMtype =>
142142
printNat(); printNat()
143-
case CONSTRAINT =>
144-
printInt(); until(end) { printNat(); printTree(); printTree() }
143+
case ASSUMEINFO =>
144+
until(end) { printNat(); printTree(); printInt(); printTree() }
145145
case _ =>
146146
printTrees()
147147
}

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

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -472,20 +472,13 @@ class TreePickler(pickler: TastyPickler) {
472472
writeByte(BLOCK)
473473
stats.foreach(preRegister)
474474
withLength { pickleTree(expr); stats.foreach(pickleTree) }
475-
case GadtExpr(gadt, expr) =>
476-
writeByte(GADTEXPR)
475+
case AssumeInfo(sym, nestingLevel, info, body) =>
476+
writeByte(ASSUMEINFO)
477477
withLength {
478-
for (symbols, nestingLevel) <- gadt.inputs do
479-
writeByte(CONSTRAINT)
480-
withLength {
481-
writeInt(nestingLevel)
482-
for sym <- symbols do
483-
val TypeBounds(lo, hi) = gadt.fullBounds(sym).nn
484-
pickleSymRef(sym)
485-
pickleType(lo)
486-
pickleType(hi)
487-
}
488-
pickleTree(expr)
478+
pickleSymRef(sym)
479+
writeInt(nestingLevel)
480+
pickleType(info)
481+
pickleTree(body)
489482
}
490483
case tree @ If(cond, thenp, elsep) =>
491484
writeByte(IF)

0 commit comments

Comments
 (0)