Skip to content

Commit cfec1d0

Browse files
committed
Simplify CapturedVars phase
No need for a separate entry in the context's store; we can keep everything in the phase itself, which is more efficient and modular.
1 parent e22744d commit cfec1d0

File tree

1 file changed

+20
-35
lines changed

1 file changed

+20
-35
lines changed

compiler/src/dotty/tools/dotc/transform/CapturedVars.scala

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,20 @@ import core.NameKinds.TempResultName
1313
import core.Constants._
1414
import util.Store
1515
import dotty.tools.uncheckedNN
16-
17-
import scala.compiletime.uninitialized
16+
import ast.tpd.*
17+
import compiletime.uninitialized
1818

1919
/** This phase translates variables that are captured in closures to
2020
* heap-allocated refs.
2121
*/
2222
class CapturedVars extends MiniPhase with IdentityDenotTransformer:
2323
thisPhase =>
24-
import ast.tpd._
2524

2625
override def phaseName: String = CapturedVars.name
2726

2827
override def description: String = CapturedVars.description
2928

30-
private[this] var Captured: Store.Location[util.ReadOnlySet[Symbol]] = uninitialized
31-
private def captured(using Context) = ctx.store(Captured)
32-
33-
override def initContext(ctx: FreshContext): Unit =
34-
Captured = ctx.addLocation(util.ReadOnlySet.empty)
29+
private val captured = util.HashSet[Symbol]()
3530

3631
private class RefInfo(using Context) {
3732
/** The classes for which a Ref type exists. */
@@ -57,33 +52,10 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer:
5752
myRefInfo.uncheckedNN
5853
}
5954

60-
private class CollectCaptured extends TreeTraverser {
61-
private val captured = util.HashSet[Symbol]()
62-
def traverse(tree: Tree)(using Context) = tree match {
63-
case id: Ident =>
64-
val sym = id.symbol
65-
if (sym.is(Mutable, butNot = Method) && sym.owner.isTerm) {
66-
val enclMeth = ctx.owner.enclosingMethod
67-
if (sym.enclosingMethod != enclMeth) {
68-
report.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth")
69-
captured += sym
70-
}
71-
}
72-
case _ =>
73-
traverseChildren(tree)
74-
}
75-
def runOver(tree: Tree)(using Context): util.ReadOnlySet[Symbol] = {
76-
traverse(tree)
77-
captured
78-
}
79-
}
80-
81-
override def prepareForUnit(tree: Tree)(using Context): Context = {
82-
val captured = atPhase(thisPhase) {
83-
CollectCaptured().runOver(ctx.compilationUnit.tpdTree)
84-
}
85-
ctx.fresh.updateStore(Captured, captured)
86-
}
55+
override def prepareForUnit(tree: Tree)(using Context): Context =
56+
captured.clear()
57+
atPhase(thisPhase)(CapturedVars.collect(captured)).traverse(tree)
58+
ctx
8759

8860
/** The {Volatile|}{Int|Double|...|Object}Ref class corresponding to the class `cls`,
8961
* depending on whether the reference should be @volatile
@@ -143,3 +115,16 @@ class CapturedVars extends MiniPhase with IdentityDenotTransformer:
143115
object CapturedVars:
144116
val name: String = "capturedVars"
145117
val description: String = "represent vars captured by closures as heap objects"
118+
119+
def collect(captured: util.HashSet[Symbol]): TreeTraverser = new:
120+
def traverse(tree: Tree)(using Context) = tree match
121+
case id: Ident =>
122+
val sym = id.symbol
123+
if sym.is(Mutable, butNot = Method) && sym.owner.isTerm then
124+
val enclMeth = ctx.owner.enclosingMethod
125+
if sym.enclosingMethod != enclMeth then
126+
report.log(i"capturing $sym in ${sym.enclosingMethod}, referenced from $enclMeth")
127+
captured += sym
128+
case _ =>
129+
traverseChildren(tree)
130+
end CapturedVars

0 commit comments

Comments
 (0)