Skip to content

Commit 2cd85b9

Browse files
committed
Remove all mixin traits from Contexts. In particular:
- `newSymbol`, `requiredSymbol` etc, now are available from Symbols, no `ctx.` prefix needed - All reporing methods are available from `report` object. Also: - Change functions from Context to context functions. - Add atPhase, atPhaseNoLater, addPhaseNoEarlier and have them replace most uss of `withPhase`... - Add inMode, withMode, withoutMode utility wrappers - Move error messages directly into reporting: this avoids an annoying import - Convert old style implicit parameters to `(using Context)` - Reorganize TyperState.test: Instead of overwriting fields of TyperState, keep test contexts in an explicit stack, so that they can be re-used. This is simpler and since there is more decoupling between tests. Usage is now `Contexts.explore(...)` instead of `ctx.test(...)`. # Conflicts: # compiler/src/dotty/tools/dotc/core/Definitions.scala # Conflicts: # compiler/src/dotty/tools/dotc/Run.scala # compiler/src/dotty/tools/dotc/core/Annotations.scala # compiler/src/dotty/tools/dotc/core/Contexts.scala # compiler/src/dotty/tools/dotc/core/Definitions.scala # compiler/src/dotty/tools/dotc/core/Phases.scala # compiler/src/dotty/tools/dotc/core/TyperState.scala # compiler/src/dotty/tools/dotc/core/Types.scala # compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala # compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala # compiler/src/dotty/tools/dotc/transform/TreeChecker.scala # compiler/src/dotty/tools/dotc/typer/Namer.scala
1 parent b81cc98 commit 2cd85b9

File tree

11 files changed

+71
-57
lines changed

11 files changed

+71
-57
lines changed

compiler/src/dotty/tools/dotc/Run.scala

+5-5
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
131131
throw ex
132132
}
133133

