Skip to content

Conversation

@odersky
Copy link
Contributor

@odersky odersky commented Dec 22, 2025

Under separation checking: A mutable var owned by a term that is not annotated with @untrackedCaptures gives rise to a Mutable capability. Since a mutable variable is not trackable, we do this by adding a varMirror symbol to the variable which represents the capability.

@odersky odersky requested a review from a team as a code owner December 22, 2025 12:08
Move operations a bit higher up the callchain and allow for more modifications
what is allowed.
When we have

  var x: A^{c} = ...

where `x` is a local variable then when dereferencing `x` we also need to charge `c`.
This was forgotten before. For fields it's not a problem since `c` would already have been
charged for the prefix `p` in `p.x`.

An alternative would be to consider mutable variables to have boxed types. Then the same
capture set would be charged on unboxing.
Copy link
Contributor

@bracevac bracevac left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

case self: CoreCapability => self.isTrackableRef
case _ => true

/** Under separatiion checking: Is this a mutable var owned by a term that is
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/** Under separatiion checking: Is this a mutable var owned by a term that is
/** Under separation checking: Is this a mutable var owned by a term that is

var r: Int = 0
(() => r, (x: Int) => r = x)

class Struct:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The asymmetry between pairs and such a custom class is jarring.
I'm wondering if we could have a less boilerplate-y way of achieving the Struct case with standard pairs? Could we have a scoped delimiter that
says "We allow construction of data with shared components here"?

def foo() =
  val r = Ref()
  shared:
    (() => r.get, (x: Int) => r.set(x)) // ok, now

Making sure that the cap of the pair object subsumes the component caps?

@bracevac bracevac assigned odersky and unassigned bracevac Dec 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants