@@ -676,29 +676,24 @@ class CheckCaptures extends Recheck, SymTransformer:
676676 i " Sealed type variable $pname" , " be instantiated to" ,
677677 i " This is often caused by a local capability $where\n leaking as part of its result. " ,
678678 tree.srcPos)
679- val res = handleCall(meth, tree, () => Existential .toCap(super .recheckTypeApply(tree, pt)))
680- if meth == defn.Caps_containsImpl then checkContains(tree)
681- res
679+ try handleCall(meth, tree, () => Existential .toCap(super .recheckTypeApply(tree, pt)))
680+ finally checkContains(tree)
682681 end recheckTypeApply
683682
684683 /** Faced with a tree of form `caps.contansImpl[CS, r.type]`, check that `R` is a tracked
685684 * capability and assert that `{r} <:CS`.
686685 */
687- def checkContains (tree : TypeApply )(using Context ): Unit =
688- tree.fun.knownType.widen match
689- case fntpe : PolyType =>
690- tree.args match
691- case csArg :: refArg :: Nil =>
692- val cs = csArg.knownType.captureSet
693- val ref = refArg.knownType
694- capt.println(i " check contains $cs , $ref" )
695- ref match
696- case ref : CaptureRef if ref.isTracked =>
697- checkElem(ref, cs, tree.srcPos)
698- case _ =>
699- report.error(em " $refArg is not a tracked capability " , refArg.srcPos)
700- case _ =>
701- case _ =>
686+ def checkContains (tree : TypeApply )(using Context ): Unit = tree match
687+ case ContainsImpl (csArg, refArg) =>
688+ val cs = csArg.knownType.captureSet
689+ val ref = refArg.knownType
690+ capt.println(i " check contains $cs , $ref" )
691+ ref match
692+ case ref : CaptureRef if ref.isTracked =>
693+ checkElem(ref, cs, tree.srcPos)
694+ case _ =>
695+ report.error(em " $refArg is not a tracked capability " , refArg.srcPos)
696+ case _ =>
702697
703698 override def recheckBlock (tree : Block , pt : Type )(using Context ): Type =
704699 inNestedLevel(super .recheckBlock(tree, pt))
@@ -814,15 +809,26 @@ class CheckCaptures extends Recheck, SymTransformer:
814809 val localSet = capturedVars(sym)
815810 if ! localSet.isAlwaysEmpty then
816811 curEnv = Env (sym, EnvKind .Regular , localSet, curEnv)
812+
813+ // ctx with AssumedContains entries for each Contains parameter
814+ val bodyCtx =
815+ var ac = CaptureSet .assumedContains
816+ for paramSyms <- sym.paramSymss do
817+ for case ContainsParam (cs, ref) <- paramSyms do
818+ ac = ac.updated(cs, ac.getOrElse(cs, SimpleIdentitySet .empty) + ref)
819+ if ac.isEmpty then ctx
820+ else ctx.withProperty(CaptureSet .AssumedContains , Some (ac))
821+
817822 inNestedLevel : // TODO: needed here?
818- try checkInferredResult(super .recheckDefDef(tree, sym), tree)
823+ try checkInferredResult(super .recheckDefDef(tree, sym)( using bodyCtx) , tree)
819824 finally
820825 if ! sym.isAnonymousFunction then
821826 // Anonymous functions propagate their type to the enclosing environment
822827 // so it is not in general sound to interpolate their types.
823828 interpolateVarsIn(tree.tpt)
824829 curEnv = saved
825-
830+ end recheckDefDef
831+
826832 /** If val or def definition with inferred (result) type is visible
827833 * in other compilation units, check that the actual inferred type
828834 * conforms to the expected type where all inferred capture sets are dropped.
0 commit comments