@@ -97,6 +97,7 @@ object SepCheck:
9797 var refs : Array [CaptureRef ] = new Array (4 )
9898 var locs : Array [SrcPos ] = new Array (4 )
9999 var size = 0
100+ var peaks : Refs = emptyRefs
100101
101102 private def double [T <: AnyRef : ClassTag ](xs : Array [T ]): Array [T ] =
102103 val xs1 = new Array [T ](xs.length * 2 )
@@ -114,31 +115,44 @@ object SepCheck:
114115 while i < size && (refs(i) ne ref) do i += 1
115116 if i < size then locs(i) else null
116117
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+
117128 /** 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 =
119130 if get(ref) == null then
120131 ensureCapacity(1 )
121132 refs(size) = ref
122133 locs(size) = loc
123134 size += 1
135+ peaks = peaks ++ ref.peaks
124136
125137 /** Add all references with their associated positions from `that` which
126138 * are not yet in the set.
127139 */
128- def ++= (that : ConsumedSet ): Unit =
140+ def ++= (that : ConsumedSet )( using Context ) : Unit =
129141 for i <- 0 until that.size do put(that.refs(i), that.locs(i))
130142
131143 /** Run `op` and return any new references it created in a separate `ConsumedSet`.
132144 * The current mutable set is reset to its state before `op` was run.
133145 */
134146 def segment (op : => Unit ): ConsumedSet =
135147 val start = size
148+ val savedPeaks = peaks
136149 try
137150 op
138151 if size == start then EmptyConsumedSet
139152 else ConstConsumedSet (refs.slice(start, size), locs.slice(start, size))
140153 finally
141154 size = start
155+ peaks = savedPeaks
142156 end MutConsumedSet
143157
144158 val EmptyConsumedSet = ConstConsumedSet (Array (), Array ())
@@ -265,6 +279,9 @@ object SepCheck:
265279
266280 end extension
267281
282+ extension (ref : CaptureRef )
283+ def peaks (using Context ): Refs = SimpleIdentitySet (ref).peaks
284+
268285class SepCheck (checker : CheckCaptures .CheckerAPI ) extends tpd.TreeTraverser :
269286 import checker .*
270287 import SepCheck .*
@@ -553,7 +570,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
553570 sepUseError(tree, null , used, defsShadow)
554571
555572 for ref <- used do
556- val pos = consumed.get (ref.stripReadOnly )
573+ val pos = consumed.clashing (ref)
557574 if pos != null then consumeError(ref, pos, tree.srcPos)
558575 end checkUse
559576
@@ -632,7 +649,7 @@ class SepCheck(checker: CheckCaptures.CheckerAPI) extends tpd.TreeTraverser:
632649 case _ : TypeRole .Argument | _ : TypeRole .Qualifier =>
633650 for ref <- refsToCheck do
634651 if ! ref.derivesFromSharedCapability then
635- consumed.put(ref.stripReadOnly , pos)
652+ consumed.put(ref, pos)
636653 case _ =>
637654 end checkConsumedRefs
638655
0 commit comments