@@ -12,7 +12,7 @@ import annotation.internal.sharable
12
12
import reporting .trace
13
13
import printing .{Showable , Printer }
14
14
import printing .Texts .*
15
- import util .{SimpleIdentitySet , Property }
15
+ import util .{SimpleIdentitySet , Property , optional }, optional .{ break , ? }
16
16
import util .common .alwaysTrue
17
17
import scala .collection .mutable
18
18
import config .Config .ccAllowUnsoundMaps
@@ -55,6 +55,11 @@ sealed abstract class CaptureSet extends Showable:
55
55
*/
56
56
def isAlwaysEmpty : Boolean
57
57
58
+ /** The level owner in which the set is defined. Sets can only take
59
+ * elements with nesting level up to the cc-nestinglevel of owner.
60
+ */
61
+ def owner : Symbol
62
+
58
63
/** Is this capture set definitely non-empty? */
59
64
final def isNotEmpty : Boolean = ! elems.isEmpty
60
65
@@ -123,10 +128,14 @@ sealed abstract class CaptureSet extends Showable:
123
128
* as frozen.
124
129
*/
125
130
def accountsFor (x : CaptureRef )(using Context ): Boolean =
126
- reporting.trace(i " $this accountsFor $x, ${x.captureSetOfInfo}? " , show = true ) {
127
- elems.exists(_.subsumes(x))
128
- || ! x.isRootCapability && x.captureSetOfInfo.subCaptures(this , frozen = true ).isOK
129
- }
131
+ if comparer.isInstanceOf [ExplainingTypeComparer ] then // !!! DEBUG
132
+ reporting.trace.force(i " $this accountsFor $x, ${x.captureSetOfInfo}? " , show = true ):
133
+ elems.exists(_.subsumes(x))
134
+ || ! x.isRootCapability && x.captureSetOfInfo.subCaptures(this , frozen = true ).isOK
135
+ else
136
+ reporting.trace(i " $this accountsFor $x, ${x.captureSetOfInfo}? " , show = true ):
137
+ elems.exists(_.subsumes(x))
138
+ || ! x.isRootCapability && x.captureSetOfInfo.subCaptures(this , frozen = true ).isOK
130
139
131
140
/** A more optimistic version of accountsFor, which does not take variable supersets
132
141
* of the `x` reference into account. A set might account for `x` if it accounts
@@ -191,7 +200,8 @@ sealed abstract class CaptureSet extends Showable:
191
200
if this .subCaptures(that, frozen = true ).isOK then that
192
201
else if that.subCaptures(this , frozen = true ).isOK then this
193
202
else if this .isConst && that.isConst then Const (this .elems ++ that.elems)
194
- else Var (this .elems ++ that.elems).addAsDependentTo(this ).addAsDependentTo(that)
203
+ else Var (this .owner.maxNested(that.owner), this .elems ++ that.elems)
204
+ .addAsDependentTo(this ).addAsDependentTo(that)
195
205
196
206
/** The smallest superset (via <:<) of this capture set that also contains `ref`.
197
207
*/
@@ -276,7 +286,9 @@ sealed abstract class CaptureSet extends Showable:
276
286
if isUniversal then handler()
277
287
this
278
288
279
- /** Invoke handler on the elements to check wellformedness of the capture set */
289
+ /** Invoke handler on the elements to ensure wellformedness of the capture set.
290
+ * The handler might add additional elements to the capture set.
291
+ */
280
292
def ensureWellformed (handler : List [CaptureRef ] => Context ?=> Unit )(using Context ): this .type =
281
293
handler(elems.toList)
282
294
this
@@ -353,6 +365,8 @@ object CaptureSet:
353
365
354
366
def withDescription (description : String ): Const = Const (elems, description)
355
367
368
+ def owner = NoSymbol
369
+
356
370
override def toString = elems.toString
357
371
end Const
358
372
@@ -371,16 +385,23 @@ object CaptureSet:
371
385
end Fluid
372
386
373
387
/** The subclass of captureset variables with given initial elements */
374
- class Var (initialElems : Refs = emptySet) extends CaptureSet :
388
+ class Var (directOwner : Symbol , initialElems : Refs = emptySet)( using @ constructorOnly ictx : Context ) extends CaptureSet :
375
389
376
390
/** A unique identification number for diagnostics */
377
391
val id =
378
392
varId += 1
379
393
varId
380
394
395
+ override val owner = directOwner.levelOwner
396
+
381
397
/** A variable is solved if it is aproximated to a from-then-on constant set. */
382
398
private var isSolved : Boolean = false
383
399
400
+ private var ownLevelCache = - 1
401
+ private def ownLevel (using Context ) =
402
+ if ownLevelCache == - 1 then ownLevelCache = owner.ccNestingLevel
403
+ ownLevelCache
404
+
384
405
/** The elements currently known to be in the set */
385
406
var elems : Refs = initialElems
386
407
@@ -425,16 +446,30 @@ object CaptureSet:
425
446
deps = state.deps(this )
426
447
427
448
def addNewElems (newElems : Refs , origin : CaptureSet )(using Context , VarState ): CompareResult =
428
- if ! isConst && recordElemsState() then
449
+ if isConst || ! recordElemsState() then
450
+ CompareResult .fail(this ) // fail if variable is solved or given VarState is frozen
451
+ else if levelsOK(newElems) then
429
452
elems ++= newElems
430
453
if isUniversal then rootAddedHandler()
431
454
newElemAddedHandler(newElems.toList)
432
455
// assert(id != 5 || elems.size != 3, this)
433
456
(CompareResult .OK /: deps) { (r, dep) =>
434
457
r.andAlso(dep.tryInclude(newElems, this ))
435
458
}
436
- else // fail if variable is solved or given VarState is frozen
437
- CompareResult .fail(this )
459
+ else widenCaptures(newElems) match
460
+ case Some (newElems1) => tryInclude(newElems1, origin)
461
+ case None => CompareResult .fail(this )
462
+
463
+ private def levelsOK (elems : Refs )(using Context ): Boolean =
464
+ ! elems.exists(_.ccNestingLevel > ownLevel)
465
+
466
+ private def widenCaptures (elems : Refs )(using Context ): Option [Refs ] =
467
+ optional :
468
+ (SimpleIdentitySet [CaptureRef ]() /: elems): (acc, elem) =>
469
+ if elem.ccNestingLevel <= ownLevel then acc + elem
470
+ else if elem.isRootCapability then break()
471
+ else acc ++ widenCaptures(elem.captureSetOfInfo.elems).?
472
+ .showing(i " widen catures ${elems.toList} for $this at $owner = $result" , capt)
438
473
439
474
def addDependent (cs : CaptureSet )(using Context , VarState ): CompareResult =
440
475
if (cs eq this ) || cs.isUniversal || isConst then
@@ -519,8 +554,8 @@ object CaptureSet:
519
554
end Var
520
555
521
556
/** A variable that is derived from some other variable via a map or filter. */
522
- abstract class DerivedVar (initialElems : Refs )(using @ constructorOnly ctx : Context )
523
- extends Var (initialElems):
557
+ abstract class DerivedVar (owner : Symbol , initialElems : Refs )(using @ constructorOnly ctx : Context )
558
+ extends Var (owner, initialElems):
524
559
525
560
// For debugging: A trace where a set was created. Note that logically it would make more
526
561
// sense to place this variable in Mapped, but that runs afoul of the initializatuon checker.
@@ -546,7 +581,7 @@ object CaptureSet:
546
581
*/
547
582
class Mapped private [CaptureSet ]
548
583
(val source : Var , tm : TypeMap , variance : Int , initial : CaptureSet )(using @ constructorOnly ctx : Context )
549
- extends DerivedVar (initial.elems):
584
+ extends DerivedVar (source.owner, initial.elems):
550
585
addAsDependentTo(initial) // initial mappings could change by propagation
551
586
552
587
private def mapIsIdempotent = tm.isInstanceOf [IdempotentCaptRefMap ]
@@ -612,7 +647,7 @@ object CaptureSet:
612
647
*/
613
648
final class BiMapped private [CaptureSet ]
614
649
(val source : Var , bimap : BiTypeMap , initialElems : Refs )(using @ constructorOnly ctx : Context )
615
- extends DerivedVar (initialElems):
650
+ extends DerivedVar (source.owner, initialElems):
616
651
617
652
override def addNewElems (newElems : Refs , origin : CaptureSet )(using Context , VarState ): CompareResult =
618
653
if origin eq source then
@@ -642,7 +677,7 @@ object CaptureSet:
642
677
/** A variable with elements given at any time as { x <- source.elems | p(x) } */
643
678
class Filtered private [CaptureSet ]
644
679
(val source : Var , p : Context ?=> CaptureRef => Boolean )(using @ constructorOnly ctx : Context )
645
- extends DerivedVar (source.elems.filter(p)):
680
+ extends DerivedVar (source.owner, source. elems.filter(p)):
646
681
647
682
override def addNewElems (newElems : Refs , origin : CaptureSet )(using Context , VarState ): CompareResult =
648
683
val filtered = newElems.filter(p)
@@ -673,7 +708,7 @@ object CaptureSet:
673
708
extends Filtered (source, ! other.accountsFor(_))
674
709
675
710
class Intersected (cs1 : CaptureSet , cs2 : CaptureSet )(using Context )
676
- extends Var (elemIntersection(cs1, cs2)):
711
+ extends Var (cs1.owner.minNested(cs2.owner), elemIntersection(cs1, cs2)):
677
712
addAsDependentTo(cs1)
678
713
addAsDependentTo(cs2)
679
714
deps += cs1
0 commit comments