From 571119a06939b0a111a7ca9320ffce2ca42223f3 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 3 Nov 2024 23:54:44 +0100 Subject: [PATCH] Fix toFunctionType for methods containing reach capabilities in the result type --- .../src/dotty/tools/dotc/core/Types.scala | 7 +++++-- .../captures/depfun-reach.check | 14 +++++++++++++ .../captures/depfun-reach.scala | 20 +++++++++++++++++++ .../captures/gears-problem.scala | 7 ++++++- 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 tests/neg-custom-args/captures/depfun-reach.check create mode 100644 tests/neg-custom-args/captures/depfun-reach.scala diff --git a/compiler/src/dotty/tools/dotc/core/Types.scala b/compiler/src/dotty/tools/dotc/core/Types.scala index 0c1d542bd6fc..612769616ac8 100644 --- a/compiler/src/dotty/tools/dotc/core/Types.scala +++ b/compiler/src/dotty/tools/dotc/core/Types.scala @@ -38,8 +38,7 @@ import config.Printers.{core, typr, matchTypes} import reporting.{trace, Message} import java.lang.ref.WeakReference import compiletime.uninitialized -import cc.{CapturingType, CaptureRef, CaptureSet, SingletonCaptureRef, isTrackableRef, - derivedCapturingType, isBoxedCapturing, isCaptureChecking, isRetains, isRetainsLike} +import cc.* import CaptureSet.{CompareResult, IdempotentCaptRefMap, IdentityCaptRefMap} import scala.annotation.internal.sharable @@ -4074,6 +4073,10 @@ object Types extends TypeUtils { range(defn.NothingType, atVariance(1)(apply(tp.underlying))) case CapturingType(_, _) => mapOver(tp) + case ReachCapability(tp1) => + apply(tp1) match + case tp1a: CaptureRef if tp1a.isTrackableRef => tp1a.reach + case _ => defn.captureRoot.termRef case AnnotatedType(parent, ann) if ann.refersToParamOf(thisLambdaType) => val parent1 = mapOver(parent) if ann.symbol.isRetainsLike then diff --git a/tests/neg-custom-args/captures/depfun-reach.check b/tests/neg-custom-args/captures/depfun-reach.check new file mode 100644 index 000000000000..c1d7d05dc8d6 --- /dev/null +++ b/tests/neg-custom-args/captures/depfun-reach.check @@ -0,0 +1,14 @@ +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/depfun-reach.scala:13:4 ---------------------------------- +13 | op // error + | ^^ + | Found: (xs: List[(X, box () ->{io} Unit)]) ->{op} List[box () ->{xs*} Unit] + | Required: (xs: List[(X, box () ->{io} Unit)]) => List[() -> Unit] + | + | longer explanation available when compiling with `-explain` +-- [E007] Type Mismatch Error: tests/neg-custom-args/captures/depfun-reach.scala:20:60 --------------------------------- +20 | val b: (xs: List[() ->{io} Unit]) => List[() ->{} Unit] = a // error + | ^ + | Found: (xs: List[box () ->{io} Unit]) ->{a} List[box () ->{xs*} Unit] + | Required: (xs: List[box () ->{io} Unit]) => List[() -> Unit] + | + | longer explanation available when compiling with `-explain` diff --git a/tests/neg-custom-args/captures/depfun-reach.scala b/tests/neg-custom-args/captures/depfun-reach.scala new file mode 100644 index 000000000000..94b10f7dbcdb --- /dev/null +++ b/tests/neg-custom-args/captures/depfun-reach.scala @@ -0,0 +1,20 @@ +import language.experimental.captureChecking +import caps.cap + +def test(io: Object^, async: Object^) = + def compose(op: List[(() ->{cap} Unit, () ->{cap} Unit)]): List[() ->{op*} Unit] = + List(() => op.foreach((f,g) => { f(); g() })) + + def compose1(op: List[(() ->{async} Unit, () ->{io} Unit)]): List[() ->{op*} Unit] = + compose(op) + + def foo[X](op: (xs: List[(X, () ->{io} Unit)]) => List[() ->{xs*} Unit]) + : (xs: List[(X, () ->{io} Unit)]) => List[() ->{} Unit] = + op // error + + def boom(op: List[(() ->{async} Unit, () ->{io} Unit)]): List[() ->{} Unit] = + foo(compose1)(op) + +def test2(io: Object^) = + val a: (xs: List[() ->{io} Unit]) => List[() ->{xs*} Unit] = ??? + val b: (xs: List[() ->{io} Unit]) => List[() ->{} Unit] = a // error diff --git a/tests/pos-custom-args/captures/gears-problem.scala b/tests/pos-custom-args/captures/gears-problem.scala index c6ef72bc421e..531c59d9fe7d 100644 --- a/tests/pos-custom-args/captures/gears-problem.scala +++ b/tests/pos-custom-args/captures/gears-problem.scala @@ -16,4 +16,9 @@ extension [T](@use fs: Seq[Future[T]^]) val collector: Collector[T]{val futures: Seq[Future[T]^{fs*}]} = Collector(fs) // val ch = collector.results // also errors - val fut: Future[T]^{fs*} = collector.results.read().right.get // found ...^{caps.cap} \ No newline at end of file + val fut: Future[T]^{fs*} = collector.results.read().right.get // found ...^{caps.cap} + + val ch = collector.results + val item = ch.read() + val r = item.right + val fut2: Future[T]^{fs*} = r.get \ No newline at end of file