dotty.tools.dotc.cc

Members list

Type members

Classlikes

Attributes

Supertypes
class Object
trait Matchable
class Any
Known subtypes
class CCState

Capture checking state, which is known to other capture checking components

Capture checking state, which is known to other capture checking components

Attributes

Companion
object
Supertypes
class Object
trait Matchable
class Any
object CCState

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
CCState.type
object CapsOfApply

An extractor for caps.capsOf[X], which is used to express a generic capture set as a tree in a @retains annotation.

An extractor for caps.capsOf[X], which is used to express a generic capture set as a tree in a @retains annotation.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
case class CaptureAnnotation(refs: CaptureSet, boxed: Boolean)(cls: Symbol) extends Annotation

An annotation representing a capture set and whether it is boxed. It simulates a normal @retains annotation except that it is more efficient, supports variables as capture sets, and adds a boxed flag. These annotations are created during capture checking. Before that there are only regular @retains and @retainsByName annotations.

An annotation representing a capture set and whether it is boxed. It simulates a normal @retains annotation except that it is more efficient, supports variables as capture sets, and adds a boxed flag. These annotations are created during capture checking. Before that there are only regular @retains and @retainsByName annotations.

Value parameters

boxed

whether the type carrying the annotation is boxed

cls

the underlying class (either annotation.retains or annotation.retainsByName)

refs

the capture set

Attributes

Supertypes
trait Serializable
trait Product
trait Equals
class Annotation
trait Showable
class Object
trait Matchable
class Any
Show all
trait CaptureRef extends TypeProxy, ValueType

A trait for references in CaptureSets. These can be NamedTypes, ThisTypes or ParamRefs, as well as two kinds of AnnotatedTypes representing reach and maybe capabilities.

A trait for references in CaptureSets. These can be NamedTypes, ThisTypes or ParamRefs, as well as two kinds of AnnotatedTypes representing reach and maybe capabilities.

Attributes

Supertypes
trait ValueType
trait TermType
class TypeProxy
class Type
trait Showable
trait Hashable
class Object
trait Matchable
class Any
Show all
Known subtypes
sealed abstract class CaptureSet extends Showable

A class for capture sets. Capture sets can be constants or variables. Capture sets support inclusion constraints <:< where <:< is subcapturing.

A class for capture sets. Capture sets can be constants or variables. Capture sets support inclusion constraints <:< where <:< is subcapturing.

They also allow

  • mapping with functions from elements to capture sets
  • filtering with predicates on elements
  • intersecting wo capture sets

That is, constraints can be of the forms

cs1 <:< cs2 cs1 = ∪ {f(x) | x ∈ cs2} where f is a function from capture references to capture sets. cs1 = ∪ {x | x ∈ cs2, p(x)} where p is a predicate on capture references cs1 = cs2 ∩ cs2

We call the resulting constraint system "monadic set constraints". To support capture propagation across maps, mappings are supported only if the mapped function is either a bijection or if it is idempotent on capture references (c.f. doc comment on map below).

Attributes

Companion
object
Supertypes
trait Showable
class Object
trait Matchable
class Any
Known subtypes
class Const
object Fluid
class Var
class DerivedVar
class BiMapped
class Filtered
class Diff
class Mapped
class RefiningVar
Show all
object CaptureSet

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
CaptureSet.type
object CapturingType

A (possibly boxed) capturing type. This is internally represented as an annotated type with a @retains or @retainsByName annotation, but the extractor will succeed only at phase CheckCaptures. That way, we can ignore caturing information until phase CheckCaptures since it is wrapped in a plain annotation.

A (possibly boxed) capturing type. This is internally represented as an annotated type with a @retains or @retainsByName annotation, but the extractor will succeed only at phase CheckCaptures. That way, we can ignore caturing information until phase CheckCaptures since it is wrapped in a plain annotation.

