@@ -13,18 +13,31 @@ import config.Config
13
13
import collection .mutable
14
14
import java .lang .ref .WeakReference
15
15
16
- class TyperState (r : Reporter ) extends DotClass with Showable {
16
+ class TyperState (previous : TyperState /* | Null */ ) extends DotClass with Showable {
17
17
18
- /** The current reporter */
19
- def reporter = r
18
+ private var myReporter =
19
+ if (previous == null ) new ConsoleReporter () else previous.reporter
20
20
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
25
22
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
28
41
29
42
/** The ephemeral flag is set as a side effect if an operation accesses
30
43
* 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 {
33
46
* check the ephemeral flag; If the flag is set during an operation, the result
34
47
* of that operation should not be cached.
35
48
*/
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
38
69
39
70
/** Gives for each instantiated type var that does not yet have its `inst` field
40
71
* set, the instance value stored in the constraint. Storing instances in constraints
@@ -49,76 +80,36 @@ class TyperState(r: Reporter) extends DotClass with Showable {
49
80
case tp => tp
50
81
}
51
82
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
-
63
83
/** The closest ancestor of this typer state (including possibly this typer state itself)
64
84
* which is not yet committed, or which does not have a parent.
65
85
*/
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
-
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
86
+ def uncommittedAncestor : TyperState =
87
+ if (isCommitted) previous.uncommittedAncestor else this
95
88
96
- override def constraint = myConstraint
97
- override def constraint_= (c : Constraint )(implicit ctx : Context ) = {
98
- if (Config .debugCheckConstraintsClosed && isGlobalCommittable) c.checkClosed()
99
- myConstraint = c
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
+ }
100
111
}
101
112
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
-
122
113
/** Commit typer state so that its information is copied into current typer state
123
114
* In addition (1) the owning state of undetermined or temporarily instantiated
124
115
* type variables changes from this typer state to the current one. (2) Variables
@@ -137,7 +128,7 @@ extends TyperState(r) {
137
128
* isApplicableSafe but also for (e.g. erased-lubs.scala) as well as
138
129
* many parts of dotty itself.
139
130
*/
140
- override def commit ()(implicit ctx : Context ) = {
131
+ def commit ()(implicit ctx : Context ) = {
141
132
val targetState = ctx.typerState
142
133
assert(isCommittable)
143
134
targetState.constraint =
@@ -152,7 +143,11 @@ extends TyperState(r) {
152
143
isCommitted = true
153
144
}
154
145
155
- 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 = {
156
151
val toCollect = new mutable.ListBuffer [TypeLambda ]
157
152
constraint foreachTypeVar { tvar =>
158
153
if (! tvar.inst.exists) {
@@ -170,6 +165,5 @@ extends TyperState(r) {
170
165
171
166
override def toText (printer : Printer ): Text = constraint.toText(printer)
172
167
173
- override def hashesStr : String = hashCode.toString + " -> " + previous.hashesStr
174
-
168
+ def hashesStr : String = hashCode.toString + " -> " + previous.hashesStr
175
169
}
0 commit comments