A question on the mixture of Explicit Capture Polymorphism and Self-type

Hi!
I am using explicit capture polymorphism for a project heavily, and I am trying to use capture set type variables and self-type to define a type that captures something without storing it. As an example, something like this should work in my understanding of capture sets and self-type:

class A[CS^]:
  self: A[CS^]^ =>
end A

@main def main(): Unit = 
  val a: A[{}]^ = A[{}] // should be `A[{cap}]` but the compiler didn't allow it
  val b = A[{a}]

I am expecting the compiler to infer that A’s capture set will be its type argument CS^, but it looks like it’s not the case. The compiler output with “-Xprint:cc”

val a: A[scala.caps.CapSet]^ =
  new ([CS >: scala.caps.CapSet <: scala.caps.CapSet^] =>> A[CS])[
    scala.caps.CapSet]()
val b: A[scala.caps.CapSet^{a}]^{} =
  new ([CS >: scala.caps.CapSet <: scala.caps.CapSet^] =>> A[CS])[
    scala.caps.CapSet^{a}]()

As you can see, the capture sets are empty.
I was wondering:

  • Is it a compiler bug, or am I not understanding something?
  • Is using capture set type params this way an anti-pattern?
  • Is the goal (of capturing something without storing it) possible without self-types?

Thanks

In Capture Checking of Classes:

Sometimes, a tracked capability is meant to be used only in the constructor of a class, but is not intended to be retained as a field. This fact can be communicated to the capture checker by declaring the parameter as @constructorOnly

Maybe not using @constructorOnly would do what you want? Just guessing.

Thanks for your reply!

Yes, that will make the object capture the variable without storing its value, but I still need to pass the value to the constructor. In my use case, I have one-time access to the value of the variable and want to allow others to capture it without passing it around, just through the type system and mentioning it.

In the example, a is not passed around; it’s just mentioned in the type notation of b.