From 57e467b8b0c09a93e7e05256df123bb220d6a8ef Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Sun, 10 Mar 2024 12:02:45 +0100 Subject: [PATCH] Fix: `without` should work when `$` has side effects It's ok to use unsafeError in bindFailed, because we've already checked that the result contains an error. --- questionable/private/binderror.nim | 10 +++++----- testmodules/results/test.nim | 13 +++++++++++++ 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/questionable/private/binderror.nim b/questionable/private/binderror.nim index 926e0c3..d6973f5 100644 --- a/questionable/private/binderror.nim +++ b/questionable/private/binderror.nim @@ -21,16 +21,16 @@ macro captureBindError*(error: var ref CatchableError, expression): auto = # return the evaluated result evaluated -func error[T](_: Option[T]): ref CatchableError = +func unsafeError[T](_: Option[T]): ref CatchableError = newException(ValueError, "Option is set to `none`") -func error[T](_: ref T): ref CatchableError = +func unsafeError[T](_: ref T): ref CatchableError = newException(ValueError, "ref is nil") -func error[T](_: ptr T): ref CatchableError = +func unsafeError[T](_: ptr T): ref CatchableError = newException(ValueError, "ptr is nil") -func error[Proc: proc | iterator](_: Proc): ref CatchableError = +func unsafeError[Proc: proc | iterator](_: Proc): ref CatchableError = newException(ValueError, "proc or iterator is nil") macro bindFailed*(expression: typed) = @@ -49,4 +49,4 @@ macro bindFailed*(expression: typed) = # check that the error variable is in scope when compiles(`errorVariable`): # assign bind error to error variable - `errorVariable` = `expression`.error + `errorVariable` = `expression`.unsafeError diff --git a/testmodules/results/test.nim b/testmodules/results/test.nim index 4a4a47c..96c0aac 100644 --- a/testmodules/results/test.nim +++ b/testmodules/results/test.nim @@ -643,6 +643,19 @@ suite "result": someProc(42.success) someProc(int.failure "some error") +type TypeWithSideEffect = object +proc `$`*(value: TypeWithSideEffect): string {.sideEffect.} = + discard + +suite "result side effects": + + test "without statement with error works when `$` has side effects": + proc foo = + without x =? TypeWithSideEffect.failure("error"), error: + discard error + return + fail() + foo() import pkg/questionable/resultsbase