-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
add std/asserts
containing enforce
; (catchable + customizable doAssert )
#15606
Conversation
9d569a7
to
080a52c
Compare
b1ccee7
to
c092265
Compare
@Araq PTAL; I've taken into account feedback from nim-lang/RFCs#266 by turning |
std/asserts
containing enforce
; (catchable + customizable doAssert )
@Araq PTAL, see new updates below:
benchmark
/tmp/z01lean: 157K benchmark codewhen true: # D20210608T230951
import std/macros
import std/asserts
import std/private/miscdollars
template enforce2*[T](cond: untyped, arg: T, typ: typedesc = CatchableError) =
const loc = instantiationInfo(fullPaths = compileOption("excessiveStackTrace"))
{.line: loc.}:
if not cond:
const prefix = $loc & " `" & astToStr(cond) & "` "
raise newException(typ, prefix & $arg)
macro genCode(fn, c, i) =
result = newStmtList()
let m = 1000-1
var loc = instantiationInfo(fullPaths = compileOption("excessiveStackTrace"))
for i in 0..<m:
let m2 = newLit(m)
let i2 = newLit(i)
result.add quote do:
c += 7 - `i2`
# doesn't matter much which condition, the point is to generate
# a distinct `prefix` for each enforce statement
`fn` `c` + `i2` != -4924931111110 + 1000 - 1, (c, `i2`)
import std/times
template main2(algo, c)=
let n = 10000000'u
let t = cpuTime()
for i in 0..<n:
let s = $i
c += s.len
when algo == 1: genCode(enforce, c, i)
elif algo == 2: genCode(enforce2, c, i)
else: static: doAssert false
let t2 = cpuTime()
echo (t2 - t, astToStr(algo), c)
proc main()=
var c = 0
for i in 0..<1:
when defined case2a: main2(1, c)
when defined case2b: main2(2, c)
main() |
What would happen with |
I don't mind
Seriously, error reporting is not bug detection and GCC error messages do not contain stack traces pointing into GCC's inner workings. This is widely appreciated to be a good thing. |
how about (precedent: https://dlang.org/library/std/exception/enforce.html, and IMO the name std/exceptions makes sense)
I don't understand how that relates to either this PR or
my point is two-fold: A1:after this PR, this pattern: if s.len < 0: raise newException(EnforceError, "s.len >= 0 failed; " & $s.len) simplifies to this: enforce s.len < 0, s.len and results in better codegen (smaller binary sizes), as illustrated in benchmark A2:procs like # strutils.nim:
func invalidFormatString() {.noinline.} =
raise newException(ValueError, "invalid format string")
func addf*(s: var string, formatstr: string, a: varargs[string, `$`]) =
...
if num > a.high: invalidFormatString() after PR, using # strutils.nim:
func addf*(s: var string, formatstr: string, a: varargs[string, `$`]) =
...
enforce num <= a.high, "invalid format string", ValueError
# or, showing more runtime context:
enforce num <= a.high, $(num, a.high, formatstr)
# or, lazily (if we make arg optional again):
# note that this sitll will show the line + rendered conditions, which is more informative
# than the generic (reused!) "invalid format string"
enforce num <= a.high |
e41bf68
to
9970adb
Compare
PTAL
done, I moved it to std/exceptions (see above comment) |
This pull request has been automatically marked as stale because it has not had recent activity. If you think it is still a valid PR, please rebase it on the latest devel; otherwise it will be closed. Thank you for your contributions. |
fixes nim-lang/RFCs#266
links
see also nim-lang/RFCs#387 (
NimLineInfo
) which can be used in future work to further reduce binary size