Skip to content

Commit

Permalink
Fix the pickling of This inside capture sets (#19797)
Browse files Browse the repository at this point in the history
Fixes #19662
  • Loading branch information
odersky authored Feb 27, 2024
2 parents 42ac402 + 47517b6 commit b18a02e
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 3 deletions.
9 changes: 8 additions & 1 deletion compiler/src/dotty/tools/dotc/core/tasty/TreePickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,14 @@ class TreePickler(pickler: TastyPickler, attributes: Attributes) {
pickleType(tp)
}
case This(qual) =>
if (qual.isEmpty) pickleType(tree.tpe)
if (qual.isEmpty)
if tree.tpe.isSingleton then pickleType(tree.tpe)
else
// This may happen when pickling a `This` inside a capture set. See #19662.
// In this case, we pickle the tree as null.asInstanceOf[tree.tpe].
// Since the pickled tree is not the same as the input, special handling is needed
// in the tree printer when testing the pickler. See [[PlainPrinter#homogenize]].
pickleTree(Literal(Constant(null)).cast(tree.tpe).withSpan(tree.span))
else {
writeByte(QUALTHIS)
val ThisType(tref) = tree.tpe: @unchecked
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import util.SourcePosition
import scala.util.control.NonFatal
import scala.annotation.switch
import config.{Config, Feature}
import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems}
import cc.{CapturingType, RetainingType, CaptureSet, ReachCapability, MaybeCapability, isBoxed, levelOwner, retainedElems, isRetainsLike}

class PlainPrinter(_ctx: Context) extends Printer {

Expand Down Expand Up @@ -60,7 +60,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
case OrType(tp1, tp2) =>
homogenize(tp1) | homogenize(tp2)
case AnnotatedType(parent, annot)
if !ctx.mode.is(Mode.Type) && annot.symbol == defn.UncheckedVarianceAnnot =>
if !ctx.mode.is(Mode.Type) && annot.symbol == defn.UncheckedVarianceAnnot
|| annot.symbol.isRetainsLike =>
homogenize(parent)
case tp: SkolemType =>
homogenize(tp.info)
Expand Down
9 changes: 9 additions & 0 deletions tests/pos-custom-args/captures/i19662.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Modified from #19662 to make it independent of the cc stdlib.
import language.experimental.captureChecking
trait MySeq[+A] { self: MySeq[A]^ =>
def map[B](f: A => B): MySeq[B]^{this, f}
}
object MySeq:
def apply(x: Int): MySeq[Int] = ???
class C:
private def foo = MySeq(5).map { i => i }

0 comments on commit b18a02e

Please sign in to comment.