Youssef Shoaib [MOD]
03/22/2023, 7:38 PMrunCatching swallowing `RaiseCancellationException`s and hence not playing nicely with Raise? Should Arrow maybe offer an alternative runNonFatalCatching or a Raise.runCatching shadowed function that rethrows cancellation exceptions?simon.vergauwen
03/23/2023, 8:24 AMrunCatching swallows CancellationExeption it also swallows RaiseCancellationException 😞 This is inherit to Result since it's meant for the intrinsics of Kotlin Coroutines.
There is a top-level catch function, and Either.catch that allow avoiding this issue. We could also add something for Result 🤔 Currently:
val x: Either<Throwable, Int> = Either.catch { 1 }
val y: Either<PSQLException, Int> = Either.catchOrThrow { 1 }
val i: Int = catch({ 1 }) { _: Throwable -> fallback() }
fun Raise<E>.example(): Int =
catch({ 1 }) { _: Throwable -> raise(e) }
fun Raise<E>.example(): Int =
catch({ 1 }) { _: PSQLException -> raise(e) }Youssef Shoaib [MOD]
03/23/2023, 2:03 PMfun Raise<E>.runCatching(block: () -> R): Result<R> so that if someone takes pre-existing code that uses runCatching and then wraps some of it in effect the code would still work. Maybe even with a @Deprecated that tells them to use Either instead of Resultsimon.vergauwen
03/26/2023, 5:59 PM@Deprecated with level = Deprecation.ERROR to prevent incorrect usages 🤔 https://github.com/arrow-kt/arrow/issues/2838
I'm still awaiting FIR to be-able to do add IDEA inspections through a compiler plugin, but that seems quite far away. Building a IDEA plugin seems a bad workaround.Youssef Shoaib [MOD]
03/26/2023, 9:32 PMDeprecation.ERROR runCatching function that tells the person to use either. Shall I make a PR for that, and perhaps even for bind errors? Only issue is, I'm not sure how we'd write tests to test that those functions are doing their job correctly...simon.vergauwen
04/02/2023, 5:19 PMrunCatching inside Raise that doesn't catch the RaiseCancellationException but still captures the more general CancellationException. Or even not catch it at all.
It's possible since it'll prefer the version declared on the receivers, not sure how it would behave with context receivers though.. They fix the problem of scope pollution, but not sure how it works with a function defined on a context vs top-level. I guess it would still prefer the context variant.Youssef Shoaib [MOD]
04/02/2023, 5:25 PMRaiseCancellationException, and hence every erroneous instance of runCatching { somethingThatUsesRaise() } will always have a Raise receiver in scope, and any other runCatching invocation outside of a Raise receiver would never throw RaiseCancellationException anyways.simon.vergauwen
04/02/2023, 5:26 PMin this case only functions that take a Raise as some form of receiver (extension, dispatch, or context) would ever be able to throw aYes, that was exactly my train of thought, and hence every erroneous instance ofRaiseCancellationExceptionwill always have a Raise receiver in scope, and any otherrunCatching { somethingThatUsesRaise() }invocation outside of a Raise receiver would never throwrunCatchinganyways.RaiseCancellationException
Youssef Shoaib [MOD]
04/02/2023, 5:26 PMsimon.vergauwen
04/02/2023, 5:27 PMYoussef Shoaib [MOD]
04/02/2023, 5:27 PMfun myStupidFun(raise: Raise<Blah>) = with(raise) { ... }simon.vergauwen
04/02/2023, 5:27 PMwhile if it was a member of the Raise interface, then it doesn't need to be importedI meant as a member on
Raise, I thought we already came to the conclusion that was a requirement 😜simon.vergauwen
04/02/2023, 5:28 PMfun myStupidFun(raise: Raise<Blah>) =
runCatching { raise.raise(blah) }Youssef Shoaib [MOD]
04/02/2023, 5:28 PMcontext(Raise) fun runCatchingsimon.vergauwen
04/02/2023, 5:29 PMYoussef Shoaib [MOD]
04/02/2023, 5:29 PMsimon.vergauwen
04/02/2023, 5:30 PM