Summary
Using return inside a changes callback body silently exits only the callback body rather than the enclosing proc. This causes subtle bugs where code after the return is never reached, but no error or warning is raised.
Example
state.some_value.changes:
if not condition:
return # intended to skip processing, but may not behave as expected
# ... rest of handler
In practice, we had a changes(false) callback (pause disabled) where a top-level if not added: return was silently swallowing the callback re-invocations triggered by setting the value inside the callback. The return appeared to work for the initial call but the re-triggered callbacks never produced the expected side effects, causing a 10s timeout waiting for a response that never came.
Removing the return and restructuring as if added: ... fixed the issue.
Expected behavior
Either:
return inside a changes body should return from the enclosing proc (consistent with how Nim templates typically work when the body is inlined), or
- A compile-time error should be raised if
return is used inside a changes body, since the semantics are likely not what the user expects.
Notes
This may be intentional if the changes macro/template wraps the body in a proc or closure — in that case a compile error with a helpful message ("use break or restructure with if instead of return") would prevent confusing bugs.
Summary
Using
returninside achangescallback body silently exits only the callback body rather than the enclosing proc. This causes subtle bugs where code after thereturnis never reached, but no error or warning is raised.Example
In practice, we had a
changes(false)callback (pause disabled) where a top-levelif not added: returnwas silently swallowing the callback re-invocations triggered by setting the value inside the callback. Thereturnappeared to work for the initial call but the re-triggered callbacks never produced the expected side effects, causing a 10s timeout waiting for a response that never came.Removing the
returnand restructuring asif added: ...fixed the issue.Expected behavior
Either:
returninside achangesbody should return from the enclosing proc (consistent with how Nim templates typically work when the body is inlined), orreturnis used inside achangesbody, since the semantics are likely not what the user expects.Notes
This may be intentional if the
changesmacro/template wraps the body in a proc or closure — in that case a compile error with a helpful message ("usebreakor restructure withifinstead ofreturn") would prevent confusing bugs.