Skip to content

Drop @experimental for retains and retainsCap #22745

Open
@natsukagami

Description

@natsukagami

scala.annotation.retains and retainsCap are internally used by the capture checker as the representation of capturing types. While capture checking itself is still evolving, the annotations should be considered stable.
Generally, the annotations does not show up in programs that do not enable experimental.captureChecking, even when interacting with modules that do. However, inlining will surface these annotations. While they do not affect the type checker, they cause the experimental check to fail.

An example of this is the scala.util.boundary package, which would greatly benefit from having its Label tracked and capture-checked.
However, boundary.apply requires its body to be inlined into the caller (so that locally-scoped boundary.break calls turn into efficient jumps), which leaks the tracked label with the retainsCap annotation into the caller.

  /** Run `body` with freshly generated label as implicit argument. Catch any
   *  breaks associated with that label and return their results instead of
   *  `body`'s result.
   */
  inline def apply[T](inline body: Label[T]^ ?=> T): T =
    val local: Label[T]^ = Label[T]() // Label[T] @retainsCap 
    try body(using local)
    catch case ex: Break[T] @unchecked =>
      if ex.label eq local.id then ex.value
      else throw ex

This would prevent code not enabling capture-checking (which includes the Scala compiler itself) from using boundary.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions