Skip to content

Commit a4ae554

Browse files
committed
More fix
1 parent abebcf9 commit a4ae554

File tree

12 files changed

+97
-93
lines changed

12 files changed

+97
-93
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2261,9 +2261,9 @@ object desugar {
22612261
AppliedTypeTree(ref(defn.SeqType), t),
22622262
New(ref(defn.RepeatedAnnot.typeRef), Nil :: Nil))
22632263
else if op.name == nme.CC_REACH then
2264-
Apply(ref(defn.Caps_reachCapability), t :: Nil)
2264+
Annotated(t, New(ref(defn.ReachCapabilityAnnot.typeRef), Nil :: Nil))
22652265
else if op.name == nme.CC_READONLY then
2266-
Apply(ref(defn.Caps_readOnlyCapability), t :: Nil)
2266+
Annotated(t, New(ref(defn.ReadOnlyCapabilityAnnot.typeRef), Nil :: Nil))
22672267
else
22682268
assert(ctx.mode.isExpr || ctx.reporter.errorsReported || ctx.mode.is(Mode.Interactive), ctx.mode)
22692269
Select(t, op.name)

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

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,15 +38,14 @@ case class CaptureAnnotation(refs: CaptureSet, boxed: Boolean)(cls: Symbol) exte
3838

3939
/** Reconstitute annotation tree from capture set */
4040
override def tree(using Context) =
41-
val elems = refs.elems.toList.map {
42-
case cr: TermRef => ref(cr)
43-
case cr: TermParamRef => untpd.Ident(cr.paramName).withType(cr)
44-
case cr: ThisType => This(cr.cls)
45-
case root(_) => ref(root.cap)
46-
// TODO: Will crash if the type is an annotated type, for example `cap.rd`
47-
}
48-
val arg = repeated(elems, TypeTree(defn.AnyType))
49-
New(symbol.typeRef, arg :: Nil)
41+
if symbol == defn.RetainsCapAnnot then
42+
New(symbol.typeRef, Nil)
43+
else
44+
val elems = refs.elems.toList
45+
val trefs =
46+
if elems.isEmpty then defn.NothingType
47+
else elems.reduce[Type]((a, b) => OrType(a, b, soft = false))
48+
New(AppliedType(symbol.typeRef, trefs :: Nil), Nil)
5049

5150
override def symbol(using Context) = cls
5251

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

Lines changed: 37 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -195,12 +195,12 @@ extension (tree: Tree)
195195
* throw IllegalCaptureRef otherwise
196196
*/
197197
def toCaptureRefs(using Context): List[CaptureRef] = tree match
198-
case ReachCapabilityApply(arg) =>
199-
arg.toCaptureRefs.map(_.reach)
200-
case ReadOnlyCapabilityApply(arg) =>
201-
arg.toCaptureRefs.map(_.readOnly)
202-
case CapsOfApply(arg) =>
203-
arg.toCaptureRefs
198+
// case ReachCapabilityApply(arg) =>
199+
// arg.toCaptureRefs.map(_.reach)
200+
// case ReadOnlyCapabilityApply(arg) =>
201+
// arg.toCaptureRefs.map(_.readOnly)
202+
// case CapsOfApply(arg) =>
203+
// arg.toCaptureRefs
204204
case _ => tree.tpe.dealiasKeepAnnots match
205205
case ref: CaptureRef if ref.isTrackableRef =>
206206
ref :: Nil
@@ -220,28 +220,20 @@ extension (tree: Tree)
220220
val refs =
221221
tree match
222222
case Apply(_: TypeApply, _) =>
223-
CaptureSet(tree.retainedElemsFromType*)
223+
CaptureSet(tree.retainedSet.retainedElements*)
224224
case _ =>
225225
CaptureSet(tree.retainedElems.flatMap(_.toCaptureRefs)*)
226226
// println(s"toCaptureSet: $tree -> $refs")
227227
tree.putAttachment(Captures, refs)
228228
refs
229229

230-
def retainedElemsFromType(using Context): List[CaptureRef] =
231-
def collectRefs(tp: Type): List[CaptureRef] = tp match
232-
case tp: CaptureRef if tp.isTrackableRef =>
233-
tp :: Nil
234-
case tp: TypeRef if tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet) =>
235-
tp :: Nil
236-
case OrType(tp1, tp2) =>
237-
collectRefs(tp1) ++ collectRefs(tp2)
238-
case _ =>
239-
Nil
230+
def retainedSet(using Context): Type =
240231
tree match
241-
case Apply(TypeApply(_, refs :: Nil), _) =>
242-
collectRefs(refs.tpe)
232+
case Apply(TypeApply(_, refs :: Nil), _) => refs.tpe
243233
case _ =>
244-
Nil
234+
if tree.symbol.maybeOwner == defn.RetainsCapAnnot
235+
then root.cap
236+
else NoType
245237

