Skip to content

Commit a3c12b4

Browse files
authored
Revert "Avoid exploring TyperState creations"
1 parent fe60cc1 commit a3c12b4

File tree

9 files changed

+137
-124
lines changed

9 files changed

+137
-124
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 TyperState(ctx.typerState))
52+
.setTyperState(new MutableTyperState(ctx.typerState, ctx.typerState.reporter, isCommittable = true))
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
@@ -459,9 +459,9 @@ object Contexts {
459459
def setCompilerCallback(callback: CompilerCallback): this.type = { this.compilerCallback = callback; this }
460460
def setSbtCallback(callback: AnalysisCallback): this.type = { this.sbtCallback = callback; this }
461461
def setTyperState(typerState: TyperState): this.type = { this.typerState = typerState; this }
462-
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.fresh().setReporter(reporter))
463-
def setNewTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(true))
464-
def setExploreTyperState(): this.type = setTyperState(typerState.fresh().setCommittable(false))
462+
def setReporter(reporter: Reporter): this.type = setTyperState(typerState.withReporter(reporter))
463+
def setNewTyperState: this.type = setTyperState(typerState.fresh(isCommittable = true))
464+
def setExploreTyperState: this.type = setTyperState(typerState.fresh(isCommittable = false))
465465
def setPrinterFn(printer: Context => Printer): this.type = { this.printerFn = printer; this }
466466
def setOwner(owner: Symbol): this.type = { assert(owner != NoSymbol); this.owner = owner; this }
467467
def setSettings(sstate: SettingsState): this.type = { this.sstate = sstate; this }
@@ -520,7 +520,7 @@ object Contexts {
520520
outer = NoContext
521521
period = InitialPeriod
522522
mode = Mode.None
523-
typerState = new TyperState(null)
523+
typerState = new TyperState(new ConsoleReporter())
524524
printerFn = new RefinedPrinter(_)
525525
owner = NoSymbol
526526
sstate = settings.defaultState

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

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

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

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

21-
def reporter: Reporter = myReporter
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 = {}
2225

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
26+
/** The uninstantiated variables */
27+
def uninstVars = constraint.uninstVars
4128

4229
/** The ephemeral flag is set as a side effect if an operation accesses
4330
* the underlying type of a type variable. The reason we need this flag is
@@ -46,26 +33,8 @@ class TyperState(previous: TyperState /* | Null */) extends DotClass with Showab
4633
* check the ephemeral flag; If the flag is set during an operation, the result
4734
* of that operation should not be cached.
4835
*/
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
36+
def ephemeral: Boolean = false
37+
def ephemeral_=(x: Boolean): Unit = ()
6938

7039
/** Gives for each instantiated type var that does not yet have its `inst` field
7140
* set, the instance value stored in the constraint. Storing instances in constraints
@@ -80,36 +49,76 @@ class TyperState(previous: TyperState /* | Null */) extends DotClass with Showab
8049
case tp => tp
8150
}
8251

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+
8363
/** The closest ancestor of this typer state (including possibly this typer state itself)
8464
* which is not yet committed, or which does not have a parent.
8565
*/
86-
def uncommittedAncestor: TyperState =
87-
if (isCommitted) previous.uncommittedAncestor else this
66+
def uncommittedAncestor: TyperState = this
8867

