@@ -115,6 +115,7 @@ sealed abstract class CaptureSet extends Showable:
115
115
case Nil =>
116
116
addSuper(that)
117
117
recur(elems.toList)
118
+ .showing(i " subcaptures $this <:< $that = ${result.show}" , capt)
118
119
119
120
def =:= (that : CaptureSet )(using Context ): Boolean =
120
121
this .subCaptures(that, frozen = true ) == CompareResult .OK
@@ -180,7 +181,9 @@ sealed abstract class CaptureSet extends Showable:
180
181
* The upper approximation is meaningful only if it is constant. If not,
181
182
* `upperApprox` can return an arbitrary capture set variable.
182
183
*/
183
- def upperApprox (using Context ): CaptureSet
184
+ protected def upperApprox (origin : CaptureSet )(using Context ): CaptureSet
185
+
186
+ protected def propagateSolved ()(using Context ): Unit = ()
184
187
185
188
def toRetainsTypeArg (using Context ): Type =
186
189
assert(isConst)
@@ -230,7 +233,7 @@ object CaptureSet:
230
233
231
234
def addSuper (cs : CaptureSet )(using Context , VarState ) = CompareResult .OK
232
235
233
- def upperApprox (using Context ): CaptureSet = this
236
+ def upperApprox (origin : CaptureSet )( using Context ): CaptureSet = this
234
237
235
238
override def toString = elems.toString
236
239
end Const
@@ -284,32 +287,52 @@ object CaptureSet:
284
287
else
285
288
CompareResult .fail(this )
286
289
287
- def upperApprox (using Context ): CaptureSet =
290
+ def upperApprox (origin : CaptureSet )( using Context ): CaptureSet =
288
291
if isConst then this
289
292
else (universal /: deps) { (acc, sup) =>
290
- if acc.isConst then
291
- val supApprox = sup.upperApprox
292
- if supApprox.isConst then acc ** supApprox else supApprox
293
- else acc
293
+ assert( acc.isConst)
294
+ val supApprox = sup.upperApprox( this )
295
+ assert( supApprox.isConst)
296
+ acc ** supApprox
294
297
}
295
298
296
299
def solve (variance : Int )(using Context ): Unit =
297
- if variance < 0 then
298
- val approx = upperApprox
300
+ if variance < 0 && ! isConst then
301
+ val approx = upperApprox(empty)
302
+ // println(i"solving var $this $approx ${approx.isConst} deps = ${deps.toList}")
299
303
if approx.isConst then
300
- elems = approx.elems
301
- isSolved = true
304
+ val newElems = approx.elems -- elems
305
+ if newElems.isEmpty
306
+ || addNewElems(newElems, empty)(using ctx, VarState ()) == CompareResult .OK then
307
+ markSolved()
308
+
309
+ def markSolved ()(using Context ): Unit =
310
+ isSolved = true
311
+ deps.foreach(_.propagateSolved())
312
+
313
+ override def toText (printer : Printer ): Text =
314
+ super .toText(printer)
315
+ ~ (id.toString ~ getClass.getSimpleName.take(1 ) provided ! isConst)
302
316
303
317
override def toString = s " Var $id$elems"
304
318
end Var
305
319
306
- /** A variable that changes when `cv` changes, where all additional new elements are mapped
320
+ abstract class DerivedVar (initialElems : Refs )(using @ constructorOnly ctx : Context )
321
+ extends Var (initialElems):
322
+ def source : Var
323
+
324
+ addSub(source)
325
+
326
+ override def propagateSolved ()(using Context ) =
327
+ if source.isConst && ! isConst then markSolved()
328
+ end DerivedVar
329
+
330
+ /** A variable that changes when `source` changes, where all additional new elements are mapped
307
331
* using ∪ { f(x) | x <- elems }
308
332
*/
309
- class Mapped private [CaptureSet ] (
310
- cv : Var , tm : TypeMap , variance : Int , initial : CaptureSet
311
- )(using @ constructorOnly ctx : Context ) extends Var (initial.elems):
312
- addSub(cv)
333
+ class Mapped private [CaptureSet ]
334
+ (val source : Var , tm : TypeMap , variance : Int , initial : CaptureSet )(using @ constructorOnly ctx : Context )
335
+ extends DerivedVar (initial.elems):
313
336
addSub(initial)
314
337
val stack = if debugSets then (new Throwable ).getStackTrace().take(20 ) else null
315
338
@@ -321,7 +344,7 @@ object CaptureSet:
321
344
322
345
override def addNewElems (newElems : Refs , origin : CaptureSet )(using Context , VarState ): CompareResult =
323
346
val added =
324
- if origin eq cv then
347
+ if origin eq source then
325
348
mapRefs(newElems, tm, variance)
326
349
else
327
350
if variance <= 0 && ! origin.isConst && (origin ne initial) then
@@ -334,49 +357,62 @@ object CaptureSet:
334
357
else CompareResult .fail(this )
335
358
else result
336
359
337
- override def upperApprox (using Context ): CaptureSet = this
360
+ override def upperApprox (origin : CaptureSet )(using Context ): CaptureSet =
361
+ if isConst then this
362
+ else if source eq origin then universal
363
+ else source.upperApprox(this ).map(tm)
364
+
365
+ override def propagateSolved ()(using Context ) =
366
+ if initial.isConst then super .propagateSolved()
338
367
339
- override def toString = s " Mapped $id( $cv , elems = $elems) "
368
+ override def toString = s " Mapped $id( $source , elems = $elems) "
340
369
end Mapped
341
370
342
- class BiMapped private [CaptureSet ] (cv : Var , bimap : BiTypeMap , initialElems : Refs )(using @ constructorOnly ctx : Context ) extends Var (initialElems):
343
- addSub(cv)
371
+ class BiMapped private [CaptureSet ]
372
+ (val source : Var , bimap : BiTypeMap , initialElems : Refs )(using @ constructorOnly ctx : Context )
373
+ extends DerivedVar (initialElems):
344
374
345
375
override def addNewElems (newElems : Refs , origin : CaptureSet )(using Context , VarState ): CompareResult =
346
- if origin eq cv then
376
+ if origin eq source then
347
377
super .addNewElems(newElems.map(bimap.forward), origin)
348
378
else
349
379
val r = super .addNewElems(newElems, origin)
350
380
if r == CompareResult .OK then
351
- cv .tryInclude(newElems.map(bimap.backward), this )
352
- .showing(i " propagating new elems $newElems backward from $this to $cv " , capt)
381
+ source .tryInclude(newElems.map(bimap.backward), this )
382
+ .showing(i " propagating new elems $newElems backward from $this to $source " , capt)
353
383
else r
354
384
355
- override def upperApprox (using Context ): CaptureSet = this
385
+ override def upperApprox (origin : CaptureSet )(using Context ): CaptureSet =
386
+ if isConst then this
387
+ else if source eq origin then super .upperApprox(this ).map(bimap.inverseTypeMap)
388
+ else source.upperApprox(this ).map(bimap)
356
389
357
- override def toString = s " BiMapped $id( $cv , elems = $elems) "
390
+ override def toString = s " BiMapped $id( $source , elems = $elems) "
358
391
end BiMapped
359
392
360
- /** A variable with elements given at any time as { x <- cv .elems | p(x) } */
361
- class Filtered private [CaptureSet ] ( cv : Var , p : CaptureRef => Boolean )( using @ constructorOnly ctx : Context )
362
- extends Var (cv.elems.filter(p)) :
363
- addSub(cv)
393
+ /** A variable with elements given at any time as { x <- source .elems | p(x) } */
394
+ class Filtered private [CaptureSet ]
395
+ ( val source : Var , p : CaptureRef => Boolean )( using @ constructorOnly ctx : Context )
396
+ extends DerivedVar (source.elems.filter(p)) :
364
397
365
398
override def addNewElems (newElems : Refs , origin : CaptureSet )(using Context , VarState ): CompareResult =
366
399
super .addNewElems(newElems.filter(p), origin)
367
400
368
- override def upperApprox (using Context ): CaptureSet = this
401
+ override def upperApprox (origin : CaptureSet )(using Context ): CaptureSet =
402
+ if isConst then this
403
+ else if source eq origin then universal
404
+ else source.upperApprox(this ).filter(p)
369
405
370
- override def toString = s " ${getClass.getSimpleName}$id( $cv , elems = $elems) "
406
+ override def toString = s " ${getClass.getSimpleName}$id( $source , elems = $elems) "
371
407
end Filtered
372
408
373
- /** A variable with elements given at any time as { x <- cv .elems | !other.accountsFor(x) } */
374
- class Diff (cv : Var , other : Const )(using Context )
375
- extends Filtered (cv , ! other.accountsFor(_))
409
+ /** A variable with elements given at any time as { x <- source .elems | !other.accountsFor(x) } */
410
+ class Diff (source : Var , other : Const )(using Context )
411
+ extends Filtered (source , ! other.accountsFor(_))
376
412
377
- /** A variable with elements given at any time as { x <- cv .elems | other.accountsFor(x) } */
378
- class Intersected (cv : Var , other : CaptureSet )(using Context )
379
- extends Filtered (cv , other.accountsFor(_)):
413
+ /** A variable with elements given at any time as { x <- source .elems | other.accountsFor(x) } */
414
+ class Intersected (source : Var , other : CaptureSet )(using Context )
415
+ extends Filtered (source , other.accountsFor(_)):
380
416
addSub(other)
381
417
382
418
def extrapolateCaptureRef (r : CaptureRef , tm : TypeMap , variance : Int )(using Context ): CaptureSet =
0 commit comments