Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 24e8ecc

Browse files
authoredMay 12, 2025··
New Syntax for Capture Variables and Explicit Capture Polymorphism v3 (#23063)
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 ```scala 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: ```scala 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: ```scala 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 - [x] Bullet-proof the "can avoid the hat" for binders scheme. - [x] Grammar doc. - [x] Update language reference. - [x] Port new tests. - [x] Clarify when and where to produce attachments. - [x] Forbid nonsense intervals mixing capture sets and types.
2 parents f784625 + eeeeb33 commit 24e8ecc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+894
-253
lines changed
 

‎compiler/src/dotty/tools/dotc/ast/Desugar.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ object desugar {
642642
.withMods(mods & (GivenOrImplicit | Erased | hasDefault | Tracked) | Param)
643643
}
644644

645-
/** Desugar type def (not param): Under x.moduliity this can expand
645+
/** Desugar type def (not param): Under x.modularity this can expand
646646
* context bounds, which are expanded to evidence ValDefs. These will
647647
* ultimately map to deferred givens.
648648
*/

‎compiler/src/dotty/tools/dotc/ast/Trees.scala

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ object Trees {
3434

3535
val SyntheticUnit: Property.StickyKey[Unit] = Property.StickyKey()
3636

37+
/** Property key for marking capture-set variables and members */
38+
val CaptureVar: Property.StickyKey[Unit] = Property.StickyKey()
39+
3740
/** Trees take a parameter indicating what the type of their `tpe` field
3841
* is. Two choices: `Type` or `Untyped`.
3942
* Untyped trees have type `Tree[Untyped]`.

0 commit comments

Comments
 (0)
Please sign in to comment.