From 2dd113f7543788c8ee8dce655157cc1ea3348623 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Tue, 19 Oct 2021 19:35:48 +0300 Subject: [PATCH] More progress towards Lent[T] in Nim 1.6 * Worked-around a bug where Nim comlains that the return value is not a path expression in functions lacking explicit return statements * Worked-around a limitation that Nim doesn't allow: let foo: lent T = makeT() --- stew/results.nim | 22 ++++++++++++++++------ tests/test_results.nim | 4 ++++ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/stew/results.nim b/stew/results.nim index c6822e2..b923167 100644 --- a/stew/results.nim +++ b/stew/results.nim @@ -466,14 +466,14 @@ func get*[T: not void, E](self: Result[T, E]): Lent[T] {.inline.} = ## Exception bridge mode: raise given Exception instead ## See also: Option.get assertOk(self) - self.v + return self.v func tryGet*[T: not void, E](self: Result[T, E]): Lent[T] {.inline.} = ## Fetch value of result if set, or raise ## When E is an Exception, raise that exception - otherwise, raise a ResultError[E] mixin raiseResultError if not self.o: self.raiseResultError() - self.v + return self.v func get*[T, E](self: Result[T, E], otherwise: T): Lent[T] {.inline.} = ## Fetch value of result if set, or return the value `otherwise` @@ -523,7 +523,7 @@ func expect*[T: not void, E](self: Result[T, E], m: string): Lent[T] = raiseResultDefect(m, self.e) else: raiseResultDefect(m) - self.v + return self.v func expect*[T: not void, E](self: var Result[T, E], m: string): var T = if not self.o: @@ -545,7 +545,7 @@ func error*[T, E](self: Result[T, E]): Lent[E] = raiseResultDefect("Trying to access error when value is set", self.v) else: raiseResultDefect("Trying to access error when value is set") - self.e + return self.e template value*[T, E](self: Result[T, E]): Lent[T] = mixin get @@ -651,6 +651,11 @@ template value*[E](self: var Result[void, E]) = mixin get self.get() +template isBorrowable*(x: typed): bool = + type T = typeof(x) + compiles: + let v: Lent[T] = x + template `?`*[T, E](self: Result[T, E]): auto = ## Early return - if self is an error, we will return from the current ## function, else we'll move on.. @@ -659,9 +664,14 @@ template `?`*[T, E](self: Result[T, E]): auto = ## let v = ? funcWithResult() ## echo v # prints value, not Result! ## ``` - let v: Lent[Result[T, E]] = self + type S = typeof(self) + when isBorrowable(self): + let v: Lent[S] = self + else: + let v = self + if not v.o: - when typeof(result) is typeof(v): + when typeof(result) is typeof(self): return v else: return err(typeof(result), v.e) diff --git a/tests/test_results.nim b/tests/test_results.nim index 2465a2c..e03c6d4 100644 --- a/tests/test_results.nim +++ b/tests/test_results.nim @@ -168,8 +168,12 @@ doAssert testErr().error == "323" doAssert testOk().expect("testOk never fails") == 42 +static: doAssert isBorrowable(works()) == false +static: doAssert isBorrowable(counter2) == true + func testQn(): Result[int, string] = let x = ?works() - ?works() + static: doAssert isBorrowable(x) == true result.ok(x) func testQn2(): Result[int, string] =