The same trick does not work for the boxing information. Boxing is context dependent, so we have to add that information in the Setup step preceding CheckCaptures. Boxes are added for all type arguments of methods. For type arguments of applied types a different strategy is used where we box arguments of applied types that are not functions when accessing the argument.

An alternative strategy would add boxes also to arguments of applied types during setup. But this would have to be done for all possibly accessibly types from the compiled units as well as their dependencies. It's difficult to do this in a DenotationTransformer without accidentally forcing symbol infos. That's why this alternative was not implemented. If we would go back on this it would make sense to also treat captuyring types different from annotations and to generate them all during Setup and in DenotationTransformers.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
object CheckCaptures

The capture checker

The capture checker

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type

Attributes

Companion
object
Supertypes
class Recheck
class Phase
class Object
trait Matchable
class Any
Show all
Self type
class CleanupRetains(using x$1: Context) extends TypeMap

Drop retains annotations in the type.

Drop retains annotations in the type.

Attributes

Supertypes
class TypeMap
trait Type => Type
class Object
trait Matchable
class Any
Show all
trait ConservativeFollowAliasMap(using x$1: Context) extends TypeMap

Offers utility method to be used for type maps that follow aliases

Offers utility method to be used for type maps that follow aliases

Attributes

Supertypes
class TypeMap
trait Type => Type
class Object
trait Matchable
class Any
Show all
object ContainsImpl

An extractor for a contains argument

An extractor for a contains argument

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
object ContainsParam

An extractor for a contains parameter

An extractor for a contains parameter

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
object Existential

Handling existentials in CC:

Handling existentials in CC:

  • We generally use existentials only in function and method result types
  • All occurrences of an EX-bound variable appear co-variantly in the bound type

In Setup:

  • Convert occurrences of cap in function results to existentials. Precise rules below.

  • Conversions are done in two places:

    • As part of mapping from local types of parameters and results to infos of methods. The local types just use cap, whereas the result type in the info uses EX-bound variables.
    • When converting functions or methods appearing in explicitly declared types. Here again, we only replace cap's in fucntion results.
  • Conversion is done with a BiTypeMap in Existential.mapCap.

In reckeckApply and recheckTypeApply:

  • If an EX is toplevel in the result type, replace its bound variable occurrences with cap.

Level checking and avoidance:

  • Environments, capture refs, and capture set variables carry levels

    • levels start at 0
    • The level of a block or template statement sequence is one higher than the level of its environment
    • The level of a TermRef is the level of the environment where its symbol is defined.
    • The level of a ThisType is the level of the statements of the class to which it beloongs.
    • The level of a TermParamRef is currently -1 (i.e. TermParamRefs are not yet checked using this system)
    • The level of a capture set variable is the level of the environment where it is created.
  • Variables also carry info whether they accept cap or not. Variables introduced under a box don't, the others do.

  • Capture set variables do not accept elements of level higher than the variable's level

  • We use avoidance to heal such cases: If the level-incorrect ref appears

    • covariantly: widen to underlying capture set, reject if that is cap and the variable does not allow it
    • contravariantly: narrow to {}
    • invarianty: reject with error

In cv-computation (markFree):

  • Reach capabilities x* of a parameter x cannot appear in the capture set of the owning method. They have to be widened to dcs(x), or, where this is not possible, it's an error.

In box adaptation:

  • Check that existential variables are not boxed or unboxed.

Subtype rules

  • new alphabet: existentially bound variables a.

  • they can be stored in environments Gamma.

  • they are alpha-renable, usual hygiene conditions apply

    Gamma |- EX a.T <: U if Gamma, a |- T <: U

    Gamma |- T <: EX a.U if exists capture set C consisting of capture refs and ex-bound variables bound in Gamma such that Gamma |- T <: [a := C]U

Representation:

EX a.T[a] is represented as a dependent function type

  (a: Exists) => T[a]]

where Exists is defined in caps like this:

  sealed trait Exists extends Capability

