@@ -676,29 +676,24 @@ class CheckCaptures extends Recheck, SymTransformer:
676
676
i " Sealed type variable $pname" , " be instantiated to" ,
677
677
i " This is often caused by a local capability $where\n leaking as part of its result. " ,
678
678
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)
682
681
end recheckTypeApply
683
682
684
683
/** Faced with a tree of form `caps.contansImpl[CS, r.type]`, check that `R` is a tracked
685
684
* capability and assert that `{r} <:CS`.
686
685
*/
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 _ =>
702
697
703
698
override def recheckBlock (tree : Block , pt : Type )(using Context ): Type =
704
699
inNestedLevel(super .recheckBlock(tree, pt))
@@ -814,15 +809,26 @@ class CheckCaptures extends Recheck, SymTransformer:
814
809
val localSet = capturedVars(sym)
815
810
if ! localSet.isAlwaysEmpty then
816
811
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
+
817
822
inNestedLevel : // TODO: needed here?
818
- try checkInferredResult(super .recheckDefDef(tree, sym), tree)
823
+ try checkInferredResult(super .recheckDefDef(tree, sym)( using bodyCtx) , tree)
819
824
finally
820
825
if ! sym.isAnonymousFunction then
821
826
// Anonymous functions propagate their type to the enclosing environment
822
827
// so it is not in general sound to interpolate their types.
823
828
interpolateVarsIn(tree.tpt)
824
829
curEnv = saved
825
-
830
+ end recheckDefDef
831
+
826
832
/** If val or def definition with inferred (result) type is visible
827
833
* in other compilation units, check that the actual inferred type
828
834
* conforms to the expected type where all inferred capture sets are dropped.
0 commit comments