summary refs log tree commit diff stats
path: root/tests/effects
diff options
context:
space:
mode:
authorquantimnot <54247259+quantimnot@users.noreply.github.com>2021-07-15 14:43:57 -0400
committerGitHub <noreply@github.com>2021-07-15 20:43:57 +0200
commita9701f6531288ab3ba2c2a7ff0124802ae78122c (patch)
tree63eafc6ea0941afb9f6b1c10e5825f981eb9a594 /tests/effects
parentaf3d2d8ad90c31161c34f0d4f82cd0ac4a9b3d00 (diff)
downloadNim-a9701f6531288ab3ba2c2a7ff0124802ae78122c.tar.gz
Extended side effect error messages (#18418)
* Extended side effect error messages

* Applied feedback:
- refactored `markSideEffect`
- refactored string interpolations
- single message
- skip diagnostics in `system.compiles` context

Other:
- started a test of diagnostic messages

[ci skip] Tests aren't updated yet because messaging isn't nailed down.

* - Added hints of where for side effect call locations.
- Tried to clarify the reasons.

* fix tests

* Applied PR review feedback:
  - moved collection of side effects from TSym to TContext
  - used pragma shorthand form `.sideEffect` and `.noSideEffect` in messages
  - added leading '>' to structured messages for readability
  - changed `sempass2.markSideEffect` to a proc
  - replaced `system.echo` in the test to make the test compatible with Windows

* Applied NEP1 formatting suggestion

Co-authored-by: quantimnot <quantimnot@users.noreply.github.com>
Diffstat (limited to 'tests/effects')
-rw-r--r--tests/effects/tdiagnostic_messages.nim37
1 files changed, 37 insertions, 0 deletions
diff --git a/tests/effects/tdiagnostic_messages.nim b/tests/effects/tdiagnostic_messages.nim
new file mode 100644
index 000000000..2ce4895a3
--- /dev/null
+++ b/tests/effects/tdiagnostic_messages.nim
@@ -0,0 +1,37 @@
+discard """
+  nimoutFull: true
+  action: "reject"
+  cmd: "nim r --hint:Conf:off $file"
+  nimout: '''
+tdiagnostic_messages.nim(36, 6) Error: 'a' can have side effects
+> tdiagnostic_messages.nim(37, 30) Hint: 'a' calls `.sideEffect` 'callWithSideEffects'
+>> tdiagnostic_messages.nim(29, 6) Hint: 'callWithSideEffects' called by 'a'
+>>> tdiagnostic_messages.nim(31, 34) Hint: 'callWithSideEffects' calls `.sideEffect` 'indirectCallViaVarParam'
+>>>> tdiagnostic_messages.nim(25, 6) Hint: 'indirectCallViaVarParam' called by 'callWithSideEffects'
+>>>>> tdiagnostic_messages.nim(26, 7) Hint: 'indirectCallViaVarParam' calls routine via hidden pointer indirection
+>>> tdiagnostic_messages.nim(32, 33) Hint: 'callWithSideEffects' calls `.sideEffect` 'indirectCallViaPointer'
+>>>> tdiagnostic_messages.nim(27, 6) Hint: 'indirectCallViaPointer' called by 'callWithSideEffects'
+>>>>> tdiagnostic_messages.nim(28, 32) Hint: 'indirectCallViaPointer' calls routine via pointer indirection
+>>> tdiagnostic_messages.nim(33, 10) Hint: 'callWithSideEffects' calls `.sideEffect` 'myEcho'
+>>>> tdiagnostic_messages.nim(24, 6) Hint: 'myEcho' called by 'callWithSideEffects'
+>>> tdiagnostic_messages.nim(34, 3) Hint: 'callWithSideEffects' accesses global state 'globalVar'
+>>>> tdiagnostic_messages.nim(23, 5) Hint: 'globalVar' accessed by 'callWithSideEffects'
+
+'''
+"""
+
+var globalVar = 0
+proc myEcho(a: string) {.sideEffect.} = discard
+proc indirectCallViaVarParam(call: var proc(): int {.nimcall.}): int =
+  call()
+proc indirectCallViaPointer(call: pointer): int =
+  cast[ptr proc(): int](call)[]()
+proc callWithSideEffects(): int =
+  var p = proc (): int {.nimcall.} = 0
+  discard indirectCallViaVarParam(p)
+  discard indirectCallViaPointer(addr p)
+  myEcho ""
+  globalVar
+
+func a: int =
+  discard callWithSideEffects()