246238
/** The arguments of a @retains, @retainsCap or @retainsByName annotation */
247239
def retainedElems(using Context): List[Tree] = tree match
@@ -254,6 +246,21 @@ extension (tree: Tree)
254246

255247
extension (tp: Type)
256248

249+
def retainedElements(using Context): List[CaptureRef] = tp match
250+
case ReachCapability(tp1) =>
251+
tp1.reach :: Nil
252+
case ReadOnlyCapability(tp1) =>
253+
tp1.readOnly :: Nil
254+
case tp: CaptureRef if tp.isTrackableRef =>
255+
tp :: Nil
256+
case tp: TypeRef if tp.symbol.isType && tp.derivesFrom(defn.Caps_CapSet) =>
257+
tp :: Nil
258+
case OrType(tp1, tp2) =>
259+
tp1.retainedElements ++ tp2.retainedElements
260+
case _ =>
261+
if tp.isNothingType then Nil
262+
else throw IllegalCaptureRef(tp)
263+
257264
/** Is this type a CaptureRef that can be tracked?
258265
* This is true for
259266
* - all ThisTypes and all TermParamRef,
@@ -676,7 +683,7 @@ extension (cls: ClassSymbol)
676683
|| bc.is(CaptureChecked)
677684
&& bc.givenSelfType.dealiasKeepAnnots.match
678685
case CapturingType(_, refs) => refs.isAlwaysEmpty
679-
case RetainingType(_, refs) => refs.isEmpty
686+
case RetainingType(_, refs) => refs.retainedElements.isEmpty
680687
case selfType =>
681688
isCaptureChecking // At Setup we have not processed self types yet, so
682689
// unless a self type is explicitly given, we can't tell
@@ -794,7 +801,7 @@ class CleanupRetains(using Context) extends TypeMap:
794801
def apply(tp: Type): Type =
795802
tp match
796803
case AnnotatedType(tp, annot) if annot.symbol == defn.RetainsAnnot || annot.symbol == defn.RetainsByNameAnnot =>
797-
RetainingType(tp, Nil, byName = annot.symbol == defn.RetainsByNameAnnot)
804+
RetainingType(tp, defn.NothingType, byName = annot.symbol == defn.RetainsByNameAnnot)
798805
case _ => mapOver(tp)
799806

800807
/** A typemap that follows aliases and keeps their transformed results if
@@ -813,18 +820,18 @@ trait FollowAliasesMap(using Context) extends TypeMap:
813820
/** An extractor for `caps.reachCapability(ref)`, which is used to express a reach
814821
* capability as a tree in a @retains annotation.
815822
*/
816-
object ReachCapabilityApply:
817-
def unapply(tree: Apply)(using Context): Option[Tree] = tree match
818-
case Apply(reach, arg :: Nil) if reach.symbol == defn.Caps_reachCapability => Some(arg)
819-
case _ => None
823+
// object ReachCapabilityApply:
824+
// def unapply(tree: Apply)(using Context): Option[Tree] = tree match
825+
// case Apply(reach, arg :: Nil) if reach.symbol == defn.Caps_reachCapability => Some(arg)
826+
// case _ => None
820827

821828
/** An extractor for `caps.readOnlyCapability(ref)`, which is used to express a read-only
822829
* capability as a tree in a @retains annotation.
823830
*/
824-
object ReadOnlyCapabilityApply:
825-
def unapply(tree: Apply)(using Context): Option[Tree] = tree match
826-
case Apply(ro, arg :: Nil) if ro.symbol == defn.Caps_readOnlyCapability => Some(arg)
827-
case _ => None
831+
// object ReadOnlyCapabilityApply:
832+
// def unapply(tree: Apply)(using Context): Option[Tree] = tree match
833+
// case Apply(ro, arg :: Nil) if ro.symbol == defn.Caps_readOnlyCapability => Some(arg)
834+
// case _ => None
828835

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

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

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,25 +137,24 @@ object CheckCaptures:
137137
* This check is performed at Typer.
138138
*/
139139
def checkWellformed(parent: Tree, ann: Tree)(using Context): Unit =
140-
def check(elem: Tree, pos: SrcPos): Unit = elem.tpe match
140+
def check(elem: Type, pos: SrcPos): Unit = elem match
141141
case ref: CaptureRef =>
142142
if !ref.isTrackableRef then
143143
report.error(em"$elem cannot be tracked since it is not a parameter or local value", pos)
144144
case tpe =>
145145
report.error(em"$elem: $tpe is not a legal element of a capture set", pos)
146-
for elem <- ann.retainedElems do
146+
for elem <- ann.retainedSet.retainedElements do
147147
elem match
148-
case CapsOfApply(arg) =>
149-
def isLegalCapsOfArg =
150-
arg.symbol.isType && arg.symbol.info.derivesFrom(defn.Caps_CapSet)
151-
if !isLegalCapsOfArg then
152-
report.error(
153-
em"""$arg is not a legal prefix for `^` here,
154-
|is must be a type parameter or abstract type with a caps.CapSet upper bound.""",
155-
elem.srcPos)
156-
case ReachCapabilityApply(arg) => check(arg, elem.srcPos)
157-
case ReadOnlyCapabilityApply(arg) => check(arg, elem.srcPos)
158-
case _ => check(elem, elem.srcPos)
148+
case ref: TypeRef =>
149+
val refSym = ref.symbol
150+
if refSym.isType && !refSym.info.derivesFrom(defn.Caps_CapSet) then
151+
report.error(em"$elem is not a legal element of a capture set", ann.srcPos)
152+
case ReachCapability(ref) =>
153+
check(ref, ann.srcPos)
154+
case ReadOnlyCapability(ref) =>
155+
check(ref, ann.srcPos)
156+
case _ =>
157+
check(elem, ann.srcPos)
159158

