@@ -249,6 +249,44 @@ class CheckCaptures extends Recheck, SymTransformer:
249
249
else i " references $cs1$cs1description are not all " ,
250
250
pos, provenance)
251
251
252
+ def showRef (ref : CaptureRef )(using Context ): String =
253
+ ctx.printer.toTextCaptureRef(ref).show
254
+
255
+ // Uses 4-space indent as a trial
256
+ def checkReachCapsIsolated (tpe : Type , pos : SrcPos )(using Context ): Unit =
257
+
258
+ object checker extends TypeTraverser :
259
+ var refVariances : Map [Boolean , Int ] = Map .empty
260
+ var seenReach : CaptureRef | Null = null
261
+ def traverse (tp : Type ) =
262
+ tp match
263
+ case CapturingType (parent, refs) =>
264
+ traverse(parent)
265
+ for ref <- refs.elems do
266
+ if ref.isReach && ! ref.stripReach.isInstanceOf [TermParamRef ]
267
+ || ref.isRootCapability
268
+ then
269
+ val isReach = ref.isReach
270
+ def register () =
271
+ refVariances = refVariances.updated(isReach, variance)
272
+ seenReach = ref
273
+ refVariances.get(isReach) match
274
+ case None => register()
275
+ case Some (v) => if v != 0 && variance == 0 then register()
276
+ case _ =>
277
+ traverseChildren(tp)
278
+
279
+ checker.traverse(tpe)
280
+ if checker.refVariances.size == 2
281
+ && checker.refVariances(true ) >= 0
282
+ && checker.refVariances(false ) <= 0
283
+ then
284
+ report.error(
285
+ em """ Reach capability ${showRef(checker.seenReach.nn)} and universal capability cap cannot both
286
+ |appear in the type $tpe of this expression """ ,
287
+ pos)
288
+ end checkReachCapsIsolated
289
+
252
290
/** The current environment */
253
291
private val rootEnv : Env = inContext(ictx):
254
292
Env (defn.RootClass , EnvKind .Regular , CaptureSet .empty, null )
@@ -779,8 +817,10 @@ class CheckCaptures extends Recheck, SymTransformer:
779
817
report.error(ex.getMessage.nn)
780
818
tree.tpe
781
819
finally curEnv = saved
782
- if tree.isTerm && ! pt.isBoxedCapturing then
783
- markFree(res.boxedCaptureSet, tree.srcPos)
820
+ if tree.isTerm then
821
+ checkReachCapsIsolated(res.widen, tree.srcPos)
822
+ if ! pt.isBoxedCapturing then
823
+ markFree(res.boxedCaptureSet, tree.srcPos)
784
824
res
785
825
786
826
override def recheckFinish (tpe : Type , tree : Tree , pt : Type )(using Context ): Type =
0 commit comments