@@ -59,15 +59,15 @@ sealed abstract class CaptureSet extends Showable:
5959 def mutability_= (x : Mutability ): Unit =
6060 myMut = x
6161
62- /** Mark this capture set as belonging to a Mutable type. Called when a new
62+ /** Mark this capture set as belonging to a Stateful type. Called when a new
6363 * CapturingType is formed. This is different from the setter `mutability_=`
64- * in that it be defined with different behaviors:
64+ * in that it can be defined with different behaviors:
6565 *
66- * - set mutability to Mutable (for normal Vars)
66+ * - set mutability to Writer (for normal Vars)
6767 * - take mutability from the set's sources (for DerivedVars)
6868 * - compute mutability on demand based on mutability of elements (for Consts)
6969 */
70- def associateWithMutable ()(using Context ): CaptureSet
70+ def associateWithStateful ()(using Context ): CaptureSet
7171
7272 /** Is this capture set constant (i.e. not an unsolved capture variable)?
7373 * Solved capture variables count as constant.
@@ -148,15 +148,27 @@ sealed abstract class CaptureSet extends Showable:
148148
149149 final def isAlwaysReadOnly (using Context ): Boolean = isConst && isReadOnly
150150
151- final def isExclusive (using Context ): Boolean =
152- elems.exists(_.isExclusive)
151+ /** Is capture set exclusive? If `required` is true, a variable capture set
152+ * is forced to Writer mutability which makes it exclusive. Otherwise a set
153+ * is exclusive if one of its elements is exclusive.
154+ * Possible issue: If required is true, and the set is a constant, with
155+ * multiple elements that each have a variable capture set, then we make
156+ * the set exclusive by updating the first such variable capture set with
157+ * Ignore mutability to have Write mutability. That makes the effect
158+ * order dependent.
159+ */
160+ def isExclusive (required : Boolean = false )(using Context ): Boolean =
161+ if required && ! isConst && mutability == Ignored then
162+ mutability = Writer
163+ mutability == Writer
164+ || elems.exists(_.isExclusive(required))
153165
154166 /** Similar to isExclusive, but also includes capture set variables
155167 * with unknown status.
156168 */
157169 final def maybeExclusive (using Context ): Boolean = reporting.trace(i " mabe exclusive $this" ):
158170 if isConst then elems.exists(_.maybeExclusive)
159- else mutability != ReadOnly
171+ else mutability != Reader
160172
161173 final def keepAlways : Boolean = this .isInstanceOf [EmptyWithProvenance ]
162174
@@ -191,7 +203,7 @@ sealed abstract class CaptureSet extends Showable:
191203 newElems.forall(tryInclude(_, origin))
192204
193205 protected def mutableToReader (origin : CaptureSet )(using Context ): Boolean =
194- if mutability == Mutable then toReader() else true
206+ if mutability == Writer then toReader() else true
195207
196208 /** Add an element to this capture set, assuming it is not already accounted for,
197209 * and omitting any mapping or filtering.
@@ -315,8 +327,8 @@ sealed abstract class CaptureSet extends Showable:
315327 def adaptMutability (that : CaptureSet )(using Context ): CaptureSet | Null =
316328 val m1 = this .mutability
317329 val m2 = that.mutability
318- if m1 == Mutable && m2 == Reader then this .readOnly
319- else if m1 == Reader && m2 == Mutable then
330+ if m1 == Writer && m2 == Reader then this .readOnly
331+ else if m1 == Reader && m2 == Writer then
320332 if that.toReader() then this else null
321333 else this
322334
@@ -541,14 +553,14 @@ object CaptureSet:
541553 type Vars = SimpleIdentitySet [Var ]
542554 type Deps = SimpleIdentitySet [CaptureSet ]
543555
544- enum Mutability :
545- case Mutable , Reader , Ignored
556+ enum Mutability derives CanEqual :
557+ case Writer , Reader , Ignored
546558
547559 def | (that : Mutability ): Mutability =
548560 if this == that then this
549561 else if this == Ignored || that == Ignored then Ignored
550562 else if this == Reader || that == Reader then Reader
551- else Mutable
563+ else Writer
552564
553565 def & (that : Mutability ): Mutability =
554566 if this == that then this
@@ -569,9 +581,9 @@ object CaptureSet:
569581 @ sharable // sharable since the set is empty, so mutability won't be set
570582 val empty : CaptureSet .Const = Const (emptyRefs)
571583
572- /** The empty capture set `{}` of a Mutable type, with Reader status */
573- @ sharable // sharable since the set is empty, so mutability won't be set
574- val emptyOfMutable : CaptureSet .Const =
584+ /** The empty capture set `{}` of a Stateful type, with Reader status */
585+ @ sharable // sharable since the set is empty, so mutability won't be re- set
586+ val emptyOfStateful : CaptureSet .Const =
575587 val cs = Const (emptyRefs)
576588 cs.mutability = Mutability .Reader
577589 cs
@@ -630,15 +642,15 @@ object CaptureSet:
630642
631643 private var isComplete = true
632644
633- def associateWithMutable ()(using Context ): CaptureSet =
634- if elems.isEmpty then emptyOfMutable
645+ def associateWithStateful ()(using Context ): CaptureSet =
646+ if elems.isEmpty then emptyOfStateful
635647 else
636648 isComplete = false // delay computation of Mutability status
637649 this
638650
639651 override def mutability (using Context ): Mutability =
640652 if ! isComplete then
641- myMut = if maybeExclusive then Mutable else Reader
653+ myMut = if maybeExclusive then Writer else Reader
642654 isComplete = true
643655 myMut
644656
@@ -652,7 +664,7 @@ object CaptureSet:
652664 else " "
653665
654666 private def capImpliedByCapability (parent : Type )(using Context ): Capability =
655- if parent.derivesFromMutable then GlobalCap .readOnly else GlobalCap
667+ if parent.derivesFromStateful then GlobalCap .readOnly else GlobalCap
656668
657669 /* The same as {cap} but generated implicitly for references of Capability subtypes.
658670 */
@@ -665,13 +677,14 @@ object CaptureSet:
665677 * nulls, this provides more lenient checking against compilation units that
666678 * were not yet compiled with capture checking on.
667679 */
668- @ sharable // sharable since the set is empty, so setMutable is a no-op
680+ @ sharable
669681 object Fluid extends Const (emptyRefs):
670682 override def isAlwaysEmpty (using Context ) = false
671683 override def addThisElem (elem : Capability )(using Context , VarState ) = true
672684 override def toReader ()(using Context ) = true
673685 override def accountsFor (x : Capability )(using Context )(using VarState ): Boolean = true
674686 override def mightAccountFor (x : Capability )(using Context ): Boolean = true
687+ override def mutability_= (x : Mutability ): Unit = ()
675688 override def toString = " <fluid>"
676689 end Fluid
677690
@@ -727,8 +740,8 @@ object CaptureSet:
727740 */
728741 var deps : Deps = SimpleIdentitySet .empty
729742
730- def associateWithMutable ()(using Context ): CaptureSet =
731- mutability = Mutable
743+ def associateWithStateful ()(using Context ): CaptureSet =
744+ mutability = Writer
732745 this
733746
734747 def isConst (using Context ) = solved >= ccState.iterationId
@@ -846,7 +859,7 @@ object CaptureSet:
846859 if isConst then failWith(MutAdaptFailure (this ))
847860 else
848861 mutability = Reader
849- TypeComparer .logUndoAction(() => mutability = Mutable )
862+ TypeComparer .logUndoAction(() => mutability = Writer )
850863 deps.forall(_.mutableToReader(this ))
851864
852865 private def isPartOf (binder : Type )(using Context ): Boolean =
@@ -933,7 +946,7 @@ object CaptureSet:
933946 def markSolved (provisional : Boolean )(using Context ): Unit =
934947 solved = if provisional then ccState.iterationId else Int .MaxValue
935948 deps.foreach(_.propagateSolved(provisional))
936- if mutability == Mutable && ! maybeExclusive then mutability = Reader
949+ if mutability == Writer && ! maybeExclusive then mutability = Reader
937950
938951
939952 var skippedMaps : Set [TypeMap ] = Set .empty
@@ -1046,7 +1059,7 @@ object CaptureSet:
10461059 addAsDependentTo(source)
10471060
10481061 /** Mutability is same as in source, except for readOnly */
1049- override def associateWithMutable ()(using Context ): CaptureSet = this
1062+ override def associateWithStateful ()(using Context ): CaptureSet = this
10501063
10511064 override def mutableToReader (origin : CaptureSet )(using Context ): Boolean =
10521065 super .mutableToReader(origin)
@@ -1175,8 +1188,8 @@ object CaptureSet:
11751188 super .mutableToReader(origin)
11761189 && {
11771190 if (origin eq cs1) || (origin eq cs2) then true
1178- else if cs1.isConst && cs1.mutability == Mutable then cs2.mutableToReader(this )
1179- else if cs2.isConst && cs2.mutability == Mutable then cs1.mutableToReader(this )
1191+ else if cs1.isConst && cs1.mutability == Writer then cs2.mutableToReader(this )
1192+ else if cs2.isConst && cs2.mutability == Writer then cs1.mutableToReader(this )
11801193 else true
11811194 }
11821195
@@ -1403,7 +1416,7 @@ object CaptureSet:
14031416 else i " $elem cannot be included in $cs"
14041417 end IncludeFailure
14051418
1406- /** Failure indicating that a read-only capture set of a mutable type cannot be
1419+ /** Failure indicating that a read-only capture set of a stateful type cannot be
14071420 * widened to an exclusive set.
14081421 * @param cs the exclusive set in question
14091422 * @param lo the lower type of the orginal type comparison, or NoType if not known
@@ -1412,7 +1425,7 @@ object CaptureSet:
14121425 case class MutAdaptFailure (cs : CaptureSet , lo : Type = NoType , hi : Type = NoType ) extends Note :
14131426
14141427 def render (using Context ): String =
1415- def ofType (tp : Type ) = if tp.exists then i " of the mutable type $tp" else " of a mutable type"
1428+ def ofType (tp : Type ) = if tp.exists then i " of the stateful type $tp" else " of a stateful type"
14161429 i """
14171430 |
14181431 |Note that $cs is an exclusive capture set ${ofType(hi)},
0 commit comments