Skip to content

func doesn't check for side effects in proc parameters #16303

@ee7

Description

@ee7

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:

Nim/doc/manual.rst

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:

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationRelated to documentation content (not generation).EasyHacktoberfest (Open)Issues suitable for Hacktoberfest, open for working on.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions