From 1ff81c60eaaff6867fef81680273f3d0f4b5d18b Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Mon, 6 May 2024 10:56:48 +0200 Subject: [PATCH] avoid warning in noCancel with non-raising future (#540) --- chronos/internal/asyncfutures.nim | 19 +++++++++++------- tests/testmacro.nim | 32 ++++++++++++++++++++++++++++++- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/chronos/internal/asyncfutures.nim b/chronos/internal/asyncfutures.nim index 1898685a..6c8f2bdd 100644 --- a/chronos/internal/asyncfutures.nim +++ b/chronos/internal/asyncfutures.nim @@ -1031,19 +1031,24 @@ proc noCancel*[F: SomeFuture](future: F): auto = # async: (raw: true, raises: as let retFuture = newFuture[F.T]("chronos.noCancel(T)", {FutureFlag.OwnCancelSchedule}) template completeFuture() = + const canFail = when declared(InternalRaisesFutureRaises): + InternalRaisesFutureRaises isnot void + else: + true + if future.completed(): when F.T is void: retFuture.complete() else: retFuture.complete(future.value) - elif future.failed(): - when F is Future: - retFuture.fail(future.error, warn = false) - when declared(InternalRaisesFutureRaises): - when InternalRaisesFutureRaises isnot void: - retFuture.fail(future.error, warn = false) else: - raiseAssert("Unexpected future state [" & $future.state & "]") + when canFail: # Avoid calling `failed` on non-failing raises futures + if future.failed(): + retFuture.fail(future.error, warn = false) + else: + raiseAssert("Unexpected future state [" & $future.state & "]") + else: + raiseAssert("Unexpected future state [" & $future.state & "]") proc continuation(udata: pointer) {.gcsafe.} = completeFuture() diff --git a/tests/testmacro.nim b/tests/testmacro.nim index d646303a..335e2eef 100644 --- a/tests/testmacro.nim +++ b/tests/testmacro.nim @@ -519,7 +519,7 @@ suite "Exceptions tracking": noraises() - test "Nocancel errors": + test "Nocancel errors with raises": proc testit {.async: (raises: [ValueError, CancelledError]).} = await sleepAsync(5.milliseconds) raise (ref ValueError)() @@ -535,6 +535,36 @@ suite "Exceptions tracking": noraises() + test "Nocancel with no errors": + proc testit {.async: (raises: [CancelledError]).} = + await sleepAsync(5.milliseconds) + + proc test {.async: (raises: []).} = + await noCancel testit() + + proc noraises() {.raises: [].} = + let f = test() + waitFor(f.cancelAndWait()) + waitFor(f) + + noraises() + + test "Nocancel errors without raises": + proc testit {.async.} = + await sleepAsync(5.milliseconds) + raise (ref ValueError)() + + proc test {.async.} = + await noCancel testit() + + proc noraises() = + expect(ValueError): + let f = test() + waitFor(f.cancelAndWait()) + waitFor(f) + + noraises() + test "Defect on wrong exception type at runtime": {.push warning[User]: off} let f = InternalRaisesFuture[void, (ValueError,)]()