160159
/** Under the sealed policy, report an error if some part of `tp` contains the
161160
* root capability in its capture set or if it refers to a type parameter that

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

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,24 +12,22 @@ import Decorators.i
1212
*/
1313
object RetainingType:
1414

15-
def apply(tp: Type, refs: List[Tree], byName: Boolean = false)(using Context): Type =
15+
// def apply(tp: Type, refs: List[CaptureRef], byName: Boolean = false)(using Context): Type = ???
16+
17+
def apply(tp: Type, typeRefs: Type, byName: Boolean = false)(using Context): Type =
1618
val annotCls = if byName then defn.RetainsByNameAnnot else defn.RetainsAnnot
17-
val annotTree =
18-
New(annotCls.typeRef,
19-
Typed(
20-
SeqLiteral(refs, TypeTree(defn.AnyType)),
21-
TypeTree(defn.RepeatedParamClass.typeRef.appliedTo(defn.AnyType))) :: Nil)
19+
val annotTree = New(AppliedType(annotCls.typeRef, defn.NothingType :: Nil), Nil)
2220
AnnotatedType(tp, Annotation(annotTree))
2321

24-
def unapply(tp: AnnotatedType)(using Context): Option[(Type, List[Tree])] =
22+
def unapply(tp: AnnotatedType)(using Context): Option[(Type, Type)] =
2523
val sym = tp.annot.symbol
2624
if sym.isRetainsLike then
2725
tp.annot match
2826
case _: CaptureAnnotation =>
2927
assert(ctx.mode.is(Mode.IgnoreCaptures), s"bad retains $tp at ${ctx.phase}")
3028
None
3129
case ann =>
32-
Some((tp.parent, ann.tree.retainedElems))
30+
Some((tp.parent, ann.tree.retainedSet))
3331
else
3432
None
3533
end RetainingType

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

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -810,7 +810,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
810810
case CapturingType(_, refs) =>
811811
!refs.isAlwaysEmpty
812812
case RetainingType(parent, refs) =>
813-
!refs.isEmpty
813+
!refs.retainedElements.isEmpty
814814
case tp: (TypeRef | AppliedType) =>
815815
val sym = tp.typeSymbol
816816
if sym.isClass
@@ -856,7 +856,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
856856
&& !refs.isUniversal // if refs is {cap}, an added variable would not change anything
857857
case RetainingType(parent, refs) =>
858858
needsVariable(parent)
859-
&& !refs.tpes.exists:
859+
&& !refs.retainedElements.exists:
860860
case ref: TermRef => ref.isCap
861861
case _ => false
862862
case AnnotatedType(parent, _) =>
@@ -951,19 +951,13 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
951951
* @param tpt the tree for which an error or warning should be reported
952952
*/
953953
private def checkWellformed(parent: Type, ann: Tree, tpt: Tree)(using Context): Unit =
954-
capt.println(i"checkWF post $parent ${ann.retainedElems} in $tpt")
955-
var retained = ann.retainedElems.toArray
956-
for i <- 0 until retained.length do
957-
val refTree = retained(i)
958-
val refs =
959-
try refTree.toCaptureRefs
960-
catch case ex: IllegalCaptureRef =>
961-
report.error(em"Illegal capture reference: ${ex.getMessage.nn}", refTree.srcPos)
962-
Nil
963-
for ref <- refs do
954+
capt.println(i"checkWF post $parent ${ann.retainedSet} in $tpt")
955+
try
956+
val retainedRefs = ann.retainedSet.retainedElements.toArray
957+
for i <- 0 until retainedRefs.length do
958+
val ref = retainedRefs(i)
964959
def pos =
965-
if refTree.span.exists then refTree.srcPos
966-
else if ann.span.exists then ann.srcPos
960+
if ann.span.exists then ann.srcPos
967961
else tpt.srcPos
968962