The defn.RefinedFunctionOf extractor will exclude existential types from its results, so only normal refined functions match.

Let boundvar(ex) be the TermParamRef defined by the existential type ex.

Subtype checking algorithm, general scheme:

Maintain two structures in TypeComparer:

openExistentials: List[TermParamRef]
assocExistentials: Map[TermParamRef, List[TermParamRef]]

openExistentials corresponds to the list of existential variables stored in the environment. assocExistentials maps existential variables bound by existentials appearing on the right to the value of openExistentials at the time when the existential on the right was dropped.

Subtype checking algorithm, steps to add for tp1 <:< tp2:

If tp1 is an existential EX a.tp1a:

  val saved = openExistentials
  openExistentials = boundvar(tp1) :: openExistentials
  try tp1a <:< tp2
  finally openExistentials = saved

If tp2 is an existential EX a.tp2a:

  val saved = assocExistentials
  assocExistentials = assocExistentials + (boundvar(tp2) -> openExistentials)
  try tp1 <:< tp2a
  finally assocExistentials = saved

If tp2 is an existentially bound variable: assocExistentials(tp2).isDefined && (assocExistentials(tp2).contains(tp1) || tp1 is not existentially bound)

Subtype checking algorithm, comparing two capture sets CS1 <:< CS2:

We need to map the (possibly to-be-added) existentials in CS1 to existentials in CS2 so that we can compare them. We use assocExistentals for that: To map an EX-variable V1 in CS1, pick the last (i.e. outermost, leading to the smallest type) EX-variable in assocExistentials that has V1 in its possible instances. To go the other way (and therby produce a BiTypeMap), map an EX-variable V2 in CS2 to the first (i.e. innermost) EX-variable it can be instantiated to. If either direction is not defined, we choose a special "bad-existetal" value that represents and out-of-scope existential. This leads to failure of the comparison.

Existential source syntax:

Existential types are ususally not written in source, since we still allow the ^ syntax that can express most of them more concesely (see below for translation rules). But we should also allow to write existential types explicity, even if it ends up mainly for debugging. To express them, we use the encoding with Exists, so a typical expression of an existential would be

  (x: Exists) => A ->{x} B

Existential types can only at the top level of the result type of a function or method.

Restrictions on Existential Types: (to be implemented if we want to keep the source syntax for users).

- An existential capture ref must be the only member of its set. This is
  intended to model the idea that existential variables effectibely range
  over capture sets, not capture references. But so far our calculus
  and implementation does not yet acoommodate first-class capture sets.
- Existential capture refs must appear co-variantly in their bound type

So the following would all be illegal:

  EX x.C^{x, io}            // error: multiple members
  EX x.() => EX y.C^{x, y}  // error: multiple members
  EX x.C^{x} ->{x} D        // error: contra-variant occurrence
  EX x.Set[C^{x}]           // error: invariant occurrence

Expansion of ^:

We expand all occurrences of cap in the result types of functions or methods to existentially quantified types. Nested scopes are expanded before outer ones.

The expansion algorithm is then defined as follows:

1. In a result type, replace every occurrence of ^ with a fresh existentially
   bound variable and quantify over all variables such introduced.

2. After this step, type aliases are expanded. If aliases have aliases in arguments,
   the outer alias is expanded before the aliases in the arguments. Each time an alias
   is expanded that reveals a `^`, apply step (1).

3. The algorithm ends when no more alieases remain to be expanded.

Examples:

- `A => B` is an alias type that expands to `(A -> B)^`, therefore
  `() -> A => B` expands to `() -> EX c. A ->{c} B`.

- `() => Iterator[A => B]` expands to `() => EX c. Iterator[A ->{c} B]`

- `A -> B^` expands to `A -> EX c.B^{c}`.

