-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
What's the intended behaviour here?
Example
proc echoInt(n: int) =
echo n
func foo(n: int, bar: proc(x: int)) =
bar(n)
foo(2, echoInt)See: https://play.nim-lang.org/#ix=2HiM
Current Output
2
which also occurs if you compile with --experimental:strictFuncs.
Expected Output
Either
2
in which case, I think the manual could be a little clearer, or:
foo.nim(4, 6) Error: 'foo' can have side effects
which is what happens if you call echoInt inside the func more directly:
proc echoInt(n: int) =
echo n
func foo(n: int, bar: proc(x: int)) =
- bar(n)
+ echoInt(n)
foo(2, echoInt)An error is produced if we write:
proc echoInt(n: int) =
echo n
-func foo(n: int, bar: proc(x: int)) =
+func foo(n: int, bar: proc(x: int) {.noSideEffect.}) =
bar(n)
foo(2, echoInt)Additional Information
This behaviour occurs with devel and all Nim versions going back to v0.18.0, which introduced func.
The manual contains:
Lines 6155 to 6161 in 9ce2f87
| The ``noSideEffect`` pragma is used to mark a proc/iterator to have no side | |
| effects. This means that the proc/iterator only changes locations that are | |
| reachable from its parameters and the return value only depends on the | |
| arguments. If none of its parameters have the type ``var T`` or ``out T`` | |
| or ``ref T`` or ``ptr T`` this means no locations are modified. It is a static | |
| error to mark a proc/iterator to have no side effect if the compiler cannot | |
| verify this. |
The procedural type is internally a pointer to a procedure, but I don't know if it's supposed to be covered by "var T or out T
or ref T or ptr T".
The experimental manual says this about strictFuncs:
Nim/doc/manual_experimental.rst
Lines 1785 to 1790 in 9ce2f87
| Since version 1.4 a stricter definition of "side effect" is available. In addition | |
| to the existing rule that a side effect is calling a function with side effects | |
| the following rule is also enforced: | |
| Any mutation to an object does count as a side effect if that object is reachable | |
| via a parameter that is not declared as a ``var`` parameter. |