@@ -3,7 +3,10 @@ package dotc
33package cc
44
55import core .*
6+ import Decorators .*
67import Types .* , Symbols .* , Contexts .*
8+ import NameKinds .UniqueName
9+ import util .SimpleIdentityMap
710
811/** A (possibly boxed) capturing type. This is internally represented as an annotated type with a @retains
912 * or @retainsByName annotation, but the extractor will succeed only at phase CheckCaptures.
@@ -40,12 +43,14 @@ object CapturingType:
4043 /** An extractor that succeeds only during CheckCapturingPhase. Boxing statis is
4144 * returned separately by CaptureOps.isBoxed.
4245 */
43- def unapply (tp : AnnotatedType )(using Context ): Option [(Type , CaptureSet )] =
46+ def unapply (tp : Type )(using Context ): Option [(Type , CaptureSet )] =
4447 if ctx.phase == Phases .checkCapturesPhase
45- && tp.annot.symbol == defn.RetainsAnnot
4648 && ! ctx.mode.is(Mode .IgnoreCaptures )
4749 then
48- EventuallyCapturingType .unapply(tp)
50+ tp match
51+ case Annotated (parent, cs) => Some (parent, cs)
52+ case Capability (parent, cs) => Some (parent, cs)
53+ case _ => None
4954 else None
5055
5156 /** Check whether a type is uncachable when computing `baseType`.
@@ -58,15 +63,69 @@ object CapturingType:
5863 ctx.phase == Phases .checkCapturesPhase &&
5964 (Setup .isDuringSetup || ctx.mode.is(Mode .IgnoreCaptures ) && tp.isEventuallyCapturingType)
6065
66+ object Annotated :
67+ def unapply (tp : AnnotatedType )(using Context ): Option [(Type , CaptureSet )] =
68+ if ctx.phase == Phases .checkCapturesPhase
69+ && ! ctx.mode.is(Mode .IgnoreCaptures )
70+ && tp.annot.symbol == defn.RetainsAnnot
71+ then
72+ EventuallyCapturingType .unapplyAnnot(tp)
73+ else None
74+
75+ object Capability :
76+ def unapply (tp : Type )(using Context ): Option [(Type , CaptureSet )] =
77+ if ctx.phase == Phases .checkCapturesPhase
78+ && ! ctx.mode.is(Mode .IgnoreCaptures )
79+ then
80+ EventuallyCapturingType .unapplyCap(tp)
81+ else None
82+
6183end CapturingType
6284
85+
6386/** An extractor for types that will be capturing types at phase CheckCaptures. Also
6487 * included are types that indicate captures on enclosing call-by-name parameters
6588 * before phase ElimByName.
6689 */
6790object EventuallyCapturingType :
6891
69- def unapply (tp : AnnotatedType )(using Context ): Option [(Type , CaptureSet )] =
92+ object Annotated :
93+ def unapply (tp : AnnotatedType )(using Context ): Option [(Type , CaptureSet )] = unapplyAnnot(tp)
94+
95+ object Capability :
96+ def unapply (tp : TypeRef )(using Context ): Option [(Type , CaptureSet )] = unapplyCap(tp)
97+
98+ private var pureCapClassSymCache : SimpleIdentityMap [ClassSymbol , ClassSymbol ] = SimpleIdentityMap .empty
99+
100+ private def createPureSymbolOf (csym : ClassSymbol )(using Context ): ClassSymbol =
101+ csym.copy(flags = csym.flags | Flags .CapabilityBase ).asClass
102+
103+ private def pureSymbolOf (csym : ClassSymbol )(using Context ): ClassSymbol =
104+ pureCapClassSymCache(csym) match
105+ case psym : ClassSymbol => psym
106+ case null =>
107+ val sym = createPureSymbolOf(csym)
108+ pureCapClassSymCache = pureCapClassSymCache.updated(csym, sym)
109+ sym
110+
111+ def unapply (tp : Type )(using Context ): Option [(Type , CaptureSet )] =
112+ tp match
113+ case tp : AnnotatedType => unapplyAnnot(tp)
114+ case _ => unapplyCap(tp)
115+
116+ def unapplyCap (tp : Type )(using Context ): Option [(Type , CaptureSet )] =
117+ if tp.classSymbol.hasAnnotation(defn.CapabilityAnnot ) && ! tp.classSymbol.is(Flags .CapabilityBase ) then
118+ val sym = tp.classSymbol
119+ val psym = pureSymbolOf(sym.asClass)
120+ tp match
121+ case tp : TypeRef => Some ((psym.typeRef, CaptureSet .universal))
122+ case tp : AppliedType =>
123+ Some ((tp.derivedAppliedType(psym.typeRef, tp.args), CaptureSet .universal))
124+ case _ => None
125+ else None
126+ // None
127+
128+ def unapplyAnnot (tp : AnnotatedType )(using Context ): Option [(Type , CaptureSet )] =
70129 val sym = tp.annot.symbol
71130 if sym == defn.RetainsAnnot || sym == defn.RetainsByNameAnnot then
72131 tp.annot match
0 commit comments