@@ -48,134 +48,6 @@ class IllegalCaptureRef(tpe: Type)(using Context) extends Exception(tpe.show)
4848/** A base trait for data producing addenda to error messages */
4949trait ErrorNote
5050
51- /** Capture checking state, which is known to other capture checking components */
52- class CCState :
53-
54- /** Error reprting notes produces since the last call to `test` */
55- var notes : List [ErrorNote ] = Nil
56-
57- def addNote (note : ErrorNote ): Unit =
58- if ! notes.exists(_.getClass == note.getClass) then
59- notes = note :: notes
60-
61- def test (op : => CompareResult ): CompareResult =
62- val saved = notes
63- notes = Nil
64- try op match
65- case res : CompareFailure => res.withNotes(notes)
66- case res => res
67- finally notes = saved
68-
69- def testOK (op : => Boolean ): CompareResult =
70- test(if op then CompareResult .OK else CompareResult .Fail (Nil ))
71-
72- /** Warnings relating to upper approximations of capture sets with
73- * existentially bound variables.
74- */
75- val approxWarnings : mutable.ListBuffer [Message ] = mutable.ListBuffer ()
76-
77- private var curLevel : Level = outermostLevel
78- private val symLevel : mutable.Map [Symbol , Int ] = mutable.Map ()
79-
80- private var openExistentialScopes : List [MethodType ] = Nil
81-
82- private var capIsRoot : Boolean = false
83-
84- /** If true, apply a BiTypeMap also to elements added to the set in the future
85- * (and use its inverse when back-progating).
86- */
87- private var mapFutureElems = true
88-
89- var iterCount = 1
90-
91- object CCState :
92-
93- opaque type Level = Int
94-
95- val undefinedLevel : Level = - 1
96-
97- val outermostLevel : Level = 0
98-
99- /** The level of the current environment. Levels start at 0 and increase for
100- * each nested function or class. -1 means the level is undefined.
101- */
102- def currentLevel (using Context ): Level = ccState.curLevel
103-
104- /** Perform `op` in the next inner level
105- * @pre We are currently in capture checking or setup
106- */
107- inline def inNestedLevel [T ](inline op : T )(using Context ): T =
108- val ccs = ccState
109- val saved = ccs.curLevel
110- ccs.curLevel = ccs.curLevel.nextInner
111- try op finally ccs.curLevel = saved
112-
113- /** Perform `op` in the next inner level unless `p` holds.
114- * @pre We are currently in capture checking or setup
115- */
116- inline def inNestedLevelUnless [T ](inline p : Boolean )(inline op : T )(using Context ): T =
117- val ccs = ccState
118- val saved = ccs.curLevel
119- if ! p then ccs.curLevel = ccs.curLevel.nextInner
120- try op finally ccs.curLevel = saved
121-
122- /** If we are currently in capture checking or setup, and `mt` is a method
123- * type that is not a prefix of a curried method, perform `op` assuming
124- * a fresh enclosing existential scope `mt`, otherwise perform `op` directly.
125- */
126- inline def inNewExistentialScope [T ](mt : MethodType )(op : => T )(using Context ): T =
127- if isCaptureCheckingOrSetup then
128- val ccs = ccState
129- val saved = ccs.openExistentialScopes
130- if mt.marksExistentialScope then ccs.openExistentialScopes = mt :: ccs.openExistentialScopes
131- try op finally ccs.openExistentialScopes = saved
132- else
133- op
134-
135- /** Run `op` under the assumption that `cap` can subsume all other capabilties
136- * except Result capabilities. Every use of this method should be scrutinized
137- * for whether it introduces an unsoundness hole.
138- */
139- inline def withCapAsRoot [T ](op : => T )(using Context ): T =
140- if isCaptureCheckingOrSetup then
141- val ccs = ccState
142- val saved = ccs.capIsRoot
143- ccs.capIsRoot = true
144- try op finally ccs.capIsRoot = saved
145- else op
146-
147- /** Don't map future elements in this `op` */
148- inline def withoutMappedFutureElems [T ](op : => T )(using Context ): T =
149- val ccs = ccState
150- val saved = ccs.mapFutureElems
151- ccs.mapFutureElems = false
152- try op finally ccs.mapFutureElems = saved
153-
154- /** Is `caps.cap` a root capability that is allowed to subsume other capabilities? */
155- def capIsRoot (using Context ): Boolean = ccState.capIsRoot
156-
157- /** When mapping a capture set with a BiTypeMap, should we create a BiMapped set
158- * so that future elements can also be mapped, and elements added to the BiMapped
159- * are back-propagated? Turned off when creating capture set variables for the
160- * first time, since we then do not want to change the binder to the original type
161- * without capture sets when back propagating. Error case where this shows:
162- * pos-customargs/captures/lists.scala, method m2c.
163- */
164- def mapFutureElems (using Context ) = ccState.mapFutureElems
165-
166- /** The currently opened existential scopes */
167- def openExistentialScopes (using Context ): List [MethodType ] = ccState.openExistentialScopes
168-
169- extension (x : Level )
170- def isDefined : Boolean = x >= 0
171- def <= (y : Level ) = (x : Int ) <= y
172- def nextInner : Level = if isDefined then x + 1 else x
173-
174- extension (sym : Symbol )(using Context )
175- def ccLevel : Level = ccState.symLevel.getOrElse(sym, - 1 )
176- def recordLevel () = ccState.symLevel(sym) = currentLevel
177- end CCState
178-
17951/** The currently valid CCState */
18052def ccState (using Context ): CCState =
18153 Phases .checkCapturesPhase.asInstanceOf [CheckCaptures ].ccState1
@@ -631,8 +503,8 @@ extension (tp: Type)
631503
632504 def level (using Context ): Level =
633505 tp match
634- case tp : TermRef => tp.symbol.ccLevel
635- case tp : ThisType => tp.cls.ccLevel .nextInner
506+ case tp : TermRef => ccState.symLevel( tp.symbol)
507+ case tp : ThisType => ccState.symLevel( tp.cls) .nextInner
636508 case _ => undefinedLevel
637509
638510extension (tp : MethodType )
0 commit comments