Skip to content

Commit 15db46d

Browse files
committed
Make capture-sets thread-safe again
1 parent d3e26ce commit 15db46d

File tree

2 files changed

+10
-8
lines changed

2 files changed

+10
-8
lines changed

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -512,17 +512,13 @@ object CaptureSet:
512512
val emptyRefs: Refs = SimpleIdentitySet.empty
513513

514514
/** The empty capture set `{}` */
515+
@sharable // sharable since the set is empty, so setMutable is a no-op
515516
val empty: CaptureSet.Const = Const(emptyRefs)
516517

517518
/** The universal capture set `{cap}` */
518519
def universal(using Context): Const =
519520
Const(SimpleIdentitySet(GlobalCap))
520521

521-
/** The same as {cap.rd} but generated implicitly for
522-
* references of Capability subtypes
523-
*/
524-
val csImpliedByCapability = Const(SimpleIdentitySet(GlobalCap.readOnly))
525-
526522
def fresh(origin: Origin)(using Context): Const =
527523
FreshCap(origin).singletonCaptureSet
528524

@@ -572,7 +568,8 @@ object CaptureSet:
572568
private var isComplete = true
573569

574570
def setMutable()(using Context): Unit =
575-
isComplete = false // delay computation of Mutability status
571+
if !elems.isEmpty then
572+
isComplete = false // delay computation of Mutability status
576573

577574
override def mutability(using Context): Mutability =
578575
if !isComplete then
@@ -589,12 +586,17 @@ object CaptureSet:
589586
then i" under-approximating the result of mapping $ref to $mapped"
590587
else ""
591588

589+
/* The same as {cap.rd} but generated implicitly for references of Capability subtypes.
590+
*/
591+
case class CSImpliedByCapability() extends Const(SimpleIdentitySet(GlobalCap.readOnly))
592+
592593
/** A special capture set that gets added to the types of symbols that were not
593594
* themselves capture checked, in order to admit arbitrary corresponding capture
594595
* sets in subcapturing comparisons. Similar to platform types for explicit
595596
* nulls, this provides more lenient checking against compilation units that
596597
* were not yet compiled with capture checking on.
597598
*/
599+
@sharable // sharable since the set is empty, so setMutable is a no-op
598600
object Fluid extends Const(emptyRefs):
599601
override def isAlwaysEmpty(using Context) = false
600602
override def addThisElem(elem: Capability)(using Context, VarState) = true

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -367,7 +367,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
367367
*/
368368
def stripImpliedCaptureSet(tp: Type): Type = tp match
369369
case tp @ CapturingType(parent, refs)
370-
if (refs eq CaptureSet.csImpliedByCapability) && !tp.isBoxedCapturing =>
370+
if refs.isInstanceOf[CaptureSet.CSImpliedByCapability] && !tp.isBoxedCapturing =>
371371
parent
372372
case tp: AliasingBounds =>
373373
tp.derivedAlias(stripImpliedCaptureSet(tp.alias))
@@ -430,7 +430,7 @@ class Setup extends PreRecheck, SymTransformer, SetupAPI:
430430
&& !t.isSingleton
431431
&& (!sym.isConstructor || (t ne tp.finalResultType))
432432
// Don't add ^ to result types of class constructors deriving from Capability
433-
then CapturingType(t, CaptureSet.csImpliedByCapability, boxed = false)
433+
then CapturingType(t, CaptureSet.CSImpliedByCapability(), boxed = false)
434434
else normalizeCaptures(mapFollowingAliases(t))
435435

436436
def innerApply(t: Type) =

0 commit comments

Comments
 (0)