Skip to content

Commit 36169a4

Browse files
committed
Remove empty capabilities for separation checking
1 parent 59862e3 commit 36169a4

File tree

4 files changed

+43
-5
lines changed

4 files changed

+43
-5
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ class CCState:
8181
def start(): Unit =
8282
iterCount = 1
8383

84+
private var mySepCheck = false
85+
86+
/** Are we currently running separation checks? */
87+
def isSepCheck = mySepCheck
88+
89+
def inSepCheck(op: => Unit): Unit =
90+
val saved = mySepCheck
91+
mySepCheck = true
92+
try op finally mySepCheck = saved
93+
8494
// ------ Global counters -----------------------
8595

8696
/** Next CaptureSet.Var id */

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

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,14 @@ sealed abstract class CaptureSet extends Showable:
8383
*/
8484
def owner: Symbol
8585

86+
/** If this set is a variable: Drop capabilities that are known to be empty
87+
* This is called during separation checking so that capabilities that turn
88+
* out to be always empty because of conflicting clasisifiers don't contribute
89+
* to peaks. We can't do it before that since classifiers are set during
90+
* capture checking.
91+
*/
92+
def dropEmpties()(using Context): this.type
93+
8694
/** Is this capture set definitely non-empty? */
8795
final def isNotEmpty: Boolean = !elems.isEmpty
8896

@@ -412,9 +420,15 @@ sealed abstract class CaptureSet extends Showable:
412420
res
413421

414422
def transClassifiers(using Context): Classifiers =
415-
if isConst then
423+
def elemClassifiers =
416424
(ClassifiedAs(Nil) /: elems.map(_.transClassifiers))(joinClassifiers)
417-
else UnknownClassifier
425+
if ccState.isSepCheck then
426+
dropEmpties()
427+
elemClassifiers
428+
else if isConst then
429+
elemClassifiers
430+
else
431+
UnknownClassifier
418432

419433
def tryClassifyAs(cls: ClassSymbol)(using Context): Boolean =
420434
elems.forall(_.tryClassifyAs(cls))
@@ -574,6 +588,8 @@ object CaptureSet:
574588

575589
def owner = NoSymbol
576590

591+
def dropEmpties()(using Context) = this
592+
577593
private var isComplete = true
578594

579595
def setMutable()(using Context): Unit =
@@ -658,6 +674,16 @@ object CaptureSet:
658674

659675
def isMaybeSet = false // overridden in BiMapped
660676

677+
private var emptiesDropped = false
678+
679+
def dropEmpties()(using Context): this.type =
680+
if !emptiesDropped then
681+
emptiesDropped = true
682+
for elem <- elems do
683+
if elem.isKnownEmpty then
684+
elems -= empty
685+
this
686+
661687
/** A handler to be invoked if the root reference `cap` is added to this set */
662688
var rootAddedHandler: () => Context ?=> Unit = () => ()
663689

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2021,7 +2021,9 @@ class CheckCaptures extends Recheck, SymTransformer:
20212021
end checker
20222022

20232023
checker.traverse(unit)(using ctx.withOwner(defn.RootClass))
2024-
if ccConfig.useSepChecks then SepCheck(this).traverse(unit)
2024+
if ccConfig.useSepChecks then
2025+
ccState.inSepCheck:
2026+
SepCheck(this).traverse(unit)
20252027
if !ctx.reporter.errorsReported then
20262028
// We dont report errors here if previous errors were reported, because other
20272029
// errors often result in bad applied types, but flagging these bad types gives

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ object SepCheck:
185185
case newElem :: newElems1 =>
186186
if seen.contains(newElem) then
187187
recur(seen, acc, newElems1)
188-
else newElem.stripReadOnly match
188+
else newElem.stripRestricted.stripReadOnly match
189189
case elem: FreshCap =>
190190
if elem.hiddenSet.deps.isEmpty then recur(seen + newElem, acc + newElem, newElems1)
191191
else
@@ -197,7 +197,7 @@ object SepCheck:
197197
if newElem.isTerminalCapability
198198
//|| newElem.isInstanceOf[TypeRef | TypeParamRef]
199199
then recur(seen + newElem, acc, newElems1)
200-
else recur(seen + newElem, acc, newElem.captureSetOfInfo.elems.toList ++ newElems1)
200+
else recur(seen + newElem, acc, newElem.captureSetOfInfo.dropEmpties().elems.toList ++ newElems1)
201201
case Nil => acc
202202
recur(emptyRefs, emptyRefs, refs.toList)
203203

0 commit comments

Comments
 (0)