From b8b4e1fc477edeb1ca0b0ae641d0e8fa5c3416ab Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Mon, 25 Mar 2024 10:37:42 +0100 Subject: [PATCH] make `Raising` compatible with 2.0 (#526) * make `Raising` compatible with 2.0 See https://github.com/nim-lang/Nim/issues/23432 * Update tests/testfut.nim * Update tests/testfut.nim --- chronos/internal/raisesfutures.nim | 23 +++++++++++++++++++---- tests/testfut.nim | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/chronos/internal/raisesfutures.nim b/chronos/internal/raisesfutures.nim index 07e3438e..546f3b73 100644 --- a/chronos/internal/raisesfutures.nim +++ b/chronos/internal/raisesfutures.nim @@ -59,17 +59,32 @@ proc members(tup: NimNode): seq[NimNode] {.compileTime.} = macro hasException(raises: typedesc, ident: static string): bool = newLit(raises.members.anyIt(it.eqIdent(ident))) -macro Raising*[T](F: typedesc[Future[T]], E: varargs[typedesc]): untyped = +macro Raising*[T](F: typedesc[Future[T]], E: typed): untyped = ## Given a Future type instance, return a type storing `{.raises.}` ## information ## ## Note; this type may change in the future - E.expectKind(nnkBracket) - let raises = if E.len == 0: + # An earlier version used `E: varargs[typedesc]` here but this is buggyt/no + # longer supported in 2.0 in certain cases: + # https://github.com/nim-lang/Nim/issues/23432 + let + e = + case E.getTypeInst().typeKind() + of ntyTypeDesc: @[E] + of ntyArray: + for x in E: + if x.getTypeInst().typeKind != ntyTypeDesc: + error("Expected typedesc, got " & repr(x), x) + E.mapIt(it) + else: + error("Expected typedesc, got " & repr(E), E) + @[] + + let raises = if e.len == 0: makeNoRaises() else: - nnkTupleConstr.newTree(E.mapIt(it)) + nnkTupleConstr.newTree(e) nnkBracketExpr.newTree( ident "InternalRaisesFuture", nnkDotExpr.newTree(F, ident"T"), diff --git a/tests/testfut.nim b/tests/testfut.nim index 8c082931..c2231f12 100644 --- a/tests/testfut.nim +++ b/tests/testfut.nim @@ -2047,9 +2047,27 @@ suite "Future[T] behavior test suite": check: future1.cancelled() == true future2.cancelled() == true + test "Sink with literals": # https://github.com/nim-lang/Nim/issues/22175 let fut = newFuture[string]() fut.complete("test") check: fut.value() == "test" + + test "Raising type matching": + type X[E] = Future[void].Raising(E) + + proc f(x: X) = discard + + var v: Future[void].Raising([ValueError]) + f(v) + + type Object = object + # TODO cannot use X[[ValueError]] here.. + field: Future[void].Raising([ValueError]) + discard Object(field: v) + + check: + not compiles(Future[void].Raising([42])) + not compiles(Future[void].Raising(42))