- If we define `type Fun[T] = A -> T`, then `() -> Fun[B^]` expands to `() -> EX c.Fun[B^{c}]`, which
  dealiases to `() -> EX c.A -> B^{c}`.

- If we define

    type F = A -> Fun[B^]

  then the type alias expands to

    type F = A -> EX c.A -> B^{c}

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
trait FollowAliasesMap(using x$1: Context) extends TypeMap

A typemap that follows aliases and keeps their transformed results if there is a change.

A typemap that follows aliases and keeps their transformed results if there is a change.

Attributes

Supertypes
class TypeMap
trait Type => Type
class Object
trait Matchable
class Any
Show all

An extractor for all kinds of function types as well as method and poly types. It includes aliases of function types such as =>. TODO: Can we do without?

An extractor for all kinds of function types as well as method and poly types. It includes aliases of function types such as =>. TODO: Can we do without?

Attributes

Returns

1st half: The argument types or empty if this is a type function 2nd half: The result type

Supertypes
class Object
trait Matchable
class Any
Self type
class IllegalCaptureRef(tpe: Type)(using x$2: Context) extends Exception

An exception thrown if a @retains argument is not syntactically a CaptureRef

An exception thrown if a @retains argument is not syntactically a CaptureRef

Attributes

Supertypes
class Exception
class Throwable
trait Serializable
class Object
trait Matchable
class Any
Show all

An extractor for ref @maybeCapability, which is used to express the maybe capability ref? as a type.

An extractor for ref @maybeCapability, which is used to express the maybe capability ref? as a type.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type

An extractor for ref @annotation.internal.reachCapability, which is used to express the reach capability ref* as a type.

An extractor for ref @annotation.internal.reachCapability, which is used to express the reach capability ref* as a type.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type

An extractor for caps.reachCapability(ref), which is used to express a reach capability as a tree in a @retains annotation.

An extractor for caps.reachCapability(ref), which is used to express a reach capability as a tree in a @retains annotation.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
object RetainingType

A builder and extractor for annotated types with @retains or @retainsByName annotations.

A builder and extractor for annotated types with @retains or @retainsByName annotations.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
object Setup

Attributes

Companion
class
Supertypes
class Object
trait Matchable
class Any
Self type
Setup.type

Phase that sets up everthing for capture checking.

Phase that sets up everthing for capture checking.

A tree traverser that prepares a compilation unit to be capture checked. It does the following:

  • For every inferred type, drop any retains annotations, add capture sets to all its parts, add refinements to class types and function types. (c.f. mapInferred)
  • For explicit capturing types, expand throws aliases to the underlying (pure) function, and add some implied capture sets to curried functions (c.f. expandThrowsAlias, expandAbbreviations).
  • Add capture sets to self types of classes and objects, unless the self type was written explicitly.
  • Box the types of mutable variables and type arguments to methods (type arguments of types are boxed on access).
  • Link the external types of val and def symbols with the inferred types based on their parameter symbols.

Attributes

Companion
object
Supertypes
trait SetupAPI
class PreRecheck
class Phase
class Object
trait Matchable
class Any
Show all
Self type
trait SetupAPI

Operations accessed from CheckCaptures

Operations accessed from CheckCaptures

Attributes

Supertypes
class Object
trait Matchable
class Any
Known subtypes
class Setup

Attributes

Supertypes
trait CaptureRef
trait ValueType
trait TermType
class TypeProxy
class Type
trait Showable
trait Hashable
class Object
trait Matchable
class Any
Show all
Known subtypes
class TermParamRef
class TermRef
class ThisType
object Synthetics

Classification and transformation methods for function methods and synthetic case class methods that need to be treated specially. In particular, compute capturing types for some of these methods which have inferred (result-)types that need to be established under separate compilation.

Classification and transformation methods for function methods and synthetic case class methods that need to be treated specially. In particular, compute capturing types for some of these methods which have inferred (result-)types that need to be established under separate compilation.

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
Synthetics.type
object ccConfig