134-
/** TODO: There's a fundamental design problem here: We assemble phases using `squash`
134+
/** TODO: There's a fundamental design problem here: We assemble phases using `fusePhases`
135135
* when we first build the compiler. But we modify them with -Yskip, -Ystop
136136
* on each run. That modification needs to either transform the tree structure,
137137
* or we need to assemble phases on each run, and take -Yskip, -Ystop into
@@ -237,26 +237,26 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
237237
private def printTree(last: PrintedTree)(using Context): PrintedTree = {
238238
val unit = ctx.compilationUnit
239239
val prevPhase = ctx.phase.prev // can be a mini-phase
240-
val squashedPhase = ctx.base.squashed(prevPhase)
240+
val fusedPhase = ctx.base.fusedContaining(prevPhase)
241241
val treeString = unit.tpdTree.show(using ctx.withProperty(XprintMode, Some(())))
242242

243-
report.echo(s"result of $unit after $squashedPhase:")
243+
report.echo(s"result of $unit after $fusedPhase:")
244244

245245
last match {
246246
case SomePrintedTree(phase, lastTreeSting) if lastTreeSting != treeString =>
247247
val msg =
248248
if (!ctx.settings.XprintDiff.value && !ctx.settings.XprintDiffDel.value) treeString
249249
else DiffUtil.mkColoredCodeDiff(treeString, lastTreeSting, ctx.settings.XprintDiffDel.value)
250250
report.echo(msg)
251-
SomePrintedTree(squashedPhase.toString, treeString)
251+
SomePrintedTree(fusedPhase.toString, treeString)
252252

253253
case SomePrintedTree(phase, lastTreeSting) =>
254254
report.echo(" Unchanged since " + phase)
255255
last
256256

257257
case NoPrintedTree =>
258258
report.echo(treeString)
259-
SomePrintedTree(squashedPhase.toString, treeString)
259+
SomePrintedTree(fusedPhase.toString, treeString)
260260
}
261261
}
262262

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

+5
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ object Annotations {
5959
case symFn: (Context ?=> Symbol) @unchecked =>
6060
mySym = null
6161
mySym = atPhaseNoLater(picklerPhase)(symFn)
62+
// We should always produce the same annotation tree, no matter when the
63+
// annotation is evaluated. Setting the phase to a pre-transformation phase
64+
// seems to be enough to ensure this (note that after erasure, `ctx.typer`
65+
// will be the Erasure typer, but that doesn't seem to affect the annotation
66+
// trees we create, so we leave it as is)
6267
case sym: Symbol if sym.defRunId != parentCtx.runId =>
6368
mySym = sym.denot.current.symbol
6469
case _ =>

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

+7-13
Original file line numberDiff line numberDiff line change
@@ -305,7 +305,7 @@ object Contexts {
305305
private var phasedCtxs: Array[Context] = null
306306

307307
/** This context at given phase.
308-
* This method will always return a phase period equal to phaseId, thus will never return squashed phases
308+
* This method will always return a phase period equal to phaseId, thus will never return a fused phase
309309
*/
310310
final def withPhase(phaseId: PhaseId): Context =
311311
if (this.period.phaseId == phaseId) this
@@ -324,12 +324,6 @@ object Contexts {
324324
final def withPhase(phase: Phase): Context =
325325
withPhase(phase.id)
326326

327-
final def withPhaseNoLater(phase: Phase): Context =
328-
if (phase.exists && period.phaseId > phase.id) withPhase(phase) else this
329-
330-
final def withPhaseNoEarlier(phase: Phase): Context =
331-
if (phase.exists && period.phaseId < phase.id) withPhase(phase) else this
332-
333327
// `creationTrace`-related code. To enable, uncomment the code below and the
334328
// call to `setCreationTrace()` in this file.
335329
/*
@@ -662,8 +656,8 @@ object Contexts {
662656
def updateStore[T](loc: Store.Location[T], value: T): this.type =
663657
setStore(store.updated(loc, value))
664658

665-
def setPhase(pid: PhaseId): this.type = setPeriod(Period(period.runId, pid))
666-
def setPhase(phase: Phase): this.type = setPeriod(Period(period.runId, phase.start, phase.end))
659+
def setPhase(pid: PhaseId): this.type = setPeriod(Period(runId, pid))
660+
def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end))
667661

668662
def setSetting[T](setting: Setting[T], value: T): this.type =
669663
setSettings(setting.updateIn(settingsState, value))
@@ -709,7 +703,7 @@ object Contexts {
709703
testContexts(testsInUse).reuseIn(ctx)
710704
else
711705
val ts = TyperState()
712-
.setReporter(TestingReporter())
706+
.setReporter(ExploringReporter())
713707
.setCommittable(false)
714708
val c = FreshContext(ctx.base).init(ctx, ctx).setTyperState(ts)
715709
testContexts += c
@@ -720,7 +714,7 @@ object Contexts {
720714
val result =
721715
try op(using nestedCtx)
722716
finally
723-
nestedTS.reporter.asInstanceOf[TestingReporter].reset()
717+
nestedTS.reporter.asInstanceOf[ExploringReporter].reset()
724718
testsInUse -= 1
725719
result
726720
end explore
@@ -796,7 +790,7 @@ object Contexts {
796790
definitions.init()
797791
}
798792

799-
def squashed(p: Phase): Phase =
793+
def fusedContaining(p: Phase): Phase =
800794
allPhases.find(_.period.containsPhaseId(p.id)).getOrElse(NoPhase)
801795
}
802796

@@ -864,7 +858,7 @@ object Contexts {
864858
/** Phases by id */
865859
private[dotc] var phases: Array[Phase] = _
866860

867-
/** Phases with consecutive Transforms grouped into a single phase, Empty array if squashing is disabled */
861+
/** Phases with consecutive Transforms grouped into a single phase, Empty array if fusion is disabled */
868862
private[core] var fusedPhases: Array[Phase] = Array.empty[Phase]
869863

870864
/** Next denotation transformer id */

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -710,7 +710,7 @@ class Definitions {
710710
@tu lazy val InternalQuotedType_unapply: Symbol = InternalQuotedTypeModule.requiredMethod(nme.unapply)
711711

712712
@tu lazy val QuotedTypeClass: ClassSymbol = requiredClass("scala.quoted.Type")
713-
@tu lazy val QuotedType_splice: Symbol = QuotedTypeClass.requiredType(tpnme.splice)
713+
@tu lazy val QuotedType_splice: Symbol = QuotedTypeClass.requiredType(tpnme.spliceType)
714714

715715
@tu lazy val QuotedTypeModule: Symbol = QuotedTypeClass.companionModule
716716

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,13 @@ object Phases {
9292
s"${phase.phaseName} requires ${unmetRequirements.mkString(", ")} to be in different TreeTransformer")
9393

9494
case _ =>
95-
assert(false, s"Only tree transforms can be squashed, ${phase.phaseName} can not be squashed")
95+
assert(false, s"Only tree transforms can be fused, ${phase.phaseName} can not be fused")
9696
}
9797
val superPhase = new MegaPhase(filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray)
9898
prevPhases ++= filteredPhaseBlock.map(_.phaseName)
9999
superPhase
100100
}
101-
else { // block of a single phase, no squashing
101+
else { // block of a single phase, no fusion
102102
val phase = filteredPhaseBlock.head
103103
prevPhases += phase.phaseName
104104
phase
@@ -118,9 +118,9 @@ object Phases {
118118

119119
/** Use the following phases in the order they are given.
120120
* The list should never contain NoPhase.
121-
* if squashing is enabled, phases in same subgroup will be squashed to single phase.
121+
* if fusion is enabled, phases in same subgroup will be fused to single phase.
122122
*/
123-
final def usePhases(phasess: List[Phase], squash: Boolean = true): Unit = {
123+
final def usePhases(phasess: List[Phase], fuse: Boolean = true): Unit = {
124124

125125
val flatPhases = collection.mutable.ListBuffer[Phase]()
126126

@@ -183,7 +183,7 @@ object Phases {
183183
nextDenotTransformerId(i) = lastTransformerId
184184
}
185185

186-
if (squash)
186+
if (fuse)
187187
this.fusedPhases = (NoPhase :: phasess).toArray
188188
else
189189
this.fusedPhases = this.phases

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

+2-11
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class TyperState() {
2929
private var myId: Int = _
3030
def id: Int = myId
3131

32-
private var previous: TyperState = _
32+
private var previous: TyperState /* | Null */ = _
3333

3434
private var myReporter: Reporter = _
3535

@@ -69,7 +69,7 @@ class TyperState() {
6969
/** Initializes all fields except reporter, isCommittable, which need to be
7070
* set separately.
7171
*/
72-
private[core] def init(previous: TyperState, constraint: Constraint): this.type =
72+
private[core] def init(previous: TyperState /* | Null */, constraint: Constraint): this.type =
7373
this.myId = TyperState.nextId
7474
TyperState.nextId += 1
7575
this.previous = previous
@@ -79,15 +79,6 @@ class TyperState() {
7979
this.isCommitted = false
8080
this
8181

82-
def disable() =
83-
previous = null
84-
myConstraint = null
85-
previousConstraint = null
86-
myOwnedVars = null
87-
isCommitted = false
88-
myReporter = null
89-
myIsCommittable = true
90-
9182
/** A fresh typer state with the same constraint as this one. */
9283
def fresh(reporter: Reporter = StoreReporter(this.reporter)): TyperState =
9384
util.Stats.record("TyperState.fresh")

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

+9-7
Original file line numberDiff line numberDiff line change
@@ -116,9 +116,10 @@ class TreeUnpickler(reader: TastyReader,
116116
val owner = ctx.owner
117117
val source = ctx.source
118118
def complete(denot: SymDenotation)(using Context): Unit =
119-
treeAtAddr(currentAddr) =
119+
treeAtAddr(currentAddr) = atPhaseNoLater(picklerPhase) {
120120
new TreeReader(reader).readIndexedDef()(
121-
using ctx.withPhaseNoLater(picklerPhase).withOwner(owner).withSource(source))
121+
using ctx.withOwner(owner).withSource(source))
122+
}
122123
}
123124

124125
class TreeReader(val reader: TastyReader) {
@@ -1375,11 +1376,12 @@ class TreeUnpickler(reader: TastyReader,
13751376
op: TreeReader => Context ?=> T) extends Trees.Lazy[T] {
13761377
def complete(using Context): T = {
13771378
pickling.println(i"starting to read at ${reader.reader.currentAddr} with owner $owner")
1378-
op(reader)(using ctx
1379-
.withPhaseNoLater(picklerPhase)
1380-
.withOwner(owner)
1381-
.withModeBits(mode)
1382-
.withSource(source))
1379+
atPhaseNoLater(picklerPhase) {
1380+
op(reader)(using ctx
1381+
.withOwner(owner)
1382+
.withModeBits(mode)
1383+
.withSource(source))
1384+
}
13831385
}
13841386
}
13851387

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package dotty.tools
2+
package dotc
3+
package reporting
4+
5+
import collection.mutable
6+
import core.Contexts.Context
7+
import Diagnostic._
8+
9+
/** A re-usable Reporter used in Contexts#test */
10+
class ExploringReporter extends StoreReporter(null):
11+
infos = new mutable.ListBuffer[Diagnostic]
12+
13+
override def hasUnreportedErrors: Boolean =
14+
infos.exists(_.isInstanceOf[Error])
15+
16+
override def removeBufferedMessages(using Context): List[Diagnostic] =
17+
try infos.toList finally reset()
18+
19+
def reset(): Unit = infos.clear()
20+
21+
end ExploringReporter

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

+10-7
Original file line numberDiff line numberDiff line change
@@ -397,16 +397,19 @@ object ExplicitOuter {
397397
try
398398
@tailrec def loop(tree: Tree, count: Int): Tree =
399399
val treeCls = tree.tpe.widen.classSymbol
400-
val outerAccessorCtx = ctx.withPhaseNoLater(lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore
401-
report.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(using outerAccessorCtx)} in $treeCls")
400+
report.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${atPhaseNoLater(lambdaLiftPhase)(outerAccName(treeCls.asClass))} in $treeCls")
402401
if (count == 0 || count < 0 && treeCls == toCls) tree
403402
else
404403
val enclClass = ctx.owner.lexicallyEnclosingClass.asClass
405-
val outerAcc = tree match
406-
case tree: This if tree.symbol == enclClass && !enclClass.is(Trait) =>
407-
outerParamAccessor(enclClass)(using outerAccessorCtx)
408-
case _ =>
409-
outerAccessor(treeCls.asClass)(using outerAccessorCtx)
404+
val outerAcc = atPhaseNoLater(lambdaLiftPhase) {
405+
// lambdalift mangles local class names, which means we cannot
406+
// reliably find outer acessors anymore
407+
tree match
408+
case tree: This if tree.symbol == enclClass && !enclClass.is(Trait) =>
409+
outerParamAccessor(enclClass)
410+
case _ =>
411+
outerAccessor(treeCls.asClass)
412+
}
410413
assert(outerAcc.exists,
411414
i"failure to construct path from ${ctx.owner.ownersIterator.toList}%/% to `this` of ${toCls.showLocated};\n${treeCls.showLocated} does not have an outer accessor")
412415
loop(tree.select(outerAcc).ensureApplied, count - 1)

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

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ class TreeChecker extends Phase with SymTransformer {
100100
cur.signature
101101
}
102102
assert(curSig == initial.signature,
103-
i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.squashed(ctx.phase.prev)}
103+
i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.fusedContaining(ctx.phase.prev)}
104104
|Initial info: ${initial}
105105
|Initial sig : ${initial.signature}
106106
|Current info: ${cur}
@@ -133,8 +133,8 @@ class TreeChecker extends Phase with SymTransformer {
133133

134134
def check(phasesToRun: Seq[Phase], ctx: Context): Tree = {
135135
val prevPhase = ctx.phase.prev // can be a mini-phase
136-
val squashedPhase = ctx.base.squashed(prevPhase)
137-
report.echo(s"checking ${ctx.compilationUnit} after phase ${squashedPhase}")(using ctx)
136+
val fusedPhase = ctx.base.fusedContaining(prevPhase)
137+
report.echo(s"checking ${ctx.compilationUnit} after phase ${fusedPhase}")(using ctx)
138138

139139
inContext(ctx) {
140140
assertSelectWrapsNew(ctx.compilationUnit.tpdTree)

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

+3-5
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@ class Namer { typer: Typer =>
669669
given creationContext as Context = ictx
670670

671671
// make sure testing contexts are not captured by completers
672-
assert(!ictx.reporter.isInstanceOf[TestingReporter])
672+
assert(!ictx.reporter.isInstanceOf[ExploringReporter])
673673

674674
protected def typeSig(sym: Symbol): Type = original match {
675675
case original: ValDef =>
@@ -1213,10 +1213,8 @@ class Namer { typer: Typer =>
12131213
}
12141214

12151215
def typedAheadType(tree: Tree, pt: Type = WildcardType)(using Context): tpd.Tree =
1216-
withoutMode(Mode.PatternOrTypeBits) {
1217-
withMode(Mode.Type) {
1218-
typedAhead(tree, typer.typed(_, pt))
1219-
}
1216+
inMode(ctx.mode &~ Mode.PatternOrTypeBits | Mode.Type) {
1217+
typedAhead(tree, typer.typed(_, pt))
12201218
}
12211219

12221220
def typedAheadExpr(tree: Tree, pt: Type = WildcardType)(using Context): tpd.Tree =

0 commit comments

Comments
 (0)