@@ -10,7 +10,7 @@ import config.Config
1010import config .Printers .constr
1111import collection .mutable
1212import java .lang .ref .WeakReference
13- import util .Stats
13+ import util .{ Stats , SimpleIdentityMap }
1414import Decorators ._
1515
1616import scala .annotation .internal .sharable
@@ -23,24 +23,28 @@ object TyperState {
2323 .setReporter(new ConsoleReporter ())
2424 .setCommittable(true )
2525
26- opaque type Snapshot = (Constraint , TypeVars , TypeVars )
26+ type LevelMap = SimpleIdentityMap [TypeVar , Integer ]
27+
28+ opaque type Snapshot = (Constraint , TypeVars , TypeVars , LevelMap )
2729
2830 extension (ts : TyperState )
2931 def snapshot ()(using Context ): Snapshot =
3032 var previouslyInstantiated : TypeVars = SimpleIdentitySet .empty
3133 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 )
3335
3436 def resetTo (state : Snapshot )(using Context ): Unit =
35- val (c, tvs, previouslyInstantiated) = state
37+ val (c, tvs, previouslyInstantiated, upLevels ) = state
3638 for tv <- tvs do
3739 if tv.inst.exists && ! previouslyInstantiated.contains(tv) then
3840 tv.resetInst(ts)
3941 ts.ownedVars = tvs
4042 ts.constraint = c
43+ ts.upLevels = upLevels
4144}
4245
4346class TyperState () {
47+ import TyperState .LevelMap
4448
4549 private var myId : Int = _
4650 def id : Int = myId
@@ -89,6 +93,8 @@ class TyperState() {
8993 def ownedVars : TypeVars = myOwnedVars
9094 def ownedVars_= (vs : TypeVars ): Unit = myOwnedVars = vs
9195
96+ private var upLevels : LevelMap = _
97+
9298 /** Initializes all fields except reporter, isCommittable, which need to be
9399 * set separately.
94100 */
@@ -99,20 +105,35 @@ class TyperState() {
99105 this .myConstraint = constraint
100106 this .previousConstraint = constraint
101107 this .myOwnedVars = SimpleIdentitySet .empty
108+ this .upLevels = SimpleIdentityMap .empty
102109 this .isCommitted = false
103110 this
104111
105112 /** A fresh typer state with the same constraint as this one. */
106113 def fresh (reporter : Reporter = StoreReporter (this .reporter, fromTyperState = true ),
107114 committable : Boolean = this .isCommittable): TyperState =
108115 util.Stats .record(" TyperState.fresh" )
109- TyperState ().init(this , this .constraint)
116+ val ts = TyperState ().init(this , this .constraint)
110117 .setReporter(reporter)
111118 .setCommittable(committable)
119+ ts.upLevels = upLevels
120+ ts
112121
113122 /** The uninstantiated variables */
114123 def uninstVars : collection.Seq [TypeVar ] = constraint.uninstVars
115124
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+
116137 /** The closest ancestor of this typer state (including possibly this typer state itself)
117138 * which is not yet committed, or which does not have a parent.
118139 */
@@ -164,6 +185,12 @@ class TyperState() {
164185 if ! ownedVars.isEmpty then ownedVars.foreach(targetState.includeVar)
165186 else
166187 targetState.mergeConstraintWith(this )
188+
189+ upLevels.foreachBinding { (tv, level) =>
190+ if level < targetState.nestingLevel(tv) then
191+ targetState.setNestingLevel(tv, level)
192+ }
193+
167194 targetState.gc()
168195 isCommitted = true
169196 ownedVars = SimpleIdentitySet .empty
0 commit comments