Skip to content

Reorganize CC docs #23709

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
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 3 additions & 8 deletions compiler/src/dotty/tools/dotc/cc/Capability.scala
Original file line number Diff line number Diff line change
Expand Up @@ -703,14 +703,6 @@ object Capabilities:
(this eq y)
|| this.match
case x: FreshCap =>
def levelOK =
if ccConfig.useFreshLevels && !CCState.collapseFresh then
val yOwner = y.levelOwner
yOwner.isStaticOwner || x.ccOwner.isContainedIn(yOwner)
else y.core match
case ResultCap(_) | _: ParamRef => false
case _ => true

vs.ifNotSeen(this)(x.hiddenSet.elems.exists(_.subsumes(y)))
|| x.acceptsLevelOf(y)
&& ( y.tryClassifyAs(x.hiddenSet.classifier)
Expand Down Expand Up @@ -788,6 +780,9 @@ object Capabilities:
case _: Maybe => MaybeCapability(c1)
case _ => c1

def showAsCapability(using Context) =
i"capability ${ctx.printer.toTextCapability(this).show}"

def toText(printer: Printer): Text = printer.toTextCapability(this)
end Capability

Expand Down
31 changes: 22 additions & 9 deletions compiler/src/dotty/tools/dotc/cc/CaptureSet.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ import CCState.*
import TypeOps.AvoidMap
import compiletime.uninitialized
import Capabilities.*
import Names.Name
import NameKinds.CapsetName

/** A class for capture sets. Capture sets can be constants or variables.
* Capture sets support inclusion constraints <:< where <:< is subcapturing.
Expand Down Expand Up @@ -738,6 +740,17 @@ object CaptureSet:

var description: String = ""

private var myRepr: Name | Null = null

/** A represtentation of this capture set as a unique name. We print
* empty capture set variables in this representation. Bimapped sets have
* the representation of their source set.
*/
def repr(using Context): Name = {
if (myRepr == null) myRepr = CapsetName.fresh()
myRepr.nn
}

/** Check that all maps recorded in skippedMaps map `elem` to itself
* or something subsumed by it.
*/
Expand Down Expand Up @@ -1028,6 +1041,7 @@ object CaptureSet:
override def isMaybeSet: Boolean = bimap.isInstanceOf[MaybeMap]
override def toString = s"BiMapped$id($source, elems = $elems)"
override def summarize = bimap.getClass.toString
override def repr(using Context): Name = source.repr
end BiMapped

/** A variable with elements given at any time as { x <- source.elems | p(x) } */
Expand Down Expand Up @@ -1300,24 +1314,23 @@ object CaptureSet:
case cs: Var =>
if !cs.levelOK(elem) then
val levelStr = elem match
case ref: TermRef => i", defined in ${ref.symbol.maybeOwner}"
case _ => ""
i"""capability ${elem}$levelStr
|cannot be included in outer capture set $cs"""
case ref: TermRef => i", defined in ${ref.symbol.maybeOwner}\n"
case _ => " "
i"""${elem.showAsCapability}${levelStr}cannot be included in outer capture set $cs"""
else if !elem.tryClassifyAs(cs.classifier) then
i"""capability ${elem} is not classified as ${cs.classifier}, therefore it
i"""${elem.showAsCapability} is not classified as ${cs.classifier}, therefore it
|cannot be included in capture set $cs of ${cs.classifier.name} elements"""
else if cs.isBadRoot(elem) then
elem match
case elem: FreshCap =>
i"""local capability $elem created in ${elem.ccOwner}
i"""local ${elem.showAsCapability} created in ${elem.ccOwner}
|cannot be included in outer capture set $cs"""
case _ =>
i"universal capability $elem cannot be included in capture set $cs"
i"universal ${elem.showAsCapability} cannot be included in capture set $cs"
else
i"capability $elem cannot be included in capture set $cs"
i"${elem.showAsCapability} cannot be included in capture set $cs"
case _ =>
i"capability $elem is not included in capture set $cs$why"
i"${elem.showAsCapability} is not included in capture set $cs$why"

override def toText(printer: Printer): Text =
inContext(printer.printerContext):
Expand Down
1 change: 1 addition & 0 deletions compiler/src/dotty/tools/dotc/core/NameKinds.scala
Original file line number Diff line number Diff line change
Expand Up @@ -328,6 +328,7 @@ object NameKinds {
val ExceptionBinderName: UniqueNameKind = new UniqueNameKind("ex")
val ExistentialBinderName: UniqueNameKind = new UniqueNameKind("ex$")
val SkolemName: UniqueNameKind = new UniqueNameKind("?")
val CapsetName: UniqueNameKind = new UniqueNameKind("'s")
val SuperArgName: UniqueNameKind = new UniqueNameKind("$superArg$")
val DocArtifactName: UniqueNameKind = new UniqueNameKind("$doc")
val UniqueInlineName: UniqueNameKind = new UniqueNameKind("$i")
Expand Down
9 changes: 4 additions & 5 deletions compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,10 +173,11 @@ class PlainPrinter(_ctx: Context) extends Printer {
else if cs == CaptureSet.Fluid then "<fluid>"
else
val core: Text =
if !cs.isConst && cs.elems.isEmpty then "?"
else "{" ~ Text(cs.processElems(_.toList.map(toTextCapability)), ", ") ~ "}"
if !cs.isConst && cs.elems.isEmpty then cs.asVar.repr.show
else
Str("'").provided(ccVerbose && !cs.isConst)
~ "{" ~ Text(cs.processElems(_.toList.map(toTextCapability)), ", ") ~ "}"
~ Str(".reader").provided(ccVerbose && cs.mutability == Mutability.Reader)
~ Str("?").provided(ccVerbose && !cs.isConst)
~ Str(s"#${cs.asVar.id}").provided(showUniqueIds && !cs.isConst)
core ~ cs.optionalInfo

Expand Down Expand Up @@ -243,8 +244,6 @@ class PlainPrinter(_ctx: Context) extends Printer {
selectionString(tp)
else
toTextPrefixOf(tp) ~ selectionString(tp)
case tp: TermParamRef =>
ParamRefNameString(tp) ~ hashStr(tp.binder) ~ ".type"
case tp: TypeParamRef =>
val suffix =
if showNestingLevel then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
---
layout: doc-page
title: "Capture Checking -- Advanced Use Cases"
nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/cc-advanced.html
title: "Capability Polymorphism -- Advanced Use Cases"
nightlyOf: https://docs.scala-lang.org/scala3/reference/experimental/capture-checking/advanced.html
---


Expand Down Expand Up @@ -75,4 +75,4 @@ By leveraging capability polymorphism, capability members, and path-dependent ca
* `Label`s store the free capabilities `C` of the `block` passed to `boundary` in their capability member `Fv`.
* When suspending on a given label, the suspension handler can capture at most the capabilities that occur freely at the `boundary` that introduced the label. That prevents mentioning nested bound labels.

[Back to Capture Checking](cc.md)
[Back to Capability Polymorphism](polymorphism.md)
Loading
Loading