Skip to content

Commit f0b3080

Browse files
committed
Simplify TyperState
Have just one class instead of two. This will be important for inlining the `test` method. Also, fix test method - it needs to create a new StoreReporter.
1 parent ba9ad1e commit f0b3080

File tree

4 files changed

+69
-92
lines changed

4 files changed

+69
-92
lines changed

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class Run(comp: Compiler, ictx: Context) {
4949
.setOwner(defn.RootClass)
5050
.setTyper(new Typer)
5151
.addMode(Mode.ImplicitsEnabled)
52-
.setTyperState(new MutableTyperState(ctx.typerState, ctx.typerState.reporter, isCommittable = true))
52+
.setTyperState(new TyperState(ctx.typerState))
5353
.setFreshNames(new FreshNameCreator.Default)
5454
ctx.initialize()(start) // re-initialize the base context with start
5555
def addImport(ctx: Context, refFn: () => TermRef) =

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,9 +455,9 @@ object Contexts {
455455
def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
456456
def setSbtCallback(callback: AnalysisCallback): this.type = { this.sbtCallback = callback; this }
457457
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
458-
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.withReporter(reporter))
459-
def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
460-
def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false))
458+
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.fresh().setReporter(reporter))
459+
def setNewTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(true))
460+
def setExploreTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(false))
461461
def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
462462
def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this }
463463
def setSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
@@ -516,7 +516,7 @@ object Contexts {
516516
outer = NoContext
517517
period = InitialPeriod
518518
mode = Mode.None
519-
typerState = new TyperState(new ConsoleReporter())
519+
typerState = new TyperState(null)
520520
printerFn = new RefinedPrinter(_)
521521
owner = NoSymbol
522522
sstate = settings.defaultState

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

Lines changed: 62 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,31 @@ import config.Config
1313
import collection.mutable
1414
import java.lang.ref.WeakReference
1515

16-
class TyperState(r: Reporter) extends DotClass with Showable {
16+
class TyperState(previous: TyperState /* | Null */) extends DotClass with Showable {
1717

18-
/** The current reporter */
19-
def reporter = r
18+
private var myReporter =
19+
if (previous == null) new ConsoleReporter() else previous.reporter
2020

21-
/** The current constraint set */
22-
def constraint: Constraint =
23-
new OrderingConstraint(SimpleMap.Empty, SimpleMap.Empty, SimpleMap.Empty)
24-
def constraint_=(c: Constraint)(implicit ctx: Context): Unit = {}
21+
def reporter: Reporter = myReporter
2522

26-
/** The uninstantiated variables */
27-
def uninstVars = constraint.uninstVars
23+
/** A fresh type state with the same constraint as this one and the given reporter */
24+
def setReporter(reporter: Reporter): this.type = { myReporter = reporter; this }
25+
26+
private var myConstraint: Constraint =
27+
if (previous == null) new OrderingConstraint(SimpleMap.Empty, SimpleMap.Empty, SimpleMap.Empty)
28+
else previous.constraint
29+
30+
def constraint = myConstraint
31+
def constraint_=(c: Constraint)(implicit ctx: Context) = {
32+
if (Config.debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed()
33+
myConstraint = c
34+
}
35+
36+
private val previousConstraint =
37+
if (previous == null) constraint else previous.constraint
38+
39+
private var myEphemeral: Boolean =
40+
if (previous == null) false else previous.ephemeral
2841

2942
/** The ephemeral flag is set as a side effect if an operation accesses
3043
* the underlying type of a type variable. The reason we need this flag is
@@ -33,8 +46,26 @@ class TyperState(r: Reporter) extends DotClass with Showable {
3346
* check the ephemeral flag; If the flag is set during an operation, the result
3447
* of that operation should not be cached.
3548
*/
36-
def ephemeral: Boolean = false
37-
def ephemeral_=(x: Boolean): Unit = ()
49+
def ephemeral = myEphemeral
50+
def ephemeral_=(x: Boolean): Unit = { myEphemeral = x }
51+
52+
private var myIsCommittable = true
53+
54+
def isCommittable = myIsCommittable
55+
56+
def setCommittable(committable: Boolean): this.type = { this.myIsCommittable = committable; this }
57+
58+
def isGlobalCommittable: Boolean =
59+
isCommittable && (previous == null || previous.isGlobalCommittable)
60+
61+
private var isCommitted = false
62+
63+
/** A fresh typer state with the same constraint as this one. */
64+
def fresh(): TyperState =
65+
new TyperState(this).setReporter(new StoreReporter(reporter)).setCommittable(isCommittable)
66+
67+
/** The uninstantiated variables */
68+
def uninstVars = constraint.uninstVars
3869

3970
/** Gives for each instantiated type var that does not yet have its `inst` field
4071
* set, the instance value stored in the constraint. Storing instances in constraints
@@ -49,92 +80,33 @@ class TyperState(r: Reporter) extends DotClass with Showable {
4980
case tp => tp
5081
}
5182

52-
/** A fresh typer state with the same constraint as this one.
53-
* @param isCommittable The constraint can be committed to an enclosing context.
54-
*/
55-
def fresh(isCommittable: Boolean): TyperState = this
56-
57-
/** A fresh type state with the same constraint as this one and the given reporter */
58-
def withReporter(reporter: Reporter) = new TyperState(reporter)
59-
60-
/** Commit state so that it gets propagated to enclosing context */
61-
def commit()(implicit ctx: Context): Unit = unsupported("commit")
62-
6383
/** The closest ancestor of this typer state (including possibly this typer state itself)
6484
* which is not yet committed, or which does not have a parent.
6585
*/
66-
def uncommittedAncestor: TyperState = this
67-
68-
/** Make type variable instances permanent by assigning to `inst` field if
69-
* type variable instantiation cannot be retracted anymore. Then, remove
70-
* no-longer needed constraint entries.
71-
*/
72-
def gc()(implicit ctx: Context): Unit = ()
73-
74-
/** Is it allowed to commit this state? */
75-
def isCommittable: Boolean = false
76-
def isCommittable_=(b: Boolean) = ()
86+
def uncommittedAncestor: TyperState =
87+
if (isCommitted) previous.uncommittedAncestor else this
7788

78-
/** Can this state be transitively committed until the top-level? */
79-
def isGlobalCommittable: Boolean = false
89+
private var testReporter: StoreReporter = null
8090

8191
/** Test using `op`, restoring typerState to previous state afterwards */
82-
def test(op: => Boolean): Boolean = op
83-
84-
override def toText(printer: Printer): Text = "ImmutableTyperState"
85-
86-
/** A string showing the hashes of all nested mutable typerstates */
87-
def hashesStr: String = ""
88-
}
89-
90-
class MutableTyperState(previous: TyperState, r: Reporter, override var isCommittable: Boolean)
91-
extends TyperState(r) {
92-
93-
private var myReporter = r
94-
95-
override def reporter = myReporter
96-
97-
private val previousConstraint = previous.constraint
98-
private var myConstraint: Constraint = previousConstraint
99-
100-
override def constraint = myConstraint
101-
override def constraint_=(c: Constraint)(implicit ctx: Context) = {
102-
if (Config.debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed()
103-
myConstraint = c
104-
}
105-
106-
private var myEphemeral: Boolean = previous.ephemeral
107-
108-
override def ephemeral = myEphemeral
109-
override def ephemeral_=(x: Boolean): Unit = { myEphemeral = x }
110-
111-
override def fresh(isCommittable: Boolean): TyperState =
112-
new MutableTyperState(this, new StoreReporter(reporter), isCommittable)
113-
114-
override def withReporter(reporter: Reporter) =
115-
new MutableTyperState(this, reporter, isCommittable)
116-
117-
override val isGlobalCommittable =
118-
isCommittable &&
119-
(!previous.isInstanceOf[MutableTyperState] || previous.isGlobalCommittable)
120-
121-
private var isCommitted = false
122-
123-
override def uncommittedAncestor: TyperState =
124-
if (isCommitted) previous.uncommittedAncestor else this
125-
126-
override def test(op: => Boolean): Boolean = {
92+
def test(op: => Boolean): Boolean = {
12793
val savedReporter = myReporter
12894
val savedConstraint = myConstraint
95+
val savedCommittable = myIsCommittable
12996
val savedCommitted = isCommitted
130-
val savedCommittable = isCommittable
131-
isCommittable = false
97+
myIsCommittable = false
98+
myReporter =
99+
if (testReporter == null) new StoreReporter(reporter)
100+
else {
101+
testReporter.reset()
102+
testReporter
103+
}
132104
try op
133105
finally {
134106
myReporter = savedReporter
135107
myConstraint = savedConstraint
108+
myIsCommittable = savedCommittable
136109
isCommitted = savedCommitted
137-
isCommittable = savedCommittable
138110
}
139111
}
140112

@@ -156,7 +128,7 @@ extends TyperState(r) {
156128
* isApplicableSafe but also for (e.g. erased-lubs.scala) as well as
157129
* many parts of dotty itself.
158130
*/
159-
override def commit()(implicit ctx: Context) = {
131+
def commit()(implicit ctx: Context) = {
160132
val targetState = ctx.typerState
161133
assert(isCommittable)
162134
targetState.constraint =
@@ -171,7 +143,11 @@ extends TyperState(r) {
171143
isCommitted = true
172144
}
173145

174-
override def gc()(implicit ctx: Context): Unit = {
146+
/** Make type variable instances permanent by assigning to `inst` field if
147+
* type variable instantiation cannot be retracted anymore. Then, remove
148+
* no-longer needed constraint entries.
149+
*/
150+
def gc()(implicit ctx: Context): Unit = {
175151
val toCollect = new mutable.ListBuffer[TypeLambda]
176152
constraint foreachTypeVar { tvar =>
177153
if (!tvar.inst.exists) {
@@ -189,6 +165,5 @@ extends TyperState(r) {
189165

190166
override def toText(printer: Printer): Text = constraint.toText(printer)
191167

192-
override def hashesStr: String = hashCode.toString + " -> " + previous.hashesStr
193-
168+
def hashesStr: String = hashCode.toString + " -> " + previous.hashesStr
194169
}

compiler/src/dotty/tools/dotc/reporting/StoreReporter.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ class StoreReporter(outer: Reporter) extends Reporter {
2222

2323
private var infos: mutable.ListBuffer[MessageContainer] = null
2424

25+
def reset() = infos = null
26+
2527
def doReport(m: MessageContainer)(implicit ctx: Context): Unit = {
2628
typr.println(s">>>> StoredError: ${m.message}") // !!! DEBUG
2729
if (infos == null) infos = new mutable.ListBuffer

0 commit comments

Comments
 (0)