Skip to content

Commit 7968f22

Browse files
committed
Charge capture sets of function types
1 parent d11c513 commit 7968f22

File tree

2 files changed

+16
-1
lines changed

2 files changed

+16
-1
lines changed

compiler/src/dotty/tools/dotc/cc/CheckCaptures.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,12 @@ class CheckCaptures extends Recheck, SymTransformer:
594594
if sym.exists && curEnv.kind != EnvKind.Boxed then
595595
markFree(capturedVars(sym).filter(isRetained), tree)
596596

597+
/** Include references captured by the type of the function. */
598+
def includeFunctionCaptures(qualType: Type, tree: Apply)(using Context): Unit =
599+
if ccConfig.caplessLike && !qualType.isAlwaysPure then
600+
val funCaptures = qualType.captureSet
601+
markFree(funCaptures, tree)
602+
597603
/** If `tp` (possibly after widening singletons) is an ExprType
598604
* of a parameterless method, map Result instances in it to Fresh instances
599605
*/
@@ -815,12 +821,15 @@ class CheckCaptures extends Recheck, SymTransformer:
815821
val argCaptures =
816822
for (argType, formal) <- argTypes.lazyZip(funType.paramInfos) yield
817823
if formal.hasAnnotation(defn.UseAnnot) then argType.deepCaptureSet else argType.captureSet
824+
if ccConfig.caplessLike then
825+
includeFunctionCaptures(qualType, tree)
818826
appType match
819827
case appType @ CapturingType(appType1, refs)
820828
if qualType.exists
821829
&& !tree.fun.symbol.isConstructor
822830
&& qualCaptures.mightSubcapture(refs)
823-
&& argCaptures.forall(_.mightSubcapture(refs)) =>
831+
&& argCaptures.forall(_.mightSubcapture(refs))
832+
&& !ccConfig.caplessLike =>
824833
val callCaptures = argCaptures.foldLeft(qualCaptures)(_ ++ _)
825834
appType.derivedCapturingType(appType1, callCaptures)
826835
.showing(i"narrow $tree: $appType, refs = $refs, qual-cs = ${qualType.captureSet} = $result", capt)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import language.experimental.captureChecking
2+
trait IO { def println(msg: String): Unit }
3+
def test1(c: IO^): Unit =
4+
val f: () -> () ->{c} Unit = () => () => c.println("hello") // ok
5+
val f2: () -> Unit = () => f()() // error
6+
val f3: () ->{c} Unit = () => f()() // ok

0 commit comments

Comments
 (0)