Skip to content

Commit

Permalink
Remove all mixin traits from Contexts. In particular:
Browse files Browse the repository at this point in the history
 - `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
  • Loading branch information
odersky committed Jul 20, 2020
1 parent b81cc98 commit 2cd85b9
Show file tree
Hide file tree
Showing 11 changed files with 71 additions and 57 deletions.
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
throw ex
}

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

report.echo(s"result of $unit after $squashedPhase:")
report.echo(s"result of $unit after $fusedPhase:")

last match {
case SomePrintedTree(phase, lastTreeSting) if lastTreeSting != treeString =>
val msg =
if (!ctx.settings.XprintDiff.value && !ctx.settings.XprintDiffDel.value) treeString
else DiffUtil.mkColoredCodeDiff(treeString, lastTreeSting, ctx.settings.XprintDiffDel.value)
report.echo(msg)
SomePrintedTree(squashedPhase.toString, treeString)
SomePrintedTree(fusedPhase.toString, treeString)

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

case NoPrintedTree =>
report.echo(treeString)
SomePrintedTree(squashedPhase.toString, treeString)
SomePrintedTree(fusedPhase.toString, treeString)
}
}

Expand Down
5 changes: 5 additions & 0 deletions compiler/src/dotty/tools/dotc/core/Annotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ object Annotations {
case symFn: (Context ?=> Symbol) @unchecked =>
mySym = null
mySym = atPhaseNoLater(picklerPhase)(symFn)
// We should always produce the same annotation tree, no matter when the
// annotation is evaluated. Setting the phase to a pre-transformation phase
// seems to be enough to ensure this (note that after erasure, `ctx.typer`
// will be the Erasure typer, but that doesn't seem to affect the annotation
// trees we create, so we leave it as is)
case sym: Symbol if sym.defRunId != parentCtx.runId =>
mySym = sym.denot.current.symbol
case _ =>
Expand Down
20 changes: 7 additions & 13 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ object Contexts {
private var phasedCtxs: Array[Context] = null

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

final def withPhaseNoLater(phase: Phase): Context =
if (phase.exists && period.phaseId > phase.id) withPhase(phase) else this

final def withPhaseNoEarlier(phase: Phase): Context =
if (phase.exists && period.phaseId < phase.id) withPhase(phase) else this

// `creationTrace`-related code. To enable, uncomment the code below and the
// call to `setCreationTrace()` in this file.
/*
Expand Down Expand Up @@ -662,8 +656,8 @@ object Contexts {
def updateStore[T](loc: Store.Location[T], value: T): this.type =
setStore(store.updated(loc, value))

def setPhase(pid: PhaseId): this.type = setPeriod(Period(period.runId, pid))
def setPhase(phase: Phase): this.type = setPeriod(Period(period.runId, phase.start, phase.end))
def setPhase(pid: PhaseId): this.type = setPeriod(Period(runId, pid))
def setPhase(phase: Phase): this.type = setPeriod(Period(runId, phase.start, phase.end))

def setSetting[T](setting: Setting[T], value: T): this.type =
setSettings(setting.updateIn(settingsState, value))
Expand Down Expand Up @@ -709,7 +703,7 @@ object Contexts {
testContexts(testsInUse).reuseIn(ctx)
else
val ts = TyperState()
.setReporter(TestingReporter())
.setReporter(ExploringReporter())
.setCommittable(false)
val c = FreshContext(ctx.base).init(ctx, ctx).setTyperState(ts)
testContexts += c
Expand All @@ -720,7 +714,7 @@ object Contexts {
val result =
try op(using nestedCtx)
finally
nestedTS.reporter.asInstanceOf[TestingReporter].reset()
nestedTS.reporter.asInstanceOf[ExploringReporter].reset()
testsInUse -= 1
result
end explore
Expand Down Expand Up @@ -796,7 +790,7 @@ object Contexts {
definitions.init()
}

def squashed(p: Phase): Phase =
def fusedContaining(p: Phase): Phase =
allPhases.find(_.period.containsPhaseId(p.id)).getOrElse(NoPhase)
}

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

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

/** Next denotation transformer id */
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/Definitions.scala
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,7 @@ class Definitions {
@tu lazy val InternalQuotedType_unapply: Symbol = InternalQuotedTypeModule.requiredMethod(nme.unapply)

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

@tu lazy val QuotedTypeModule: Symbol = QuotedTypeClass.companionModule

Expand Down
10 changes: 5 additions & 5 deletions compiler/src/dotty/tools/dotc/core/Phases.scala
Original file line number Diff line number Diff line change
Expand Up @@ -92,13 +92,13 @@ object Phases {
s"${phase.phaseName} requires ${unmetRequirements.mkString(", ")} to be in different TreeTransformer")

case _ =>
assert(false, s"Only tree transforms can be squashed, ${phase.phaseName} can not be squashed")
assert(false, s"Only tree transforms can be fused, ${phase.phaseName} can not be fused")
}
val superPhase = new MegaPhase(filteredPhaseBlock.asInstanceOf[List[MiniPhase]].toArray)
prevPhases ++= filteredPhaseBlock.map(_.phaseName)
superPhase
}
else { // block of a single phase, no squashing
else { // block of a single phase, no fusion
val phase = filteredPhaseBlock.head
prevPhases += phase.phaseName
phase
Expand All @@ -118,9 +118,9 @@ object Phases {

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

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

Expand Down Expand Up @@ -183,7 +183,7 @@ object Phases {
nextDenotTransformerId(i) = lastTransformerId
}

if (squash)
if (fuse)
this.fusedPhases = (NoPhase :: phasess).toArray
else
this.fusedPhases = this.phases
Expand Down
13 changes: 2 additions & 11 deletions compiler/src/dotty/tools/dotc/core/TyperState.scala
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class TyperState() {
private var myId: Int = _
def id: Int = myId

private var previous: TyperState = _
private var previous: TyperState /* | Null */ = _

private var myReporter: Reporter = _

Expand Down Expand Up @@ -69,7 +69,7 @@ class TyperState() {
/** Initializes all fields except reporter, isCommittable, which need to be
* set separately.
*/
private[core] def init(previous: TyperState, constraint: Constraint): this.type =
private[core] def init(previous: TyperState /* | Null */, constraint: Constraint): this.type =
this.myId = TyperState.nextId
TyperState.nextId += 1
this.previous = previous
Expand All @@ -79,15 +79,6 @@ class TyperState() {
this.isCommitted = false
this

def disable() =
previous = null
myConstraint = null
previousConstraint = null
myOwnedVars = null
isCommitted = false
myReporter = null
myIsCommittable = true

/** A fresh typer state with the same constraint as this one. */
def fresh(reporter: Reporter = StoreReporter(this.reporter)): TyperState =
util.Stats.record("TyperState.fresh")
Expand Down
16 changes: 9 additions & 7 deletions compiler/src/dotty/tools/dotc/core/tasty/TreeUnpickler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -116,9 +116,10 @@ class TreeUnpickler(reader: TastyReader,
val owner = ctx.owner
val source = ctx.source
def complete(denot: SymDenotation)(using Context): Unit =
treeAtAddr(currentAddr) =
treeAtAddr(currentAddr) = atPhaseNoLater(picklerPhase) {
new TreeReader(reader).readIndexedDef()(
using ctx.withPhaseNoLater(picklerPhase).withOwner(owner).withSource(source))
using ctx.withOwner(owner).withSource(source))
}
}

class TreeReader(val reader: TastyReader) {
Expand Down Expand Up @@ -1375,11 +1376,12 @@ class TreeUnpickler(reader: TastyReader,
op: TreeReader => Context ?=> T) extends Trees.Lazy[T] {
def complete(using Context): T = {
pickling.println(i"starting to read at ${reader.reader.currentAddr} with owner $owner")
op(reader)(using ctx
.withPhaseNoLater(picklerPhase)
.withOwner(owner)
.withModeBits(mode)
.withSource(source))
atPhaseNoLater(picklerPhase) {
op(reader)(using ctx
.withOwner(owner)
.withModeBits(mode)
.withSource(source))
}
}
}

Expand Down
21 changes: 21 additions & 0 deletions compiler/src/dotty/tools/dotc/reporting/ExploringReporter.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package dotty.tools
package dotc
package reporting

import collection.mutable
import core.Contexts.Context
import Diagnostic._

/** A re-usable Reporter used in Contexts#test */
class ExploringReporter extends StoreReporter(null):
infos = new mutable.ListBuffer[Diagnostic]

override def hasUnreportedErrors: Boolean =
infos.exists(_.isInstanceOf[Error])

override def removeBufferedMessages(using Context): List[Diagnostic] =
try infos.toList finally reset()

def reset(): Unit = infos.clear()

end ExploringReporter
17 changes: 10 additions & 7 deletions compiler/src/dotty/tools/dotc/transform/ExplicitOuter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -397,16 +397,19 @@ object ExplicitOuter {
try
@tailrec def loop(tree: Tree, count: Int): Tree =
val treeCls = tree.tpe.widen.classSymbol
val outerAccessorCtx = ctx.withPhaseNoLater(lambdaLiftPhase) // lambdalift mangles local class names, which means we cannot reliably find outer acessors anymore
report.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${outerAccName(treeCls.asClass)(using outerAccessorCtx)} in $treeCls")
report.log(i"outer to $toCls of $tree: ${tree.tpe}, looking for ${atPhaseNoLater(lambdaLiftPhase)(outerAccName(treeCls.asClass))} in $treeCls")
if (count == 0 || count < 0 && treeCls == toCls) tree
else
val enclClass = ctx.owner.lexicallyEnclosingClass.asClass
val outerAcc = tree match
case tree: This if tree.symbol == enclClass && !enclClass.is(Trait) =>
outerParamAccessor(enclClass)(using outerAccessorCtx)
case _ =>
outerAccessor(treeCls.asClass)(using outerAccessorCtx)
val outerAcc = atPhaseNoLater(lambdaLiftPhase) {
// lambdalift mangles local class names, which means we cannot
// reliably find outer acessors anymore
tree match
case tree: This if tree.symbol == enclClass && !enclClass.is(Trait) =>
outerParamAccessor(enclClass)
case _ =>
outerAccessor(treeCls.asClass)
}
assert(outerAcc.exists,
i"failure to construct path from ${ctx.owner.ownersIterator.toList}%/% to `this` of ${toCls.showLocated};\n${treeCls.showLocated} does not have an outer accessor")
loop(tree.select(outerAcc).ensureApplied, count - 1)
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/dotc/transform/TreeChecker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ class TreeChecker extends Phase with SymTransformer {
cur.signature
}
assert(curSig == initial.signature,
i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.squashed(ctx.phase.prev)}
i"""Signature of ${sym.showLocated} changed at phase ${ctx.base.fusedContaining(ctx.phase.prev)}
|Initial info: ${initial}
|Initial sig : ${initial.signature}
|Current info: ${cur}
Expand Down Expand Up @@ -133,8 +133,8 @@ class TreeChecker extends Phase with SymTransformer {

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

inContext(ctx) {
assertSelectWrapsNew(ctx.compilationUnit.tpdTree)
Expand Down
8 changes: 3 additions & 5 deletions compiler/src/dotty/tools/dotc/typer/Namer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ class Namer { typer: Typer =>
given creationContext as Context = ictx

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

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

def typedAheadType(tree: Tree, pt: Type = WildcardType)(using Context): tpd.Tree =
withoutMode(Mode.PatternOrTypeBits) {
withMode(Mode.Type) {
typedAhead(tree, typer.typed(_, pt))
}
inMode(ctx.mode &~ Mode.PatternOrTypeBits | Mode.Type) {
typedAhead(tree, typer.typed(_, pt))
}

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

0 comments on commit 2cd85b9

Please sign in to comment.