Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/cc/CaptureOps.scala
Original file line number Diff line number Diff line change
Expand Up @@ -606,15 +606,16 @@ extension (cls: ClassSymbol) {
case _ => Nil

def maybeRO(ref: Capability, fields: List[Symbol]) =
if !cls.typeRef.isStatefulType && fields.forall(allLocalCapsInTypeAreRO)
if !cls.typeRef.isStatefulType() && fields.forall(allLocalCapsInTypeAreRO)
then ref.readOnly
else ref

def localCap(fields: List[Symbol]) =
LocalCap(Origin.NewInstance(core, fields))

var implied = impliedClassifiers(cls)
if cls.typeRef.isStatefulType then implied = dominators(cls.classifier :: Nil, implied)
if cls.typeRef.isStatefulType(varsOnly = true) then
implied = dominators(cls.classifier :: Nil, implied)
val fields = contributingFields(cls)
val impliedSet = ccState.localCapClassifiersAndFieldsCache.getOrElseUpdate(cls, (implied, fields)) match
case (Nil, _) =>
Expand Down
14 changes: 8 additions & 6 deletions compiler/src/dotty/tools/dotc/cc/Mutability.scala
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,16 @@ object Mutability:
else sym.owner.inExclusivePartOf(cls)

extension (tp: Type)
/** Is this a type extending `Stateful` that has non-private update methods
* or mutable fields?

/** Is this a type extending `Stateful` that has update methods or mutable fields?
* Disregard mutable fields with @untrackedCaptures annotations.
* @param varsOnly if true, disregard all update methods and search only for mutabe fields
*/
def isStatefulType(using Context): Boolean =
def isStatefulType(varsOnly: Boolean = false)(using Context): Boolean =
tp.derivesFrom(defn.Caps_Stateful)
&& tp.membersBasedOnFlags(Mutable, EmptyFlags).exists: mbr =>
if mbr.symbol.is(Method) then mbr.symbol.isUpdateMethod
else !mbr.symbol.hasAnnotation(defn.UntrackedCapturesAnnot)
mbr.symbol.isUpdateMethod && !varsOnly
|| mbr.symbol.isMutableVar && !mbr.symbol.hasAnnotation(defn.UntrackedCapturesAnnot)

/** OK, except if `tp` extends `Stateful` but `tp`'s capture set is non-exclusive
* @param required if true, exclusivity can be obtained by setting the mutability
Expand Down Expand Up @@ -120,7 +122,7 @@ object Mutability:
tp.selector.isReadOnlyMember || tp.selector.isMutableVar && tp.pt != LhsProto
case _ =>
tp.isValueType
&& (!tp.isStatefulType || tp.captureSet.mutability == CaptureSet.Mutability.Reader)
&& (!tp.isStatefulType() || tp.captureSet.mutability == CaptureSet.Mutability.Reader)

extension (ref: TermRef | ThisType)
/** Map `ref` to `ref.readOnly` if its type extends Mutable, and one of the
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-custom-args/captures/mut-iterator4-global.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import caps.{any, Stateful, SharedCapability}
import caps.{any, Stateful, SharedCapability, ExclusiveCapability}

trait Iterator[T] extends Stateful:
trait Iterator[T] extends Stateful, ExclusiveCapability:
def hasNext: Boolean
update def next(): T

Expand Down
2 changes: 1 addition & 1 deletion tests/neg-custom-args/captures/mut-iterator4.check
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
|
|Note that capability `any` cannot flow into capture set {it, f}.
|
|where: any is a root capability created in method mappedIterator when constructing instance Object with Iterator[U] {...}
|where: any is a root capability created in method mappedIterator when constructing instance Object with (Iterator[U]^{any².rd}) {...}
|
22 | def hasNext = it.hasNext
23 | update def next() = f(it.next())
Expand Down
4 changes: 2 additions & 2 deletions tests/neg-custom-args/captures/mut-iterator4.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import caps.{any, Stateful, SharedCapability}
import caps.{any, Stateful, SharedCapability, ExclusiveCapability}

trait Iterator[T] extends Stateful:
trait Iterator[T] extends Stateful, ExclusiveCapability:
def hasNext: Boolean
update def next(): T

Expand Down
6 changes: 3 additions & 3 deletions tests/neg-custom-args/captures/paths-complex-consume.scala
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import language.experimental.captureChecking
import language.experimental.separationChecking
import caps.any
import scala.caps.Stateful
import scala.caps.{Stateful, ExclusiveCapability}

// Create a deeper nesting structure
class D()
class C(val d: D^)
class B(val c: C^)
class A(consume val b: B^) extends Stateful:
class A(consume val b: B^) extends Stateful, ExclusiveCapability:
update def use() = println("Using A")

// Test 1: Accessing nested fields through a consumed path
Expand All @@ -27,7 +27,7 @@ class Container(consume val a: A^) extends Stateful:
val other: A^ = A(B(C(D())))
update def operate() = other.use()

class Outer(consume val container: Container^) extends Stateful:
class Outer(consume val container: Container^) extends Stateful, ExclusiveCapability:
update def execute() = container.operate()

def testComplexPrefix =
Expand Down
8 changes: 8 additions & 0 deletions tests/pos-custom-args/captures/stateful-implied.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@

class Iter extends caps.Stateful:
update def next() = ()

val it: Iter^{} = Iter()



Loading