Skip to content

Commit 505ba09

Browse files
committed
this solves the last invalid case but costs us two reasonable use cases
1 parent f3f8b6a commit 505ba09

File tree

2 files changed

+53
-31
lines changed

2 files changed

+53
-31
lines changed

core/src/main/scala/ox/supervised.scala

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,18 @@ package ox
33
import java.util.concurrent.atomic.AtomicInteger
44
import java.util.concurrent.{CompletableFuture, ConcurrentHashMap}
55
import scala.reflect.ClassTag
6+
import scala.util.NotGiven
7+
import scala.util.boundary.Label
68

79
sealed abstract class Supervised
810
object SupervisedEvidence extends Supervised
911

12+
private inline def availableInScope[A]: Boolean =
13+
compiletime.summonFrom {
14+
case _: NotGiven[A] => false
15+
case _: A => true
16+
}
17+
1018
/** Starts a new concurrency scope, which allows starting forks in the given code block `f`. Forks can be started using [[fork]],
1119
* [[forkUser]], [[forkCancellable]] and [[forkUnsupervised]]. All forks are guaranteed to complete before this scope completes.
1220
*
@@ -27,7 +35,19 @@ object SupervisedEvidence extends Supervised
2735
* @see
2836
* [[supervisedError]] Starts a scope in supervised mode, with the additional ability to report application errors
2937
*/
30-
def supervised[T](f: Supervised ?=> Ox ?=> T): T = supervisedError(NoErrorMode)(f)
38+
inline def supervised[T](f: Supervised ?=> Ox ?=> T): T =
39+
inline if availableInScope[Label[Either[Nothing, Nothing]]] && availableInScope[Forked] then
40+
compiletime.error(
41+
"Nesting supervised scopes along with fork and either blocks is disallowed to prevent unsafe .ok() combinator usage on forks."
42+
)
43+
else supervisedErrorInternal(NoErrorMode)(f)
44+
45+
inline def supervisedError[E, F[_], T](em: ErrorMode[E, F])(f: Supervised ?=> OxError[E, F] ?=> F[T]): F[T] =
46+
inline if availableInScope[Label[Either[Nothing, Nothing]]] && availableInScope[Forked] then
47+
compiletime.error(
48+
"Nesting supervised scopes along with fork and either blocks is disallowed to prevent unsafe .ok() combinator usage on forks."
49+
)
50+
else supervisedErrorInternal(em)(f)
3151

3252
/** Starts a new concurrency scope, which allows starting forks in the given code block `f`. Forks can be started using [[fork]],
3353
* [[forkError]], [[forkUser]], [[forkUserError]], [[forkCancellable]] and [[forkUnsupervised]]. All forks are guaranteed to complete
@@ -39,7 +59,7 @@ def supervised[T](f: Supervised ?=> Ox ?=> T): T = supervisedError(NoErrorMode)(
3959
* @see
4060
* [[forkError]] On details how to use application errors.
4161
*/
42-
def supervisedError[E, F[_], T](em: ErrorMode[E, F])(f: Supervised ?=> OxError[E, F] ?=> F[T]): F[T] =
62+
def supervisedErrorInternal[E, F[_], T](em: ErrorMode[E, F])(f: Supervised ?=> OxError[E, F] ?=> F[T]): F[T] =
4363
val s = DefaultSupervisor[E]
4464
val capability = OxError(s, em)
4565
try

core/src/test/scala/ox/ForkEitherInteropTest.scala

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -196,35 +196,37 @@ class ForkEitherInteropTest extends AnyFlatSpec with Matchers {
196196
}
197197
}""" should compile
198198

199-
"""
200-
import ox.*
201-
import ox.either.*
202-
203-
either {
204-
supervised {
205-
fork {
206-
supervised {
207-
Right(1).ok()
208-
}
209-
}
210-
}
211-
}""" should compile
212-
213-
"""
214-
import ox.*
215-
import ox.either.*
216-
217-
either {
218-
supervised {
219-
fork {
220-
supervised {
221-
fork {
222-
Right(1).ok()
223-
}
224-
}
225-
}
226-
}
227-
}""" should compile
199+
// the new approach with supervised nesting prevention disallows these two examples but fixes last example in subsequent test
200+
201+
// """
202+
// import ox.*
203+
// import ox.either.*
204+
//
205+
// either {
206+
// supervised {
207+
// fork {
208+
// supervised {
209+
// Right(1).ok()
210+
// }
211+
// }
212+
// }
213+
// }""" should compile
214+
215+
// """
216+
// import ox.*
217+
// import ox.either.*
218+
//
219+
// either {
220+
// supervised {
221+
// fork {
222+
// supervised {
223+
// fork {
224+
// Right(1).ok()
225+
// }
226+
// }
227+
// }
228+
// }
229+
// }""" should compile
228230

229231
"""
230232
import ox.*

0 commit comments

Comments
 (0)