Skip to content

Conversation

@odersky
Copy link
Contributor

@odersky odersky commented Nov 13, 2025

Two changes:

  • We now subsume consume parameters in the fresh of a constructor, instead of keeping track of them besides.
  • We now treat val _ = e like just the expression e for separation checking.

val _: A1^{cap, b} = a1
println(b) // OK since a1's type mentions `b` explicitly
val a2 = A2(b)
val _: A2^{cap, b} = a2
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
val _: A2^{cap, b} = a2
val _: A2^ = a2

Copy link
Contributor

Choose a reason for hiding this comment

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

Is this intentional? It doesn't seem to matter if it's {cap, b} or {cap}. Or is the point to show that mentioning b explicitly as in A1 above doesn't influence the outcome?

println(b) // error
println(a1) // error, since `b` was consumed before
println(a2) // OK since b belongs to a2

Copy link
Contributor

Choose a reason for hiding this comment

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

Trying println(a2.b) at this point yields a separation failure. But why? The b should be owned by a2 now. If this is as intended, it means that consume on a val constructor parameter makes the field inaccessible.

&& !implied.isAlwaysEmpty
&& argType.captureSet.subCaptures(allCaptures)
// A consume parameter of a constructor will be hidden in the implied fresh of the
// class if there is one. Example:
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm trying to understand what should happen when the if there is one part is not true.
Say, in the below test file, if we let A1 and A2 have no implied fresh (IIUC):

class A1(val b: B^)
class A2(consume val b: B^)

Then it exhibits the expected errors, plus it complains about
val _: A2^{cap, b} = a2 and println(a2) with the same error message:

Separation failure: Illegal access to (a2 : A2{val b: B^{b²}}^{b²}), which was passed to a
   |consume parameter or was used as a prefix to a consume method on line 18
   |and therefore is no longer available.
   |
   |where:    b  is a value in class A2
   |          b² is a value in method Test

Why is accessing a2 forbidden now?

Independently of whether an error is expected or not: The error message itself is confusing, because a2 neither was "passed to a consume parameter" nor "was used as a prefix to a consume method".

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