Skip to content

Commit 5b04553

Browse files
committed
Introduce @capability annotations
This replaces the earlier @ability annotation. The mechanisms are different, though. @ability was an annotation on `val`s whereas `capability` is an annotation on classes.
1 parent cdaee68 commit 5b04553

File tree

11 files changed

+49
-31
lines changed

11 files changed

+49
-31
lines changed

compiler/src/dotty/tools/dotc/cc/CaptureSet.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,9 @@ object CaptureSet:
523523
tp.captureSet
524524
case tp: TermParamRef =>
525525
tp.captureSet
526-
case _: TypeRef | _: TypeParamRef =>
526+
case _: TypeRef =>
527+
if tp.classSymbol.hasAnnotation(defn.CapabilityAnnot) then universal else empty
528+
case _: TypeParamRef =>
527529
empty
528530
case CapturingType(parent, refs, _) =>
529531
recur(parent) ++ refs

compiler/src/dotty/tools/dotc/core/Definitions.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,6 +951,7 @@ class Definitions {
951951
@tu lazy val BeanPropertyAnnot: ClassSymbol = requiredClass("scala.beans.BeanProperty")
952952
@tu lazy val BooleanBeanPropertyAnnot: ClassSymbol = requiredClass("scala.beans.BooleanBeanProperty")
953953
@tu lazy val BodyAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Body")
954+
@tu lazy val CapabilityAnnot: ClassSymbol = requiredClass("scala.annotation.capability")
954955
@tu lazy val ChildAnnot: ClassSymbol = requiredClass("scala.annotation.internal.Child")
955956
@tu lazy val ContextResultCountAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ContextResultCount")
956957
@tu lazy val ProvisionalSuperClassAnnot: ClassSymbol = requiredClass("scala.annotation.internal.ProvisionalSuperClass")
@@ -995,7 +996,6 @@ class Definitions {
995996
@tu lazy val VarargsAnnot: ClassSymbol = requiredClass("scala.annotation.varargs")
996997
@tu lazy val SinceAnnot: ClassSymbol = requiredClass("scala.annotation.since")
997998
@tu lazy val RetainsAnnot: ClassSymbol = requiredClass("scala.retains")
998-
@tu lazy val AbilityAnnot: ClassSymbol = requiredClass("scala.annotation.ability")
999999

10001000
@tu lazy val JavaRepeatableAnnot: ClassSymbol = requiredClass("java.lang.annotation.Repeatable")
10011001

compiler/src/dotty/tools/dotc/core/Types.scala

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2767,7 +2767,6 @@ object Types {
27672767
def canBeTracked(using Context) =
27682768
((prefix eq NoPrefix)
27692769
|| symbol.is(ParamAccessor) && (prefix eq symbol.owner.thisType)
2770-
|| symbol.hasAnnotation(defn.AbilityAnnot)
27712770
|| isRootCapability
27722771
) && !symbol.is(Method)
27732772

compiler/src/dotty/tools/dotc/typer/CheckCaptures.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -406,8 +406,7 @@ class CheckCaptures extends Recheck:
406406
def checkNotGlobal(tree: Tree, tp: Type, allArgs: Tree*)(using Context): Unit =
407407
for ref <-tp.captureSet.elems do
408408
val isGlobal = ref match
409-
case ref: TermRef =>
410-
ref.isRootCapability || ref.prefix != NoPrefix && ref.symbol.hasAnnotation(defn.AbilityAnnot)
409+
case ref: TermRef => ref.isRootCapability
411410
case _ => false
412411
if isGlobal then
413412
val what = if ref.isRootCapability then "universal" else "global"

library/src-bootstrapped/scala/annotation/ability.scala

Lines changed: 0 additions & 9 deletions
This file was deleted.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package scala.annotation
2+
3+
/** Marks an annotated class as a capabulity.
4+
* If the annotation is present and -Ycc is set, any (possibly aliased
5+
* or refined) instance of the class type is implicitly augmented with
6+
* the universal capture set. Example
7+
*
8+
* @capability class CanThrow[T]
9+
*
10+
* THere, the capture set of any instance of `CanThrow` is assumed to be
11+
* `{*}`.
12+
*/
13+
final class capability extends StaticAnnotation

tests/disabled/pos/lazylist.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ object LazyNil extends LazyList[Nothing]:
3434
def map[A, B](xs: {*} LazyList[A], f: {*} A => B): {f, xs} LazyList[B] =
3535
xs.map(f)
3636

37-
class CC
38-
type Cap = {*} CC
37+
@annotation.capability class Cap
3938

4039
def test(cap1: Cap, cap2: Cap, cap3: Cap) =
4140
def f[T](x: LazyList[T]): LazyList[T] = if cap1 == cap1 then x else LazyNil

tests/neg-custom-args/captures/byname.scala

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
class CC
2-
type Cap = {*} CC
1+
@annotation.capability class Cap
32

43
def test(cap1: Cap, cap2: Cap) =
54
def f() = if cap1 == cap1 then g else g
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import annotation.capability
2+
3+
@capability class Cap
4+
def f1(c: Cap): {c} () => c.type = () => c // ok
5+
6+
def f2: Int =
7+
val g: {*} Boolean => Int = ???
8+
val x = g(true)
9+
x
10+
11+
def f3: Int =
12+
def g: {*} Boolean => Int = ???
13+
def h = g
14+
val x = g.apply(true)
15+
x
16+
17+
def foo() =
18+
val x: Cap = ???
19+
val y: Cap = x
20+
val x2: {x} () => Cap = ???
21+
val y2: {x} () => Cap = x2
22+
23+
val z1: {*} () => Cap = f1(x)
24+
def h[X](a: X)(b: X) = a
25+
26+
val z2 =
27+
if x == null then () => x else () => Cap()
28+
x

tests/pos-custom-args/captures/try3.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import language.experimental.erasedDefinitions
2-
import annotation.ability
2+
import annotation.capability
33
import java.io.IOException
44

55
class CT[-E] // variance is needed for correct rechecking inference

tests/pos-deep-subtype/i4036.scala

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ object A {
1111
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
1212
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
1313
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
14-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
15-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
16-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
1714
x.type
1815

1916
1: v.
@@ -25,16 +22,10 @@ object A {
2522
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
2623
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
2724
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
28-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
29-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
30-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
3125
x.T
3226

3327
val u = new B { type T = Int }
3428
u: u.
35-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
36-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
37-
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
3829
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
3930
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
4031
x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.x.
@@ -55,8 +46,5 @@ object A {
5546
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
5647
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
5748
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
58-
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
59-
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
60-
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#
6149
T#T#T#T#T#T#T#T#T#T#T#T#T#T#T#T
6250
}

0 commit comments

Comments
 (0)