@@ -6,19 +6,36 @@ import scala.quoted._
6
6
7
7
object CaptureDefs :
8
8
// these should become part of the reflect API in the distant future
9
- def retains (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.annotation.retains" )
10
- def retainsCap (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.annotation.retainsCap" )
11
- def retainsByName (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.annotation.retainsByName" )
12
- def CapsModule (using qctx : Quotes ) = qctx.reflect.Symbol .requiredPackage(" scala.caps" )
13
- def captureRoot (using qctx : Quotes ) = qctx.reflect.Symbol .requiredPackage(" scala.caps.cap" )
14
- def Caps_Capability (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.caps.Capability" )
15
- def Caps_CapSet (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.caps.CapSet" )
16
- def Caps_Mutable (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.caps.Mutable" )
17
- def Caps_SharedCapability (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.caps.SharedCapability" )
18
-
19
- def UseAnnot (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.caps.use" )
20
- def ConsumeAnnot (using qctx : Quotes ) = qctx.reflect.Symbol .requiredClass(" scala.caps.consume" )
21
-
9
+ def retains (using qctx : Quotes ) =
10
+ qctx.reflect.Symbol .requiredClass(" scala.annotation.retains" )
11
+ def retainsCap (using qctx : Quotes ) =
12
+ qctx.reflect.Symbol .requiredClass(" scala.annotation.retainsCap" )
13
+ def retainsByName (using qctx : Quotes ) =
14
+ qctx.reflect.Symbol .requiredClass(" scala.annotation.retainsByName" )
15
+ def CapsModule (using qctx : Quotes ) =
16
+ qctx.reflect.Symbol .requiredPackage(" scala.caps" )
17
+ def captureRoot (using qctx : Quotes ) =
18
+ qctx.reflect.Symbol .requiredPackage(" scala.caps.cap" )
19
+ def Caps_Capability (using qctx : Quotes ) =
20
+ qctx.reflect.Symbol .requiredClass(" scala.caps.Capability" )
21
+ def Caps_CapSet (using qctx : Quotes ) =
22
+ qctx.reflect.Symbol .requiredClass(" scala.caps.CapSet" )
23
+ def Caps_Mutable (using qctx : Quotes ) =
24
+ qctx.reflect.Symbol .requiredClass(" scala.caps.Mutable" )
25
+ def Caps_SharedCapability (using qctx : Quotes ) =
26
+ qctx.reflect.Symbol .requiredClass(" scala.caps.SharedCapability" )
27
+ def UseAnnot (using qctx : Quotes ) =
28
+ qctx.reflect.Symbol .requiredClass(" scala.caps.use" )
29
+ def ConsumeAnnot (using qctx : Quotes ) =
30
+ qctx.reflect.Symbol .requiredClass(" scala.caps.consume" )
31
+ def ReachCapabilityAnnot (using qctx : Quotes ) =
32
+ qctx.reflect.Symbol .requiredClass(" scala.annotation.internal.reachCapability" )
33
+ def RootCapabilityAnnot (using qctx : Quotes ) =
34
+ qctx.reflect.Symbol .requiredClass(" scala.caps.internal.rootCapability" )
35
+ def ReadOnlyCapabilityAnnot (using qctx : Quotes ) =
36
+ qctx.reflect.Symbol .requiredClass(" scala.annotation.internal.readOnlyCapability" )
37
+ def RequiresCapabilityAnnot (using qctx : Quotes ) =
38
+ qctx.reflect.Symbol .requiredClass(" scala.annotation.internal.requiresCapability" )
22
39
end CaptureDefs
23
40
24
41
extension (using qctx : Quotes )(ann : qctx.reflect.Symbol )
@@ -29,24 +46,38 @@ extension (using qctx: Quotes)(ann: qctx.reflect.Symbol)
29
46
/** This symbol is one of `retains`, `retainsCap`, or `retainsByName` */
30
47
def isRetainsLike : Boolean =
31
48
ann.isRetains || ann == CaptureDefs .retainsByName
49
+
50
+ def isReachCapabilityAnnot : Boolean =
51
+ ann == CaptureDefs .ReachCapabilityAnnot
32
52
end extension
33
53
34
54
extension (using qctx : Quotes )(tpe : qctx.reflect.TypeRepr )
35
55
def isCaptureRoot : Boolean = tpe.termSymbol == CaptureDefs .captureRoot
36
56
end extension
37
57
58
+ object ReachCapability :
59
+ def unapply (using qctx : Quotes )(ty : qctx.reflect.TypeRepr ): Option [qctx.reflect.TypeRepr ] =
60
+ import qctx .reflect ._
61
+ ty match
62
+ case AnnotatedType (base, Apply (Select (New (annot), _), Nil )) if annot.symbol.isReachCapabilityAnnot =>
63
+ Some (base)
64
+ case _ => None
65
+ end ReachCapability
66
+
38
67
/** Decompose capture sets in the union-type-encoding into the sequence of atomic `TypeRepr`s.
39
68
* Returns `None` if the type is not a capture set.
40
69
*/
41
70
def decomposeCaptureRefs (using qctx : Quotes )(typ0 : qctx.reflect.TypeRepr ): Option [List [qctx.reflect.TypeRepr ]] =
42
71
import qctx .reflect ._
43
72
val buffer = collection.mutable.ListBuffer .empty[TypeRepr ]
73
+ def include (t : TypeRepr ): Boolean = { buffer += t; true }
44
74
def traverse (typ : TypeRepr ): Boolean =
45
75
typ match
46
- case OrType (t1, t2) => traverse(t1) && traverse(t2)
47
- case t @ ThisType (_) => buffer += t; true
48
- case t @ TermRef (_, _) => buffer += t; true
49
- case t @ ParamRef (_, _) => buffer += t; true
76
+ case OrType (t1, t2) => traverse(t1) && traverse(t2)
77
+ case t @ ThisType (_) => include(t)
78
+ case t @ TermRef (_, _) => include(t)
79
+ case t @ ParamRef (_, _) => include(t)
80
+ case t @ ReachCapability (_) => include(t)
50
81
case t if t.typeSymbol == defn.NothingClass => true
51
82
// TODO: are atoms only ever the above? Then we could refine the return type
52
83
case _ => report.warning(s " Unexpected type tree $typ while trying to extract capture references from $typ0" ); false // TODO remove warning eventually
@@ -66,22 +97,4 @@ object CapturingType:
66
97
case AnnotatedType (base, Apply (Select (New (annot), _), Nil )) if annot.symbol == CaptureDefs .retainsCap =>
67
98
Some ((base, List (CaptureDefs .captureRoot.termRef)))
68
99
case _ => None
69
- end CapturingType
70
-
71
- def renderCaptureSet (using qctx : Quotes )(refs : List [qctx.reflect.TypeRepr ]): List [SignaturePart ] =
72
- import dotty .tools .scaladoc .tasty .NameNormalizer ._
73
- import qctx .reflect ._
74
- refs match
75
- case List (ref) if ref.isCaptureRoot => List (Keyword (" ^" ))
76
- case refs =>
77
- val res0 = refs.map { ref =>
78
- ref match
79
- case ThisType (_) => List (Keyword (" this" ))
80
- case TermRef (_, sym) => List (Plain (sym)) // FIXME: use type other than Plain, can we have clickable links to say, caps.cap and other things?
81
- case pf @ ParamRef (tpe, i) => List (Plain (tpe.asInstanceOf [MethodType ].paramNames(i))) // FIXME: not sure if this covers all cases
82
- case _ => List (Plain (" <unknown>" ))
83
- }
84
- val res1 = res0 match
85
- case Nil => Nil
86
- case other => other.reduce((r, e) => r ++ (List (Plain (" , " )) ++ e))
87
- Keyword (" ^" ) :: Plain (" {" ) :: (res1 ++ List (Plain (" }" )))
100
+ end CapturingType
0 commit comments