89-
private var testReporter: StoreReporter = null
90-
91-
/** Test using `op`, restoring typerState to previous state afterwards */
92-
def test(op: => Boolean): Boolean = {
93-
val savedReporter = myReporter
94-
val savedConstraint = myConstraint
95-
val savedCommittable = myIsCommittable
96-
val savedCommitted = isCommitted
97-
myIsCommittable = false
98-
myReporter =
99-
if (testReporter == null) new StoreReporter(reporter)
100-
else {
101-
testReporter.reset()
102-
testReporter
103-
}
104-
try op
105-
finally {
106-
myReporter = savedReporter
107-
myConstraint = savedConstraint
108-
myIsCommittable = savedCommittable
109-
isCommitted = savedCommitted
110-
}
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+
77+
/** Can this state be transitively committed until the top-level? */
78+
def isGlobalCommittable: Boolean = false
79+
80+
override def toText(printer: Printer): Text = "ImmutableTyperState"
81+
82+
/** A string showing the hashes of all nested mutable typerstates */
83+
def hashesStr: String = ""
84+
}
85+
86+
class MutableTyperState(previous: TyperState, r: Reporter, override val isCommittable: Boolean)
87+
extends TyperState(r) {
88+
89+
private var myReporter = r
90+
91+
override def reporter = myReporter
92+
93+
private val previousConstraint = previous.constraint
94+
private var myConstraint: Constraint = previousConstraint
95+
96+
override def constraint = myConstraint
97+
override def constraint_=(c: Constraint)(implicit ctx: Context) = {
98+
if (Config.debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed()
99+
myConstraint = c
111100
}
112101

102+
private var myEphemeral: Boolean = previous.ephemeral
103+
104+
override def ephemeral = myEphemeral
105+
override def ephemeral_=(x: Boolean): Unit = { myEphemeral = x }
106+
107+
override def fresh(isCommittable: Boolean): TyperState =
108+
new MutableTyperState(this, new StoreReporter(reporter), isCommittable)
109+
110+
override def withReporter(reporter: Reporter) =
111+
new MutableTyperState(this, reporter, isCommittable)
112+
113+
override val isGlobalCommittable =
114+
isCommittable &&
115+
(!previous.isInstanceOf[MutableTyperState] || previous.isGlobalCommittable)
116+
117+
private var isCommitted = false
118+
119+
override def uncommittedAncestor: TyperState =
120+
if (isCommitted) previous.uncommittedAncestor else this
121+
113122
/** Commit typer state so that its information is copied into current typer state
114123
* In addition (1) the owning state of undetermined or temporarily instantiated
115124
* type variables changes from this typer state to the current one. (2) Variables
@@ -128,7 +137,7 @@ class TyperState(previous: TyperState /* | Null */) extends DotClass with Showab
128137
* isApplicableSafe but also for (e.g. erased-lubs.scala) as well as
129138
* many parts of dotty itself.
130139
*/
131-
def commit()(implicit ctx: Context) = {
140+
override def commit()(implicit ctx: Context) = {
132141
val targetState = ctx.typerState
133142
assert(isCommittable)
134143
targetState.constraint =
@@ -143,11 +152,7 @@ class TyperState(previous: TyperState /* | Null */) extends DotClass with Showab
143152
isCommitted = true
144153
}
145154

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 = {
155+
override def gc()(implicit ctx: Context): Unit = {
151156
val toCollect = new mutable.ListBuffer[TypeLambda]
152157
constraint foreachTypeVar { tvar =>
153158
if (!tvar.inst.exists) {
@@ -165,5 +170,6 @@ class TyperState(previous: TyperState /* | Null */) extends DotClass with Showab
165170

166171
override def toText(printer: Printer): Text = constraint.toText(printer)
167172

168-
def hashesStr: String = hashCode.toString + " -> " + previous.hashesStr
173+
override def hashesStr: String = hashCode.toString + " -> " + previous.hashesStr
174+
169175
}

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

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

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

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

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

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -847,7 +847,7 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
847847
def followTypeAlias(tree: untpd.Tree): untpd.Tree = {
848848
tree match {
849849
case tree: untpd.RefTree =>
850-
val nestedCtx = ctx.fresh.setNewTyperState()
850+
val nestedCtx = ctx.fresh.setNewTyperState
851851
val ttree =
852852
typedType(untpd.rename(tree, tree.name.toTypeName))(nestedCtx)
853853
ttree.tpe match {
@@ -1002,20 +1002,26 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
10021002
/** Is given method reference applicable to type arguments `targs` and argument trees `args`?
10031003
* @param resultType The expected result type of the application
10041004
*/
1005-
def isApplicable(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean =
1006-
ctx.typerState.test(new ApplicableToTrees(methRef, targs, args, resultType).success)
1005+
def isApplicable(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean = {
1006+
val nestedContext = ctx.fresh.setExploreTyperState
1007+
new ApplicableToTrees(methRef, targs, args, resultType)(nestedContext).success
1008+
}
10071009

10081010
/** Is given method reference applicable to type arguments `targs` and argument trees `args` without inferring views?
10091011
* @param resultType The expected result type of the application
10101012
*/
1011-
def isDirectlyApplicable(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean =
1012-
ctx.typerState.test(new ApplicableToTreesDirectly(methRef, targs, args, resultType).success)
1013+
def isDirectlyApplicable(methRef: TermRef, targs: List[Type], args: List[Tree], resultType: Type)(implicit ctx: Context): Boolean = {
1014+
val nestedContext = ctx.fresh.setExploreTyperState
1015+
new ApplicableToTreesDirectly(methRef, targs, args, resultType)(nestedContext).success
1016+
}
10131017

10141018
/** Is given method reference applicable to argument types `args`?
10151019
* @param resultType The expected result type of the application
10161020
*/
1017-
def isApplicable(methRef: TermRef, args: List[Type], resultType: Type)(implicit ctx: Context): Boolean =
1018-
ctx.typerState.test(new ApplicableToTypes(methRef, args, resultType).success)
1021+
def isApplicable(methRef: TermRef, args: List[Type], resultType: Type)(implicit ctx: Context): Boolean = {
1022+
val nestedContext = ctx.fresh.setExploreTyperState
1023+
new ApplicableToTypes(methRef, args, resultType)(nestedContext).success
1024+
}
10191025

10201026
/** Is given type applicable to type arguments `targs` and argument trees `args`,
10211027
* possibly after inserting an `apply`?
@@ -1096,7 +1102,12 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
10961102
case tp2: MethodType => true // (3a)
10971103
case tp2: PolyType if tp2.resultType.isInstanceOf[MethodType] => true // (3a)
10981104
case tp2: PolyType => // (3b)
1099-
ctx.typerState.test(isAsSpecificValueType(tp1, constrained(tp2).resultType))
1105+
val nestedCtx = ctx.fresh.setExploreTyperState
1106+
1107+
{
1108+
implicit val ctx = nestedCtx
1109+
isAsSpecificValueType(tp1, constrained(tp2).resultType)
1110+
}
11001111
case _ => // (3b)
11011112
isAsSpecificValueType(tp1, tp2)
11021113
}
@@ -1246,20 +1257,22 @@ trait Applications extends Compatibility { self: Typer with Dynamic =>
12461257
* probability of pruning the search. result type comparisons are neither cheap nor
12471258
* do they prune much, on average.
12481259
*/
1249-
def adaptByResult(chosen: TermRef) = pt match {
1250-
case pt: FunProto if !ctx.typerState.test(resultConforms(chosen, pt.resultType)) =>
1251-
val conformingAlts = alts.filter(alt =>
1252-
(alt ne chosen) && ctx.typerState.test(resultConforms(alt, pt.resultType)))
1253-
conformingAlts match {
1254-
case Nil => chosen
1255-
case alt2 :: Nil => alt2
1256-
case alts2 =>
1257-
resolveOverloaded(alts2, pt) match {
1258-
case alt2 :: Nil => alt2
1259-
case _ => chosen
1260-
}
1261-
}
1262-
case _ => chosen
1260+
def adaptByResult(chosen: TermRef) = {
1261+
def nestedCtx = ctx.fresh.setExploreTyperState
1262+
pt match {
1263+
case pt: FunProto if !resultConforms(chosen, pt.resultType)(nestedCtx) =>
1264+
alts.filter(alt =>
1265+
(alt ne chosen) && resultConforms(alt, pt.resultType)(nestedCtx)) match {
1266+
case Nil => chosen
1267+
case alt2 :: Nil => alt2
1268+
case alts2 =>
1269+
resolveOverloaded(alts2, pt) match {
1270+
case alt2 :: Nil => alt2
1271+
case _ => chosen
1272+
}
1273+
}
1274+
case _ => chosen
1275+
}
12631276
}
12641277

12651278
var found = resolveOverloaded(alts, pt, Nil)(ctx.retractMode(Mode.ImplicitsEnabled))

0 commit comments

Comments
 (0)