@@ -97,6 +97,7 @@ object SepCheck:
97
97
var refs : Array [CaptureRef ] = new Array (4 )
98
98
var locs : Array [SrcPos ] = new Array (4 )
99
99
var size = 0
100
+ var peaks : Refs = emptyRefs
100
101
101
102
private def double [T <: AnyRef : ClassTag ](xs : Array [T ]): Array [T ] =
102
103
val xs1 = new Array [T ](xs.length * 2 )
@@ -114,31 +115,44 @@ object SepCheck:
114
115
while i < size && (refs(i) ne ref) do i += 1
115
116
if i < size then locs(i) else null
116
117
118
+ def clashing (ref : CaptureRef )(using Context ): SrcPos | Null =
119
+ val refPeaks = ref.peaks
120
+ if ! peaks.sharedWith(refPeaks).isEmpty then
121
+ var i = 0
122
+ while i < size && refs(i).peaks.sharedWith(refPeaks).isEmpty do
123
+ i += 1
124
+ assert(i < size)
125
+ locs(i)
126
+ else null
127
+
117
128
/** If `ref` is not yet in the set, add it with given source position */
118
- def put (ref : CaptureRef , loc : SrcPos ): Unit =
129
+ def put (ref : CaptureRef , loc : SrcPos )( using Context ) : Unit =
119
130
if get(ref) == null then
120
131
ensureCapacity(1 )
121
132
refs(size) = ref
122
133
locs(size) = loc
123
134
size += 1
135
+ peaks = peaks ++ ref.peaks
124
136
125
137
/** Add all references with their associated positions from `that` which
126
138
* are not yet in the set.
127
139
*/
128
- def ++= (that : ConsumedSet ): Unit =
140
+ def ++= (that : ConsumedSet )( using Context ) : Unit =
129
141
for i <- 0 until that.size do put(that.refs(i), that.locs(i))
130
142
131
143
/** Run `op` and return any new references it created in a separate `ConsumedSet`.
132
144
* The current mutable set is reset to its state before `op` was run.
133
145
*/
134
146
def segment (op : => Unit ): ConsumedSet =
135
147
val start = size
148
+ val savedPeaks = peaks
136
149
try
137
150
op
138
151
if size == start then EmptyConsumedSet
139
152
else ConstConsumedSet (refs.slice(start, size), locs.slice(start, size))
140
153
finally
141
154
size = start
155
+ peaks = savedPeaks
142
156
end MutConsumedSet
143
157
144
158
val EmptyConsumedSet = ConstConsumedSet (Array (), Array ())
@@ -265,6 +279,9 @@ object SepCheck:
265
279
266
280
end extension
267
281
282
+ extension (ref : CaptureRef )
283
+ def peaks (using Context ): Refs = SimpleIdentitySet (ref).peaks
284
+
268
285
class SepCheck (checker : CheckCaptures .CheckerAPI ) extends tpd.TreeTraverser :
269
286
import checker .*
270
287
import SepCheck .*
@@ -553,7 +570,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
553
570
sepUseError(tree, null , used, defsShadow)
554
571
555
572
for ref <- used do
556
- val pos = consumed.get (ref.stripReadOnly )
573
+ val pos = consumed.clashing (ref)
557
574
if pos != null then consumeError(ref, pos, tree.srcPos)
558
575
end checkUse
559
576
@@ -632,7 +649,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
632
649
case _ : TypeRole .Argument | _ : TypeRole .Qualifier =>
633
650
for ref <- refsToCheck do
634
651
if ! ref.derivesFromSharedCapability then
635
- consumed.put(ref.stripReadOnly , pos)
652
+ consumed.put(ref, pos)
636
653
case _ =>
637
654
end checkConsumedRefs
638
655
0 commit comments