Attributes

Supertypes
class Object
trait Matchable
class Any
Self type
ccConfig.type

Value members

Concrete methods

def ccState(using Context): CCState

The currently valid CCState

The currently valid CCState

Attributes

def depFun(args: List[Type], resultType: Type, isContextual: Boolean, paramNames: List[TermName])(using Context): Type

A dependent function type with given arguments and result type TODO Move somewhere else where we treat all function type related ops together.

A dependent function type with given arguments and result type TODO Move somewhere else where we treat all function type related ops together.

Attributes

Are we at checkCaptures phase?

Are we at checkCaptures phase?

Attributes

Are we at checkCaptures or Setup phase?

Are we at checkCaptures or Setup phase?

Attributes

Extensions

Extensions

extension (self: Type)
def derivedFunctionOrMethod(argTypes: List[Type], resType: Type)(using Context): Type

If tp is a function or method, a type of the same kind with the given argument and result types.

If tp is a function or method, a type of the same kind with the given argument and result types.

Attributes

extension (sym: Symbol)

Does this symbol allow results carrying the universal capability? Currently this is true only for function type applies (since their results are unboxed) and erasedValue since this function is magic in that is allows to conjure global capabilies from nothing (aside: can we find a more controlled way to achieve this?). But it could be generalized to other functions that so that they can take capability classes as arguments.

Does this symbol allow results carrying the universal capability? Currently this is true only for function type applies (since their results are unboxed) and erasedValue since this function is magic in that is allows to conjure global capabilies from nothing (aside: can we find a more controlled way to achieve this?). But it could be generalized to other functions that so that they can take capability classes as arguments.

Attributes

A class is pure if:

A class is pure if:

  • one its base types has an explicitly declared self type with an empty capture set
  • or it is a value class
  • or it is an exception
  • or it is one of Nothing, Null, or String

Attributes

It's a parameter accessor that is not annotated @constructorOnly or @uncheckedCaptures

It's a parameter accessor that is not annotated @constructorOnly or @uncheckedCaptures

Attributes

def isRetains(using Context): Boolean

This symbol is one of retains or retainsCap

This symbol is one of retains or retainsCap

Attributes

This symbol is one of retains, retainsCap, orretainsByName

This symbol is one of retains, retainsCap, orretainsByName

Attributes

def isUseParam(using Context): Boolean

sym is annotated @use or it is a type parameter with a matching

sym is annotated @use or it is a type parameter with a matching

Attributes

When applying sym, would the result type be unboxed? This is the case if the result type contains a top-level reference to an enclosing class or method type parameter and the method does not allow root capture. If the type parameter is instantiated to a boxed type, that type would have to be unboxed in the method's result.

When applying sym, would the result type be unboxed? This is the case if the result type contains a top-level reference to an enclosing class or method type parameter and the method does not allow root capture. If the type parameter is instantiated to a boxed type, that type would have to be unboxed in the method's result.

Attributes

extension (tp: Type)
def boxed(using Context): Type

If this is a unboxed capturing type with nonempty capture set, its boxed version. Or, if type is a TypeBounds of capturing types, the version where the bounds are boxed. The identity for all other types.

If this is a unboxed capturing type with nonempty capture set, its boxed version. Or, if type is a TypeBounds of capturing types, the version where the bounds are boxed. The identity for all other types.

Attributes

The capture set consisting of all top-level captures of tp that appear under a box. Unlike for boxed this also considers parents of capture types, unions and intersections, and type proxies other than abstract types.

The capture set consisting of all top-level captures of tp that appear under a box. Unlike for boxed this also considers parents of capture types, unions and intersections, and type proxies other than abstract types.

Attributes

final def captureSet(using Context): CaptureSet

The capture set of a type. This is:

The capture set of a type. This is:

  • For trackable capture references: The singleton capture set consisting of just the reference, provided the underlying capture set of their info is not empty.
  • For other capture references: The capture set of their info
  • For all other types: The result of CaptureSet.ofType

