Skip to content

Commit 99b48be

Browse files
committed
Tasty pickling of variances in TypeBounds
1 parent b277157 commit 99b48be

File tree

4 files changed

+52
-8
lines changed

4 files changed

+52
-8
lines changed

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3486,10 +3486,16 @@ object Types {
34863486
}
34873487

34883488
override def newLikeThis(paramNames: List[ThisName], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): This =
3489-
HKTypeLambda(paramNames, givenVariances)(
3489+
newLikeThis(paramNames, givenVariances, paramInfos, resType)
3490+
3491+
def newLikeThis(paramNames: List[ThisName], variances: List[Variance], paramInfos: List[PInfo], resType: Type)(implicit ctx: Context): This =
3492+
HKTypeLambda(paramNames, variances)(
34903493
x => paramInfos.mapConserve(_.subst(this, x).asInstanceOf[PInfo]),
34913494
x => resType.subst(this, x))
34923495

3496+
def withVariances(variances: List[Variance])(implicit ctx: Context): This =
3497+
newLikeThis(paramNames, variances, paramInfos, resType)
3498+
34933499
protected def prefixString: String = "HKTypeLambda"
34943500
final override def toString: String =
34953501
if isVariant then

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

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,15 @@ class TreePickler(pickler: TastyPickler) {
134134
pickleType(c.symbolValue.termRef)
135135
}
136136

137+
def pickleVariances(tp: Type)(given Context): Unit = tp match
138+
case tp: HKTypeLambda if tp.isVariant =>
139+
for v <- tp.givenVariances do
140+
writeByte(
141+
if v.is(Covariant) then COVARIANT
142+
else if v.is(Contravariant) then CONTRAVARIANT
143+
else STABLE)
144+
case _ =>
145+
137146
def pickleType(tpe0: Type, richTypes: Boolean = false)(implicit ctx: Context): Unit = {
138147
val tpe = tpe0.stripTypeVar
139148
try {
@@ -230,11 +239,23 @@ class TreePickler(pickler: TastyPickler) {
230239
writeByte(RECtype)
231240
pickleType(tpe.parent)
232241
case tpe: TypeAlias =>
233-
writeByte(TYPEALIAS)
234-
pickleType(tpe.alias, richTypes)
242+
tpe.alias match
243+
case alias: HKTypeLambda if alias.isVariant =>
244+
writeByte(TYPEBOUNDS)
245+
withLength {
246+
pickleType(tpe.alias, richTypes)
247+
pickleVariances(tpe.alias)
248+
}
249+
case _ =>
250+
writeByte(TYPEALIAS)
251+
pickleType(tpe.alias, richTypes)
235252
case tpe: TypeBounds =>
236253
writeByte(TYPEBOUNDS)
237-
withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) }
254+
withLength {
255+
pickleType(tpe.lo, richTypes)
256+
pickleType(tpe.hi, richTypes)
257+
pickleVariances(tpe.hi)
258+
}
238259
case tpe: AnnotatedType =>
239260
writeByte(ANNOTATEDtype)
240261
withLength { pickleType(tpe.parent, richTypes); pickleTree(tpe.annot.tree) }

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

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Flags._
1616
import Constants._
1717
import Annotations._
1818
import NameKinds._
19+
import Variances.Invariant
1920
import typer.ConstFold
2021
import typer.Checking.checkNonCyclic
2122
import util.Spans._
@@ -303,6 +304,17 @@ class TreeUnpickler(reader: TastyReader,
303304
result.asInstanceOf[LT]
304305
}
305306

307+
def readVariances(tp: Type): Type = tp match
308+
case tp: HKTypeLambda if currentAddr != end =>
309+
val vs = until(end) {
310+
readByte() match
311+
case STABLE => Invariant
312+
case COVARIANT => Covariant
313+
case CONTRAVARIANT => Contravariant
314+
}
315+
tp.withVariances(vs)
316+
case _ => tp
317+
306318
val result =
307319
(tag: @switch) match {
308320
case TERMREFin =>
@@ -335,9 +347,10 @@ class TreeUnpickler(reader: TastyReader,
335347
readType().appliedTo(until(end)(readType()))
336348
case TYPEBOUNDS =>
337349
val lo = readType()
338-
val hi = readType()
339-
if (lo.isMatch && (lo `eq` hi)) MatchAlias(lo)
340-
else TypeBounds(lo, hi)
350+
val hi = if nothingButMods(end) then lo else readType()
351+
val variantHi = readVariances(hi)
352+
if (lo.isMatch && (lo `eq` hi)) MatchAlias(variantHi)
353+
else TypeBounds(lo, variantHi)
341354
case ANNOTATEDtype =>
342355
AnnotatedType(readType(), Annotation(readTerm()))
343356
case ANDtype =>

tasty/src/dotty/tools/tasty/TastyFormat.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ Standard-Section: "ASTs" TopLevelStat*
154154
REFINEDtype Length underlying_Type refinement_NameRef info_Type -- underlying { refinement_name : info }
155155
APPLIEDtype Length tycon_Type arg_Type* -- tycon[args]
156156
TYPEALIAS alias_Type -- = alias
157-
TYPEBOUNDS Length low_Type high_Type -- >: low <: high
157+
TYPEBOUNDS Length lowOrAlias_Type high_Type? Variance* -- = alias or >: low <: high, possibly with variances of lambda parameters
158158
ANNOTATEDtype Length underlying_Type annotation_Term -- underlying @ annotation
159159
ANDtype Length left_Type right_Type -- left & right
160160
ORtype Length left_Type right_Type -- lefgt | right
@@ -213,6 +213,10 @@ Standard-Section: "ASTs" TopLevelStat*
213213
OPEN -- an open class
214214
Annotation
215215
216+
Variance = SEALED -- invariant
217+
| COVARIANT
218+
| CONTRAVARIANT
219+
216220
Annotation = ANNOTATION Length tycon_Type fullAnnotation_Term -- An annotation, given (class) type of constructor, and full application tree
217221
218222
Note: Tree tags are grouped into 5 categories that determine what follows, and thus allow to compute the size of the tagged tree in a generic way.

0 commit comments

Comments
 (0)