Skip to content

Commit b18a02e

Browse files
authored
Fix the pickling of This inside capture sets (#19797)
Fixes #19662
2 parents 42ac402 + 47517b6 commit b18a02e

File tree

3 files changed

+20
-3
lines changed

3 files changed

+20
-3
lines changed

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -405,7 +405,14 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) {
405405
pickleType(tp)
406406
}
407407
case This(qual) =>
408-
if (qual.isEmpty) pickleType(tree.tpe)
408+
if (qual.isEmpty)
409+
if tree.tpe.isSingleton then pickleType(tree.tpe)
410+
else
411+
// This may happen when pickling a `This` inside a capture set. See #19662.
412+
// In this case, we pickle the tree as null.asInstanceOf[tree.tpe].
413+
// Since the pickled tree is not the same as the input, special handling is needed
414+
// in the tree printer when testing the pickler. See [[PlainPrinter#homogenize]].
415+
pickleTree(Literal(Constant(null)).cast(tree.tpe).withSpan(tree.span))
409416
else {
410417
writeByte(QUALTHIS)
411418
val ThisType(tref) = tree.tpe: @unchecked

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import util.SourcePosition
1515
import scala.util.control.NonFatal
1616
import scala.annotation.switch
1717
import config.{Config, Feature}
18-
import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems}
18+
import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems, isRetainsLike}
1919

2020
class PlainPrinter(_ctx: Context) extends Printer {
2121

@@ -60,7 +60,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
6060
case OrType(tp1, tp2) =>
6161
homogenize(tp1) | homogenize(tp2)
6262
case AnnotatedType(parent, annot)
63-
if !ctx.mode.is(Mode.Type) && annot.symbol == defn.UncheckedVarianceAnnot =>
63+
if !ctx.mode.is(Mode.Type) && annot.symbol == defn.UncheckedVarianceAnnot
64+
|| annot.symbol.isRetainsLike =>
6465
homogenize(parent)
6566
case tp: SkolemType =>
6667
homogenize(tp.info)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Modified from #19662 to make it independent of the cc stdlib.
2+
import language.experimental.captureChecking
3+
trait MySeq[+A] { self: MySeq[A]^ =>
4+
def map[B](f: A => B): MySeq[B]^{this, f}
5+
}
6+
object MySeq:
7+
def apply(x: Int): MySeq[Int] = ???
8+
class C:
9+
private def foo = MySeq(5).map { i => i }

0 commit comments

Comments
 (0)