fix manual to reflect reality for .nosideeffect (#16781)
This commit is contained in:
parent
aca97250ea
commit
8f62cd512c
2 changed files with 49 additions and 6 deletions
|
|
@ -6141,13 +6141,13 @@ This pragma can also take in an optional warning string to relay to developers.
|
||||||
noSideEffect pragma
|
noSideEffect pragma
|
||||||
-------------------
|
-------------------
|
||||||
|
|
||||||
The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side
|
The ``noSideEffect`` pragma is used to mark a proc/iterator that can have only
|
||||||
effects. This means that the proc/iterator only changes locations that are
|
side effects through parameters. This means that the proc/iterator only changes locations that are
|
||||||
reachable from its parameters and the return value only depends on the
|
reachable from its parameters and the return value only depends on the
|
||||||
arguments. If none of its parameters have the type ``var T`` or ``ref T``
|
parameters. If none of its parameters have the type `var`, `ref`, `ptr`, `cstring`, or `proc`,
|
||||||
or ``ptr T`` this means no locations are modified. It is a static error to
|
then no locations are modified.
|
||||||
mark a proc/iterator to have no side effect if the compiler cannot verify
|
|
||||||
this.
|
It is a static error to mark a proc/iterator to have no side effect if the compiler cannot verify this.
|
||||||
|
|
||||||
As a special semantic rule, the built-in `debugEcho
|
As a special semantic rule, the built-in `debugEcho
|
||||||
<system.html#debugEcho,varargs[typed,]>`_ pretends to be free of side effects,
|
<system.html#debugEcho,varargs[typed,]>`_ pretends to be free of side effects,
|
||||||
|
|
@ -6168,6 +6168,25 @@ To override the compiler's side effect analysis a ``{.noSideEffect.}``
|
||||||
{.cast(noSideEffect).}:
|
{.cast(noSideEffect).}:
|
||||||
echo "test"
|
echo "test"
|
||||||
|
|
||||||
|
When a `noSideEffect` proc has proc params `bar`, whether it can be used inside a `noSideEffect` context
|
||||||
|
depends on what the compiler knows about `bar`:
|
||||||
|
|
||||||
|
.. code-block:: nim
|
||||||
|
:test: "nim c $1"
|
||||||
|
|
||||||
|
func foo(bar: proc(): int): int = bar()
|
||||||
|
var count = 0
|
||||||
|
proc fn1(): int = 1
|
||||||
|
proc fn2(): int = (count.inc; count)
|
||||||
|
func fun1() = discard foo(fn1) # ok because fn1 is inferred as `func`
|
||||||
|
# func fun2() = discard foo(fn2) # would give: Error: 'fun2' can have side effects
|
||||||
|
|
||||||
|
# with callbacks, the compiler is conservative, ie that bar will have side effects
|
||||||
|
var foo2: type(foo) = foo
|
||||||
|
func main() =
|
||||||
|
discard foo(fn1) # ok
|
||||||
|
# discard foo2(fn1) # now this errors
|
||||||
|
|
||||||
|
|
||||||
compileTime pragma
|
compileTime pragma
|
||||||
------------------
|
------------------
|
||||||
|
|
|
||||||
24
tests/effects/tnosideeffect.nim
Normal file
24
tests/effects/tnosideeffect.nim
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
block: # `.noSideEffect`
|
||||||
|
func foo(bar: proc(): int): int = bar()
|
||||||
|
var count = 0
|
||||||
|
proc fn1(): int = 1
|
||||||
|
proc fn2(): int = (count.inc; count)
|
||||||
|
|
||||||
|
template accept(body) =
|
||||||
|
doAssert compiles(block:
|
||||||
|
body)
|
||||||
|
|
||||||
|
template reject(body) =
|
||||||
|
doAssert not compiles(block:
|
||||||
|
body)
|
||||||
|
|
||||||
|
accept:
|
||||||
|
func fun1() = discard foo(fn1)
|
||||||
|
reject:
|
||||||
|
func fun1() = discard foo(fn2)
|
||||||
|
|
||||||
|
var foo2: type(foo) = foo
|
||||||
|
accept:
|
||||||
|
func main() = discard foo(fn1)
|
||||||
|
reject:
|
||||||
|
func main() = discard foo2(fn1)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue