1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
|
package dotty.tools
package dotc
package core
import Types._
import Flags._
import Contexts._
import util.SimpleMap
import reporting._
import printing.{Showable, Printer}
import printing.Texts._
import collection.mutable
import annotation.elidable
class TyperState(val reporter: Reporter) extends DotClass with Showable {
/** The current constraint set */
def constraint: Constraint = new Constraint(SimpleMap.Empty)
def uninstVars = constraint.uninstVars
/** A map that records for instantiated type vars their instance type.
* Used only in a temporary way for contexts that may be retracted
* without also retracting the type var as a whole.
*/
def instType(tvar: TypeVar): Type = constraint.at(tvar.origin) match {
case _: TypeBounds => NoType
case tp => tp
}
def constraint_=(c: Constraint): Unit = {}
def fresh(isCommittable: Boolean): TyperState = this
def commit()(implicit ctx: Context): Unit = unsupported("commit")
def isCommittable: Boolean = false
@elidable(elidable.FINER)
def checkConsistent(implicit ctx: Context) = ()
@elidable(elidable.FINER)
def enableChecking(b: Boolean): Boolean = true
def withCheckingDisabled[T](op: => T)(implicit ctx: Context): T = op
override def toText(printer: Printer): Text = "ImmutableTyperState"
}
class MutableTyperState(previous: TyperState, reporter: Reporter, override val isCommittable: Boolean)
extends TyperState(reporter) {
private var myConstraint: Constraint = previous.constraint
private var checkingEnabled: Boolean = true
override def constraint = myConstraint
override def constraint_=(c: Constraint) = {
myConstraint = c
checkConsistent()
}
override def fresh(isCommittable: Boolean): TyperState =
new MutableTyperState(this, new StoreReporter, isCommittable)
/** Commit typer state so that its information is copied into current typer state
* In addition (1) the owning state of undetermined or temporarily instantiated
* type variables changes from this typer state to the current one. (2) Variables
* that were temporarily instantiated in the current typer state are permanently
* instantiated instead.
*/
override def commit()(implicit ctx: Context) = {
checkConsistent
val targetState = ctx.typerState
val prev = targetState.enableChecking(false)
targetState.constraint = constraint
targetState.enableChecking(prev)
val toCollect = new mutable.ListBuffer[PolyType]
constraint foreachTypeVar { tvar =>
if (tvar.owningState eq this)
tvar.owningState = targetState
if (!tvar.inst.exists) {
val inst = instType(tvar)
if (inst.exists && (tvar.owningState eq targetState)) {
tvar.inst = inst
val poly = tvar.origin.binder
if (targetState.constraint.isRemovable(poly)) toCollect += poly
}
}
}
for (poly <- toCollect)
targetState.constraint = targetState.constraint.remove(poly)
targetState.checkConsistent // !!! DEBUG
reporter.flush()
}
@elidable(elidable.FINER)
def checkConsistent(show: Showable => String = MutableTyperState.toStr): Unit = if (checkingEnabled) {
def err(msg: String, what: Showable) = s"$msg: ${show(what)}\n${show(this)}"
for (tvar <- uninstVars)
assert(constraint contains tvar.origin, err("unconstrained type var", tvar.origin))
if (isCommittable) {
val undetParams = uninstVars map (_.origin)
for (param <- constraint.domainParams)
assert(undetParams contains param, err("junk constraint on", param))
}
}
@elidable(elidable.FINER)
override def checkConsistent(implicit ctx: Context): Unit = checkConsistent(_.show)
@elidable(elidable.FINER)
override def enableChecking(b: Boolean) = {
val prev = checkingEnabled
checkingEnabled = b
prev
}
override def withCheckingDisabled[T](op: => T)(implicit ctx: Context): T = {
val prev = enableChecking(false)
var thrown = false
try op
catch {
case ex: Throwable =>
thrown = true
throw ex
}
finally {
enableChecking(prev)
if (!thrown) checkConsistent
}
}
override def toText(printer: Printer): Text = {
val header: Text = "Typer state:"
val uninstVarsText =
" uninstVars: " ~
Text(uninstVars map (_.toText(printer)), ", ") ~ "."
val constrainedText =
" constrained types: " ~ constraint.constrainedTypesText(printer) ~ "."
val constraintText =
" constraint: " ~ constraint.constraintText(3, printer)
Text.lines(List(header, uninstVarsText, constrainedText, constraintText))
}
}
object MutableTyperState {
private def toStr(x: Any) = x.toString
}
|