@@ -61,10 +61,6 @@ sealed abstract class CaptureSet extends Showable:
6161 */
6262 def levelLimit : Symbol
6363
64- def rootSet (using Context ): CaptureSet =
65- assert(levelLimit.exists, this )
66- levelLimit.localRoot.termRef.singletonCaptureSet
67-
6864 /** Is this capture set definitely non-empty? */
6965 final def isNotEmpty : Boolean = ! elems.isEmpty
7066
@@ -144,16 +140,30 @@ sealed abstract class CaptureSet extends Showable:
144140 extension (x : CaptureRef )(using Context )
145141 private def subsumes (y : CaptureRef ) =
146142 (x eq y)
143+ || x.isSuperRootOf(y)
147144 || y.match
148- case y : TermRef => (y.prefix eq x) || y.isLocalRootCapability && x.isSuperRootOf(y)
149- case y : CaptureRoot .Var => x.isSuperRootOf(y)
145+ case y : TermRef => y.prefix eq x
150146 case _ => false
151147 || (x.isGenericRootCapability || y.isRootCapability && x.isRootCapability)
152148 && ctx.property(LooseRootChecking ).isDefined
153149
154- private def isSuperRootOf (y : CaptureRoot ) = x match
155- case x : CaptureRoot =>
156- x.isGenericRootCapability || x.isLocalRootCapability && y.encloses(x)
150+ /** x <:< cap, cap[x] <:< cap
151+ * cap[y] <:< cap[x] if y encloses x
152+ * y <:< cap[x] if y's level owner encloses x's local root owner
153+ */
154+ private def isSuperRootOf (y : CaptureRef ): Boolean = x match
155+ case x : TermRef =>
156+ if x.isGenericRootCapability then true
157+ else if x.isLocalRootCapability && ! y.isGenericRootCapability then
158+ val xowner = x.localRootOwner
159+ y match
160+ case y : TermRef =>
161+ xowner.isContainedIn(y.symbol.levelOwner)
162+ case y : ThisType =>
163+ xowner.isContainedIn(y.cls)
164+ case _ =>
165+ false
166+ else false
157167 case _ => false
158168 end extension
159169
@@ -207,9 +217,10 @@ sealed abstract class CaptureSet extends Showable:
207217 def recur (elems : List [CaptureRef ]): CompareResult = elems match
208218 case elem :: elems1 =>
209219 var result = that.tryInclude(elem, this )
210- if ! result.isOK && ! elem.isRootCapability && summon[ VarState ] != FrozenState then
220+ if ! result.isOK then
211221 ccState.levelError = ccState.levelError.orElse(result.levelError)
212- result = result.orElse(elem.captureSetOfInfo.subCaptures(that))
222+ if ! elem.isRootCapability && summon[VarState ] != FrozenState then
223+ result = result.orElse(elem.captureSetOfInfo.subCaptures(that))
213224 if result.isOK then
214225 recur(elems1)
215226 else
@@ -322,22 +333,6 @@ sealed abstract class CaptureSet extends Showable:
322333 def substParams (tl : BindingType , to : List [Type ])(using Context ) =
323334 map(Substituters .SubstParamsMap (tl, to))
324335
325- /** The capture root that corresponds to this capture set. This is:
326- * - if the capture set is a Var with a defined level limit, the
327- * associated capture root,
328- * - otherwise, if the set is nonempty, the innermost root such
329- * that some element of the set subcaptures this root,
330- * - otherwise, if the set is empty, `default`.
331- */
332- def impliedRoot (default : CaptureRoot )(using Context ): CaptureRoot =
333- if levelLimit.exists then levelLimit.localRoot.termRef
334- else if elems.isEmpty then default
335- else elems.toList
336- .map:
337- case elem : CaptureRoot if elem.isLocalRootCapability => elem
338- case elem => elem.captureSetOfInfo.impliedRoot(default)
339- .reduce((x : CaptureRoot , y : CaptureRoot ) => CaptureRoot .lub(x, y))
340-
341336 /** Invoke handler if this set has (or later aquires) the root capability `cap` */
342337 def disallowRootCapability (handler : () => Context ?=> Unit )(using Context ): this .type =
343338 if isUniversal then handler()
@@ -459,7 +454,7 @@ object CaptureSet:
459454 varId += 1
460455 varId
461456
462- // assert(id != 95 )
457+ // assert(id != 40 )
463458
464459 override val levelLimit =
465460 if directOwner.exists then directOwner.levelOwner else NoSymbol
@@ -525,12 +520,15 @@ object CaptureSet:
525520 if elem.isGenericRootCapability then rootAddedHandler()
526521 newElemAddedHandler(elem)
527522 // assert(id != 5 || elems.size != 3, this)
528- (CompareResult .OK /: deps) { (r, dep) =>
523+ val res = (CompareResult .OK /: deps) { (r, dep) =>
529524 r.andAlso(dep.tryInclude(elem, this ))
530525 }.addToTrace(this )
526+ if ! res.isOK then elems -= elem
527+ res
531528
532529 private def levelOK (elem : CaptureRef )(using Context ): Boolean =
533- ! levelLimit.exists
530+ if elem.isGenericRootCapability then ! noUniversal
531+ else ! levelLimit.exists
534532 || elem.match
535533 case elem : TermRef =>
536534 var sym = elem.symbol
@@ -571,15 +569,15 @@ object CaptureSet:
571569 else if elems.exists(_.isRootCapability) then
572570 CaptureSet (elems.filter(_.isRootCapability).toList* )
573571 else if computingApprox then
574- rootSet
572+ universal
575573 else
576574 computingApprox = true
577575 try computeApprox(origin).ensuring(_.isConst)
578576 finally computingApprox = false
579577
580578 /** The intersection of all upper approximations of dependent sets */
581579 protected def computeApprox (origin : CaptureSet )(using Context ): CaptureSet =
582- (rootSet /: deps) { (acc, sup) => acc ** sup.upperApprox(this ) }
580+ (universal /: deps) { (acc, sup) => acc ** sup.upperApprox(this ) }
583581
584582 /** Widen the variable's elements to its upper approximation and
585583 * mark it as constant from now on. This is used for contra-variant type variables
@@ -720,7 +718,7 @@ object CaptureSet:
720718 if source eq origin then
721719 // it's a mapping of origin, so not a superset of `origin`,
722720 // therefore don't contribute to the intersection.
723- rootSet
721+ universal
724722 else
725723 source.upperApprox(this ).map(tm)
726724
@@ -788,7 +786,7 @@ object CaptureSet:
788786 if source eq origin then
789787 // it's a filter of origin, so not a superset of `origin`,
790788 // therefore don't contribute to the intersection.
791- rootSet
789+ universal
792790 else
793791 source.upperApprox(this ).filter(p)
794792
@@ -819,7 +817,7 @@ object CaptureSet:
819817 if (origin eq cs1) || (origin eq cs2) then
820818 // it's a combination of origin with some other set, so not a superset of `origin`,
821819 // therefore don't contribute to the intersection.
822- rootSet
820+ universal
823821 else
824822 CaptureSet (elemIntersection(cs1.upperApprox(this ), cs2.upperApprox(this )))
825823
@@ -1010,10 +1008,6 @@ object CaptureSet:
10101008 def ofInfo (ref : CaptureRef )(using Context ): CaptureSet = ref match
10111009 case ref : TermRef if ref.isRootCapability =>
10121010 ref.singletonCaptureSet
1013- case ref : TermRef if ref.symbol.isLevelOwner =>
1014- ofType(ref.underlying, followResult = true ).filter(
1015- ref.symbol.localRoot.termRef != _)
1016- // TODO: Can replace filter with - ref.symbol.localRoot.termRef when we drop level nesting
10171011 case _ =>
10181012 ofType(ref.underlying, followResult = true )
10191013
@@ -1095,12 +1089,18 @@ object CaptureSet:
10951089 override def toAdd (using Context ) =
10961090 for CompareResult .LevelError (cs, ref) <- ccState.levelError.toList yield
10971091 ccState.levelError = None
1098- val levelStr = ref match
1099- case ref : TermRef => i " , defined in ${ref.symbol.maybeOwner}"
1100- case _ => " "
1101- i """
1102- |
1103- |Note that reference ${ref}$levelStr
1104- |cannot be included in outer capture set $cs which is associated with ${cs.levelLimit}"""
1092+ if ref.isGenericRootCapability then
1093+ i """
1094+ |
1095+ |Note that the universal capability `cap`
1096+ |cannot be included in capture set $cs"""
1097+ else
1098+ val levelStr = ref match
1099+ case ref : TermRef => i " , defined in ${ref.symbol.maybeOwner}"
1100+ case _ => " "
1101+ i """
1102+ |
1103+ |Note that reference ${ref}$levelStr
1104+ |cannot be included in outer capture set $cs which is associated with ${cs.levelLimit}"""
11051105
11061106end CaptureSet
0 commit comments