Attributes

def capturing(ref: CaptureRef)(using Context): Type

A type capturing ref

A type capturing ref

Attributes

def capturing(cs: CaptureSet)(using Context): Type

A type capturing the capture set cs. If this type is already a capturing type the two capture sets are combined.

A type capturing the capture set cs. If this type is already a capturing type the two capture sets are combined.

Attributes

def deepCaptureSet(includeTypevars: Boolean)(using Context): CaptureSet

The deep capture set of a type. This is by default the union of all covariant capture sets embedded in the widened type, as computed by CaptureSet.ofTypeDeeply. If that set is nonempty, and the type is a singleton capability x or a reach capability x*, the deep capture set can be narrowed to{x*}.

The deep capture set of a type. This is by default the union of all covariant capture sets embedded in the widened type, as computed by CaptureSet.ofTypeDeeply. If that set is nonempty, and the type is a singleton capability x or a reach capability x*, the deep capture set can be narrowed to{x*}.

Attributes

def derivedCapturingType(parent: Type, refs: CaptureSet)(using Context): Type

Attributes

Tests whether the type derives from caps.Capability, which means references of this type are maximal capabilities.

Tests whether the type derives from caps.Capability, which means references of this type are maximal capabilities.

Attributes

Drop @retains annotations everywhere

Drop @retains annotations everywhere

Attributes

def forceBoxStatus(boxed: Boolean)(using Context): Type

If this type is a capturing type, the version with boxed statues as given by boxed. If it is a TermRef of a capturing type, and the box status flips, widen to a capturing type that captures the TermRef.

If this type is a capturing type, the version with boxed statues as given by boxed. If it is a TermRef of a capturing type, and the box status flips, widen to a capturing type that captures the TermRef.

Attributes

Is type known to be always pure by its class structure? In that case, adding a capture set to it would not make sense.

Is type known to be always pure by its class structure? In that case, adding a capture set to it would not make sense.

Attributes

Is the box status of tp and tp2 compatible? I.ee they are box boxed, or both unboxed, or one of them has an empty capture set.

Is the box status of tp and tp2 compatible? I.ee they are box boxed, or both unboxed, or one of them has an empty capture set.

Attributes

Is the boxedCaptureSet of this type nonempty?

Is the boxedCaptureSet of this type nonempty?

Attributes

final def isParamPath(using Context): Boolean
final def isTrackableRef(using Context): Boolean

Is this type a CaptureRef that can be tracked? This is true for

Is this type a CaptureRef that can be tracked? This is true for

  • all ThisTypes and all TermParamRef,
  • stable TermRefs with NoPrefix or ThisTypes as prefixes,
  • the root capability caps.cap
  • abstract or parameter TypeRefs that derive from caps.CapSet
  • annotated types that represent reach or maybe capabilities

Attributes

def level(using Context): Level
def maybe(using Context): CaptureRef

If x is a capture ref, its maybe capability x?, represented internally as x @maybeCapability. x? stands for a capability x that might or might not be part of a capture set. We have {} <: {x?} <: {x}. Maybe capabilities cannot be propagated between sets. If a <: b and a acquires x? then x is propagated to b as a conservative approximation.

If x is a capture ref, its maybe capability x?, represented internally as x @maybeCapability. x? stands for a capability x that might or might not be part of a capture set. We have {} <: {x?} <: {x}. Maybe capabilities cannot be propagated between sets. If a <: b and a acquires x? then x is propagated to b as a conservative approximation.

Maybe capabilities should only arise for capture sets that appear in invariant position in their surrounding type. They are similar to TypeBunds types, but restricted to capture sets. For instance,

Array[C^{x?}]

should be morally equivalent to

Array[_ >: C^{} <: C^{x}]

but it has fewer issues with type inference.

Attributes

