Skip to content

Commit dd661bf

Browse files
committed
Make LazyRef completers take a context
This avoids memory leaks in unpicklers, where lazy refs don't capture the context anymore. Other lazyrefs still need to capture context, though.
1 parent b765b95 commit dd661bf

File tree

4 files changed

+11
-14
lines changed

4 files changed

+11
-14
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ class TypeApplications(val self: Type) extends AnyVal {
443443
case dealiased: TypeBounds =>
444444
dealiased.derivedTypeBounds(dealiased.lo.appliedTo(args), dealiased.hi.appliedTo(args))
445445
case dealiased: LazyRef =>
446-
LazyRef(() => dealiased.ref.appliedTo(args))
446+
LazyRef(c => dealiased.ref(c).appliedTo(args))
447447
case dealiased: WildcardType =>
448448
WildcardType(dealiased.optBounds.appliedTo(args).bounds)
449449
case dealiased: TypeRef if dealiased.symbol == defn.NothingClass =>

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

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,25 +2149,23 @@ object Types {
21492149
}
21502150
}
21512151

2152-
case class LazyRef(private var refFn: () => Type) extends UncachedProxyType with ValueType {
2152+
case class LazyRef(private var refFn: Context => Type) extends UncachedProxyType with ValueType {
21532153
private var myRef: Type = null
21542154
private var computed = false
2155-
def ref = {
2155+
def ref(implicit ctx: Context) = {
21562156
if (computed) assert(myRef != null)
21572157
else {
21582158
computed = true
2159-
myRef = refFn()
2159+
myRef = refFn(ctx)
2160+
refFn = null
21602161
}
21612162
myRef
21622163
}
21632164
def evaluating = computed && myRef == null
21642165
override def underlying(implicit ctx: Context) = ref
2165-
override def toString = s"LazyRef($ref)"
2166-
override def equals(other: Any) = other match {
2167-
case other: LazyRef => this.ref.equals(other.ref)
2168-
case _ => false
2169-
}
2170-
override def hashCode = ref.hashCode + 37
2166+
override def toString = s"LazyRef(...)"
2167+
override def equals(other: Any) = this eq other.asInstanceOf[AnyRef]
2168+
override def hashCode = System.identityHashCode(this)
21712169
}
21722170

21732171
// --- Refined Type and RecType ------------------------------------------------
@@ -3768,7 +3766,7 @@ object Types {
37683766
derivedSuperType(tp, this(thistp), this(supertp))
37693767

37703768
case tp: LazyRef =>
3771-
LazyRef(() => this(tp.ref))
3769+
LazyRef(_ => this(tp.ref))
37723770

37733771
case tp: ClassInfo =>
37743772
mapClassInfo(tp)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,8 @@ class TreeUnpickler(reader: TastyReader, nameAtRef: NameRef => TermName, posUnpi
295295
RecThis(readTypeRef().asInstanceOf[RecType])
296296
case LAZYref =>
297297
val rdr = fork
298-
def readUnderlying() = rdr.readType()
299298
skipTree()
300-
LazyRef(readUnderlying)
299+
LazyRef(implicit ctx => rdr.readType())
301300
case SHARED =>
302301
val ref = readAddr()
303302
typeAtAddr.getOrElseUpdate(ref, forkAt(ref).readType())

compiler/src/dotty/tools/dotc/typer/Checking.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ object Checking {
249249
} catch {
250250
case ex: CyclicReference =>
251251
ctx.debuglog(i"cycle detected for $tp, $nestedCycleOK, $cycleOK")
252-
if (cycleOK) LazyRef(() => tp)
252+
if (cycleOK) LazyRef(_ => tp)
253253
else if (reportErrors) throw ex
254254
else tp
255255
}

0 commit comments

Comments
 (0)