@@ -10,7 +10,7 @@ import config.Config
10
10
import config .Printers .constr
11
11
import collection .mutable
12
12
import java .lang .ref .WeakReference
13
- import util .Stats
13
+ import util .{ Stats , SimpleIdentityMap }
14
14
import Decorators ._
15
15
16
16
import scala .annotation .internal .sharable
@@ -23,24 +23,28 @@ object TyperState {
23
23
.setReporter(new ConsoleReporter ())
24
24
.setCommittable(true )
25
25
26
- opaque type Snapshot = (Constraint , TypeVars , TypeVars )
26
+ type LevelMap = SimpleIdentityMap [TypeVar , Integer ]
27
+
28
+ opaque type Snapshot = (Constraint , TypeVars , TypeVars , LevelMap )
27
29
28
30
extension (ts : TyperState )
29
31
def snapshot ()(using Context ): Snapshot =
30
32
var previouslyInstantiated : TypeVars = SimpleIdentitySet .empty
31
33
for tv <- ts.ownedVars do if tv.inst.exists then previouslyInstantiated += tv
32
- (ts.constraint, ts.ownedVars, previouslyInstantiated)
34
+ (ts.constraint, ts.ownedVars, previouslyInstantiated, ts.upLevels )
33
35
34
36
def resetTo (state : Snapshot )(using Context ): Unit =
35
- val (c, tvs, previouslyInstantiated) = state
37
+ val (c, tvs, previouslyInstantiated, upLevels ) = state
36
38
for tv <- tvs do
37
39
if tv.inst.exists && ! previouslyInstantiated.contains(tv) then
38
40
tv.resetInst(ts)
39
41
ts.ownedVars = tvs
40
42
ts.constraint = c
43
+ ts.upLevels = upLevels
41
44
}
42
45
43
46
class TyperState () {
47
+ import TyperState .LevelMap
44
48
45
49
private var myId : Int = _
46
50
def id : Int = myId
@@ -89,6 +93,8 @@ class TyperState() {
89
93
def ownedVars : TypeVars = myOwnedVars
90
94
def ownedVars_= (vs : TypeVars ): Unit = myOwnedVars = vs
91
95
96
+ private var upLevels : LevelMap = _
97
+
92
98
/** Initializes all fields except reporter, isCommittable, which need to be
93
99
* set separately.
94
100
*/
@@ -99,20 +105,35 @@ class TyperState() {
99
105
this .myConstraint = constraint
100
106
this .previousConstraint = constraint
101
107
this .myOwnedVars = SimpleIdentitySet .empty
108
+ this .upLevels = SimpleIdentityMap .empty
102
109
this .isCommitted = false
103
110
this
104
111
105
112
/** A fresh typer state with the same constraint as this one. */
106
113
def fresh (reporter : Reporter = StoreReporter (this .reporter, fromTyperState = true ),
107
114
committable : Boolean = this .isCommittable): TyperState =
108
115
util.Stats .record(" TyperState.fresh" )
109
- TyperState ().init(this , this .constraint)
116
+ val ts = TyperState ().init(this , this .constraint)
110
117
.setReporter(reporter)
111
118
.setCommittable(committable)
119
+ ts.upLevels = upLevels
120
+ ts
112
121
113
122
/** The uninstantiated variables */
114
123
def uninstVars : collection.Seq [TypeVar ] = constraint.uninstVars
115
124
125
+ /** The nestingLevel of `tv` in this typer state */
126
+ def nestingLevel (tv : TypeVar ): Int =
127
+ val own = upLevels(tv)
128
+ if own == null then tv.initNestingLevel else own.intValue()
129
+
130
+ /** Set the nestingLevel of `tv` in this typer state
131
+ * @pre this level must be smaller than `tv.initNestingLevel`
132
+ */
133
+ def setNestingLevel (tv : TypeVar , level : Int ) =
134
+ assert(level < tv.initNestingLevel)
135
+ upLevels = upLevels.updated(tv, level)
136
+
116
137
/** The closest ancestor of this typer state (including possibly this typer state itself)
117
138
* which is not yet committed, or which does not have a parent.
118
139
*/
@@ -164,6 +185,12 @@ class TyperState() {
164
185
if ! ownedVars.isEmpty then ownedVars.foreach(targetState.includeVar)
165
186
else
166
187
targetState.mergeConstraintWith(this )
188
+
189
+ upLevels.foreachBinding { (tv, level) =>
190
+ if level < targetState.nestingLevel(tv) then
191
+ targetState.setNestingLevel(tv, level)
192
+ }
193
+
167
194
targetState.gc()
168
195
isCommitted = true
169
196
ownedVars = SimpleIdentitySet .empty
0 commit comments