final def pathOwner(using Context): Symbol

If this part starts with C.this, the class C. Otherwise, if it starts with a reference r, r's owner. Otherwise NoSymbol.

If this part starts with C.this, the class C. Otherwise, if it starts with a reference r, r's owner. Otherwise NoSymbol.

Attributes

final def pathRoot(using Context): Type

The first element of this path type

The first element of this path type

Attributes

def reach(using Context): CaptureRef

If x is a capture ref, its reach capability x*, represented internally as x @reachCapability. x* stands for all capabilities reachable through x". We have {x} <: {x*} <: dcs(x)} where the deep capture set dcs(x) of x is the union of all capture sets that appear in covariant position in the type of x. If x and y are different variables then {x*} and {y*} are unrelated.

If x is a capture ref, its reach capability x*, represented internally as x @reachCapability. x* stands for all capabilities reachable through x". We have {x} <: {x*} <: dcs(x)} where the deep capture set dcs(x) of x is the union of all capture sets that appear in covariant position in the type of x. If x and y are different variables then {x*} and {y*} are unrelated.

Attributes

Map capturing type to their parents. Capturing types accessible via dealising are also stripped.

Map capturing type to their parents. Capturing types accessible via dealising are also stripped.

Attributes

def unboxed(using Context): Type

If this is a unboxed capturing type with nonempty capture set, its boxed version. Or, if type is a TypeBounds of capturing types, the version where the bounds are boxed. The identity for all other types.

If this is a unboxed capturing type with nonempty capture set, its boxed version. Or, if type is a TypeBounds of capturing types, the version where the bounds are boxed. The identity for all other types.

Attributes

def withReachCaptures(ref: Type)(using Context): Type

If ref is a trackable capture ref, and tp has only covariant occurrences of a universal capture set, replace all these occurrences by {ref*}. This implements the new aspect of the (Var) rule, which can now be stated as follows:

If ref is a trackable capture ref, and tp has only covariant occurrences of a universal capture set, replace all these occurrences by {ref*}. This implements the new aspect of the (Var) rule, which can now be stated as follows:

x: T in E

E |- x: T'

where T' is T with (1) the toplevel capture set replaced by {x} and (2) all covariant occurrences of cap replaced by x*, provided there are no occurrences in T at other variances. (1) is standard, whereas (2) is new.

For (2), multiple-flipped covariant occurrences of cap won't be replaced. In other words,

  • For xs: List[File^] ==> List[File^{xs*}], the cap is replaced;
  • while f: [R] -> (op: File^ => R) -> R remains unchanged.

Without this restriction, the signature of functions like withFile:

(path: String) -> [R] -> (op: File^ => R) -> R

could be refined to

(path: String) -> [R] -> (op: File^{withFile*} => R) -> R

which is clearly unsound.

Why is this sound? Covariant occurrences of cap must represent capabilities that are reachable from x, so they are included in the meaning of {x*}. At the same time, encapsulation is still maintained since no covariant occurrences of cap are allowed in instance types of type variables.

Attributes

extension (tp: AnnotatedType)
def isBoxed(using Context): Boolean

Is this a boxed capturing type?

Is this a boxed capturing type?

Attributes

extension (tree: Tree)

The arguments of a @retains, @retainsCap or @retainsByName annotation

The arguments of a @retains, @retainsCap or @retainsByName annotation

Attributes

Map tree with CaptureRef type to its type, map CapSet^{refs} to the refs references, throw IllegalCaptureRef otherwise

Map tree with CaptureRef type to its type, map CapSet^{refs} to the refs references, throw IllegalCaptureRef otherwise

Attributes

Convert a @retains or @retainsByName annotation tree to the capture set it represents. For efficience, the result is cached as an Attachment on the tree.

Convert a @retains or @retainsByName annotation tree to the capture set it represents. For efficience, the result is cached as an Attachment on the tree.

Attributes