Skip to content

Commit 38cd627

Browse files
committed
A more robust scheme for resetting denotations after Recheck
The new scheme works also for arbitrary denotation changes in PreRecheck. Furthermore, recheck denot transformers are not run after Recheck has ended. This means that effectivly only symbols touched by the Rechecker are transformed and reset again afterwards.
1 parent dc1fc60 commit 38cd627

File tree

4 files changed

+26
-23
lines changed

4 files changed

+26
-23
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,17 @@ object CheckCaptures:
3434
/** - Reset `private` flags of parameter accessors so that we can refine them
3535
* in Setup if they have non-empty capture sets.
3636
* - Special handling of some symbols defined for case classes.
37+
* Enabled only until recheck is finished, and provided some compilation unit
38+
* is CC-enabled.
3739
*/
3840
def transformSym(sym: SymDenotation)(using Context): SymDenotation =
39-
if sym.isAllOf(PrivateParamAccessor) && !sym.hasAnnotation(defn.ConstructorOnlyAnnot) then
40-
sym.copySymDenotation(initFlags = sym.flags &~ Private | Recheck.ResetPrivate)
41-
else if Synthetics.needsTransform(sym) then
42-
Synthetics.transform(sym, toCC = true)
43-
else
44-
sym
41+
if !pastRecheck && Feature.ccEnabledSomewhere then
42+
if sym.isAllOf(PrivateParamAccessor) && !sym.hasAnnotation(defn.ConstructorOnlyAnnot) then
43+
sym.copySymDenotation(initFlags = sym.flags &~ Private | Recheck.ResetPrivate)
44+
else if Synthetics.needsTransform(sym) then
45+
Synthetics.transform(sym, toCC = true)
46+
else sym
47+
else sym
4548
end Pre
4649

4750
enum EnvKind:

compiler/src/dotty/tools/dotc/cc/Setup.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -306,7 +306,7 @@ extends tpd.TreeTraverser:
306306

307307
/** Update info of `sym` for CheckCaptures phase only */
308308
private def updateInfo(sym: Symbol, info: Type)(using Context) =
309-
sym.updateInfoBetween(preRecheckPhase, thisPhase, info, newOwnerFor(sym))
309+
sym.updateInfo(preRecheckPhase, info, newOwnerFor(sym))
310310
sym.namedType match
311311
case ref: CaptureRef => ref.invalidateCaches()
312312
case _ =>

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ abstract class PreRecheck extends Phase, DenotTransformer:
1414

1515
override def changesBaseTypes: Boolean = true
1616

17+
var pastRecheck = false
18+
1719
def run(using Context): Unit = ()
1820

1921
override def isCheckable = false

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

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -48,26 +48,19 @@ object Recheck:
4848

4949
extension (sym: Symbol)
5050

51-
/** Update symbol's info to newInfo from prevPhase.next to lastPhase.
51+
/** Update symbol's info to newInfo after `prevPhase`.
5252
* Also update owner to newOwnerOrNull if it is not null.
53-
* Reset to previous info and owner for phases after lastPhase.
53+
* The update is valid until after Recheck. After that the symbol's denotation
54+
* is reset to what it was before PreRecheck.
5455
*/
55-
def updateInfoBetween(prevPhase: DenotTransformer, lastPhase: DenotTransformer, newInfo: Type, newOwnerOrNull: Symbol | Null = null)(using Context): Unit =
56+
def updateInfo(prevPhase: DenotTransformer, newInfo: Type, newOwnerOrNull: Symbol | Null = null)(using Context): Unit =
5657
val newOwner = if newOwnerOrNull == null then sym.owner else newOwnerOrNull
5758
if (sym.info ne newInfo) || (sym.owner ne newOwner) then
5859
val flags = sym.flags
59-
sym.copySymDenotation(
60-
initFlags =
61-
if flags.isAllOf(ResetPrivateParamAccessor)
62-
then flags &~ ResetPrivate | Private
63-
else flags
64-
).installAfter(lastPhase) // reset
6560
sym.copySymDenotation(
6661
owner = newOwner,
6762
info = newInfo,
68-
initFlags =
69-
if newInfo.isInstanceOf[LazyType] then flags &~ Touched
70-
else flags
63+
initFlags = if newInfo.isInstanceOf[LazyType] then flags &~ Touched else flags
7164
).installAfter(prevPhase)
7265

7366
/** Does symbol have a new denotation valid from phase.next that is different
@@ -158,16 +151,20 @@ abstract class Recheck extends Phase, SymTransformer:
158151
// One failing test is pos/i583a.scala
159152

160153
/** Change any `ResetPrivate` flags back to `Private` */
161-
def transformSym(sym: SymDenotation)(using Context): SymDenotation =
162-
if sym.isAllOf(Recheck.ResetPrivateParamAccessor) then
163-
sym.copySymDenotation(initFlags = sym.flags &~ Recheck.ResetPrivate | Private)
164-
else sym
154+
def transformSym(symd: SymDenotation)(using Context): SymDenotation =
155+
val sym = symd.symbol
156+
if sym.isUpdatedAfter(preRecheckPhase) then atPhase(preRecheckPhase)(sym.denot)
157+
else symd
165158

166159
def run(using Context): Unit =
167160
val rechecker = newRechecker()
168161
rechecker.checkUnit(ctx.compilationUnit)
169162
rechecker.reset()
170163

164+
override def runOn(units: List[CompilationUnit])(using runCtx: Context): List[CompilationUnit] =
165+
try super.runOn(units)
166+
finally preRecheckPhase.pastRecheck = true
167+
171168
def newRechecker()(using Context): Rechecker
172169

173170
/** The typechecker pass */
@@ -197,6 +194,7 @@ abstract class Recheck extends Phase, SymTransformer:
197194
def reset()(using Context): Unit =
198195
for (ref, mbr) <- prevSelDenots.iterator do
199196
ref.withDenot(mbr)
197+
preRecheckPhase
200198

201199
/** Constant-folded rechecked type `tp` of tree `tree` */
202200
protected def constFold(tree: Tree, tp: Type)(using Context): Type =

0 commit comments

Comments
 (0)