The Effect System
20.1 Exception Tracking (raises)
The compiler infers effects. The raises annotation makes them part of the API contract.
A common pattern: {.push raises: [].} at the top of a module (used heavily in Status' codebases).
proc safeDiv(a, b: int): int {.raises: [DivByZeroDefect].} = a div b
proc parse(s: string): int {.raises: [ValueError].} = parseInt(s)
proc noThrow() {.raises: [].} = # compiler verifies that no exceptions escape
try: discard parse("x")
except ValueError: discard20.2 Tag Tracking (tags)
Built-in tags: ReadIOEffect, WriteIOEffect, TimeEffect, ExecIOEffect, RootEffect.
forbids pragma (Nim 2): proc f() {.forbids: [IOEffect].}.
type
DbEffect = object of RootEffect
proc queryDb() {.tags: [DbEffect].} = discard
proc pureLogic() {.tags: [].} = discard # must not call queryDb20.3 Side Effects and func
func = proc {.noSideEffect.}: can't access global mutable state, I/O, or call side-effecting procs.
--experimental:strictFuncs additionally forbids mutating data reachable through ref params.
Debug escape hatch: {.cast(noSideEffect).}: echo "debug".
20.4 GC Safety
{.gcsafe.}: the proc doesn't access GC'd global memory, which is required for thread procs.
{.cast(gcsafe).}: ... to override (unsafe).