diff --git a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala index d21e9c7d5064..6dbf7d05c474 100644 --- a/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala +++ b/compiler/src/dotty/tools/dotc/cc/CaptureOps.scala @@ -94,6 +94,8 @@ extension (tp: Type) def retainedElementsRaw(using Context): List[Type] = tp match case OrType(tp1, tp2) => tp1.retainedElementsRaw ++ tp2.retainedElementsRaw + case AnnotatedType(tp1, ann) if tp1.derivesFrom(defn.Caps_CapSet) && ann.symbol.isRetains => + ann.tree.retainedSet.retainedElementsRaw case tp => // Nothing is a special type to represent the empty set if tp.isNothingType then Nil diff --git a/tests/pos-custom-args/captures/i23570.scala b/tests/pos-custom-args/captures/i23570.scala new file mode 100644 index 000000000000..44f378792317 --- /dev/null +++ b/tests/pos-custom-args/captures/i23570.scala @@ -0,0 +1,7 @@ +def f[C^](xs: List[() ->{C} Unit]): List[() ->{C} Unit] = + xs.reverse + +def test(io: Object^, async: Object^): Unit = + val ok = f[{io}](Nil) + val x = f[{io}] // was error + val y = f[{io, async}] // was error diff --git a/tests/pos/cc-use-alternatives.scala b/tests/pos/cc-use-alternatives.scala new file mode 100644 index 000000000000..ddfcc3b62f8b --- /dev/null +++ b/tests/pos/cc-use-alternatives.scala @@ -0,0 +1,24 @@ +import language.experimental.captureChecking +// no separation checking +import caps.{cap, use} + +def foo1(@use xs: List[() => Unit]): Unit = + var x: () ->{xs*} Unit = xs.head + var ys = xs + while ys.nonEmpty do + ys = ys.tail + x = ys.head + +def foo2(@use xs: List[() => Unit]): Unit = + var x: () => Unit = xs.head // note: this would fail separation checking + var ys = xs + while ys.nonEmpty do + ys = ys.tail + x = ys.head + +def foo3[@use C^](xs: List[() ->{C} Unit]): Unit = + var x: () ->{C} Unit = xs.head + var ys = xs + while ys.nonEmpty do + ys = ys.tail + x = ys.head