969963
def check(others: CaptureSet, dom: Type | CaptureSet): Unit =
@@ -979,14 +973,15 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
979973

980974
val others =
981975
for
982-
j <- 0 until retained.length if j != i
983-
r <- retained(j).toCaptureRefs
976+
j <- 0 until retainedRefs.length if j != i
977+
r = retainedRefs(j)
984978
if !r.isRootCapability
985979
yield r
986980
val remaining = CaptureSet(others*)
987981
check(remaining, remaining)
988982
end for
989-
end for
983+
catch case ex: IllegalCaptureRef =>
984+
report.error(em"Illegal capture reference: ${ex.getMessage.nn}", tpt.srcPos)
990985
end checkWellformed
991986

992987
/** Check well formed at post check time. We need to wait until after

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ class Definitions {
123123
HKTypeLambda(argParamNames :+ "R".toTypeName, argVariances :+ Covariant)(
124124
tl => List.fill(arity + 1)(TypeBounds.empty),
125125
tl => RetainingType(underlyingClass.typeRef.appliedTo(tl.paramRefs),
126-
ref(captureRoot.termRef) :: Nil)
126+
captureRoot.termRef)
127127
))
128128
else
129129
val cls = denot.asClass.classSymbol

compiler/src/dotty/tools/dotc/printing/PlainPrinter.scala

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,8 @@ class PlainPrinter(_ctx: Context) extends Printer {
175175
toTextCaptureRef(ref.typeOpt)
176176
case TypeApply(fn, arg :: Nil) if fn.symbol == defn.Caps_capsOf =>
177177
toTextRetainedElem(arg)
178-
case ReachCapabilityApply(ref1) => toTextRetainedElem(ref1) ~ "*"
179-
case ReadOnlyCapabilityApply(ref1) => toTextRetainedElem(ref1) ~ ".rd"
178+
// case ReachCapabilityApply(ref1) => toTextRetainedElem(ref1) ~ "*"
179+
// case ReadOnlyCapabilityApply(ref1) => toTextRetainedElem(ref1) ~ ".rd"
180180
case _ => toText(ref)
181181

182182
private def toTextRetainedElems[T <: Untyped](refs: List[Tree[T]]): Text =
@@ -277,11 +277,12 @@ class PlainPrinter(_ctx: Context) extends Printer {
277277
else
278278
toTextCaptureSet(refs)
279279
toTextCapturing(parent, refsText, boxText)
280-
case tp @ RetainingType(parent, refs) =>
280+
case tp @ RetainingType(parent, refsType) =>
281+
val refs = refsType.retainedElements
281282
if Feature.ccEnabledSomewhere then
282283
val refsText = refs match
283-
case ref :: Nil if ref.symbol == defn.captureRoot => rootSetText
284-
case _ => toTextRetainedElems(refs)
284+
case (ref: TermRef) :: Nil if ref.symbol == defn.captureRoot => rootSetText
285+
case _ => toTextRetainedElems(refs.map(r => ast.tpd.TypeTree(r)))
285286
toTextCapturing(parent, refsText, "") ~ Str("R").provided(printDebug)
286287
else toText(parent)
287288
case tp: PreviousErrorType if ctx.settings.XprintTypes.value =>

library/src/scala/annotation/retains.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,12 @@ package scala.annotation
1212
* non-standard capturing type syntax.
1313
*/
1414
@experimental
15-
class retains[Args](xs: (Any @retainsArg)*) extends annotation.StaticAnnotation
15+
class retains[Elems] extends annotation.StaticAnnotation
1616

1717
/** Equivalent in meaning to `@retains(cap)`, but consumes less bytecode.
1818
*/
1919
@experimental
20-
class retainsCap() extends annotation.StaticAnnotation
20+
class retainsCap extends annotation.StaticAnnotation
2121
// This special case is needed to be able to load standard library modules without
2222
// cyclic reference errors. Specifically, load sequences involving IterableOnce.
2323

library/src/scala/annotation/retainsByName.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ package scala.annotation
22

33
/** An annotation that indicates capture of an enclosing by-name type
44
*/
5-
@experimental class retainsByName[Args](xs: (Any@retainsArg)*) extends annotation.StaticAnnotation
5+
@experimental class retainsByName[Elems] extends annotation.StaticAnnotation
66

0 commit comments

Comments
 (0)