@@ -249,6 +249,44 @@ class CheckCaptures extends Recheck, SymTransformer:
249249 else i " references $cs1$cs1description are not all " ,
250250 pos, provenance)
251251
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+
252290 /** The current environment */
253291 private val rootEnv : Env = inContext(ictx):
254292 Env (defn.RootClass , EnvKind .Regular , CaptureSet .empty, null )
@@ -779,8 +817,10 @@ class CheckCaptures extends Recheck, SymTransformer:
779817 report.error(ex.getMessage.nn)
780818 tree.tpe
781819 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)
784824 res
785825
786826 override def recheckFinish (tpe : Type , tree : Tree , pt : Type )(using Context ): Type =
0 commit comments