Skip to content

New Syntax for Capture Variables and Explicit Capture Polymorphism v3 #23063

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

bracevac
Copy link
Contributor

@bracevac bracevac commented Apr 28, 2025

Closes #22490
Builds on #22725
Supersedes #22902

This syntax for capture variables and members caters to the view that "they are another kind", and most conventions we know from higher-kinded type parameters carry over.

A postfix ^ (analogous to [_]) indicates that a type parameter/member ranges over capture sets

def sayHi[C^](l: Logger^{C}) = l.log("hello world")

trait LList[T, C^]:
  type D^ >: C // or equivalently >: {C}
  val node: Ref[T^{D}]^

These variables can be bounded by capture-set literals:

trait Foo:
  type C^ 
  type D^ >: {logger} <: {logger, async, this.C}
  type E^ : Monad // error, context bounds are forbidden

Just as with higher-kinded type parameters, the kind is "contagious", and we can often avoid the hat if the bounds are concrete capture sets or other capture variables:

trait Foo:
  type C >: {} <: {cap}     // no hat needed
  type D >: C               // dito
  type E = {x,y,z}          // dito
  type F >: Object <: {cap} // error, ill-kinded

Capture variables will be erased if capture checking is turned off. In non-capture-checked code, they are essentially type variables within the interval >: caps.CapSet <: caps.CapSet. With capture checking turned on and without explicit bounds, the interval corresponds to >: caps.CapSet^{} <: caps.CapSet^{caps.cap}.

Tasks

  • Bullet-proof the "can avoid the hat" for binders scheme.
  • Grammar doc.
  • Update language reference.
  • Port new tests.
  • Clarify when and where to produce attachments.
  • Forbid nonsense intervals mixing capture sets and types.

@bracevac bracevac marked this pull request as ready for review April 30, 2025 15:34
@bracevac bracevac assigned bracevac and odersky and unassigned bracevac Apr 30, 2025
@bracevac bracevac requested review from noti0na1 and odersky April 30, 2025 15:38
@bracevac
Copy link
Contributor Author

@odersky making these behave analogously to higher-kinded type parameters makes me wonder if

  1. We should drop the lower bound CapSet and leave it at Nothing for capture-set variables? That makes parsing easier, especially scenarios where we are at liberty to omit the ^ and have some other cue that we are declaring a capture-set variable.
  2. If yes, make CapSet truly its own kind by making it extend from AnyKind?

@noti0na1
Copy link
Member

  1. We should drop the lower bound CapSet and leave it at Nothing for capture-set variables? That makes parsing easier, especially scenarios where we are at liberty to omit the ^ and have some other cue that we are declaring a capture-set variable.

If the lower bound of a capture variable is temprarily Noting during parsing, it is fine, but it must be bound by CapSet for both sides during or before typing. I don't know which way is easier, but I guess is doing in parser...

@bracevac
Copy link
Contributor Author

It's not impossible to add the lower bound (& upper bound) during parsing. But if the mental model is "this is another kind", then the proposed scheme will be irregular for someone who is familiar with the syntax- and subtyping-rules for higher-kinded types in Scala.

@noti0na1
Copy link
Member

I don't think we should make a capture variable a real "kind"...

@bracevac
Copy link
Contributor Author

bracevac commented May 1, 2025

@noti0na1 The old erroneous tests in tests/neg-custom-args/captures/capset-members.scala pass now when they shouldn't.
Nevermind, the problem was simply that the errors in the newly added test cases masked the old ones.

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.

CC: Better End-User Syntax for Declaring and Mentioning Capture Variables
4 participants