Open Menduist opened 1 year ago
Note: this PR targets https://github.com/status-im/nim-chronos/pull/251
While working on https://github.com/status-im/nim-chronos/pull/298, I quickly realized that we need such a system, for instance for wait:
proc wait*[T](fut: Future[T], timeout = InfiniteDuration): Future[T] {.asyncraisesof: [fut].}
This PR adds the possibility to do "async raises of" (similar to "effectsOf"):
proc test44 {.asyncraises: [ValueError], async.} = discard proc testOther {.asyncraises: [IOError], async.} = discard proc wrapper1(fut: Future[void]) {.asyncraises: [CancelledError], async, asyncraisesof: [fut].} = await fut proc test55 {.asyncraises: [ValueError, CancelledError], async.} = await wrapper1(test44()) waitFor(test55()) checkNotCompiles: proc wrapper2(fut: Future[void]) {.asyncraises: [CancelledError], async, asyncraisesof: [fut].} = await testOther() waitFor wrapper2(test44())
(this also works with "manual async", see tests)
This is a bit complex, but essentially relies on two things:
wrapper1 will become a generic taking the error types as generic parameters:
wrapper1
proc wrapper1[Err1_469768925](fut: RaiseTrackingFuture[void, Err1_469768925]): auto {. stackTrace: off, raises: [], gcsafe.} =
The return type will then be rewritten using a typed macro (that will have the generic types instantiated):
typed
result = RaiseTrackingFuture[void, combineAsyncExceptions(CancelledError, Err1)](nil)
(note that instead of auto & result =, a typed macro could directly rewrite the return type, but did this here for simplicity)
auto
result =
This will give the correct return type to the procedure once instantiated.
For .async. procedures, a second type macro will make sure that the iterator can only raise the correct exceptions:
.async.
asyncinternalraises(iterator wrapper1_469768926( chronosInternalRetFuture: Future[void]): FutureBase {.closure, gcsafe, gcsafe.} = [...] , [CancelledError, Err1])
At instantiation, will rewrite to:
iterator wrapper1_469769166(chronosInternalRetFuture: Future[void]): FutureBase {. closure, gcsafe, gcsafe, raises: [CancelledError, ValueError].} =
I'm not very happy with the code ATM hence the draft, but it works in basic cases at least
Note: this PR targets https://github.com/status-im/nim-chronos/pull/251
While working on https://github.com/status-im/nim-chronos/pull/298, I quickly realized that we need such a system, for instance for wait:
This PR adds the possibility to do "async raises of" (similar to "effectsOf"):
(this also works with "manual async", see tests)
This is a bit complex, but essentially relies on two things:
wrapper1
will become a generic taking the error types as generic parameters:The return type will then be rewritten using a
typed
macro (that will have the generic types instantiated):(note that instead of
auto
&result =
, a typed macro could directly rewrite the return type, but did this here for simplicity)This will give the correct return type to the procedure once instantiated.
For
.async.
procedures, a second type macro will make sure that the iterator can only raise the correct exceptions:At instantiation, will rewrite to:
I'm not very happy with the code ATM hence the draft, but it works in basic cases at least