-
Notifications
You must be signed in to change notification settings - Fork 23
Description
Refs: status-im/nim-chronos#226
The problem: Currently code like this does not compile:
{.experimental: "strictEffects".}
proc outer =
proc inner() {.tags: [].} =
outer()
inner()
outer()
The compiler produces:
Error: outer() can have an unlisted effect: RootEffect
When inner is analysed for its effects the effects of outer are
not yet known. The specification/manual currently does not really say
what should happen: outer is not forward declared as it doesn't have
to be, but the intention of the spec clearly was to cover this case via
the rule (3):
- Every call to a proc
qwhich has an unknown body (due to a forward
declaration) is assumed to
raisesystem.Exceptionunlessqhas an explicitraiseslist.
So, in order to make the example compile, outer's effects need to be annotated
explicitly:
{.experimental: "strictEffects".}
proc outer {.tags: [].} =
proc inner() {.tags: [].} =
outer()
inner()
outer()
While that might not be that bad, the problem here is that code like in the
initial example used to work for years and only the recent bugfixes in the
.experimental: "strictEffects" mode make it not compile. It's a breaking
change which could be handled more smoothly if we make the compiler smarter.
Proposal: Infer the effects of inner routines in combination with outer routines
The effect inference algorithm could work on outer and inner in lock-step:
When inner calls outer it is assumed that outer has no effects and if that
assumption does not turn out to be true, calls of outer need to be "patched".
Or, to phrase it differently: The interference algorithm infers the effects of outer
by also following inner routines directly, treating them much like templates.
Benefits
- Less code breakage for code that uses
.experimental: "strictEffects"(and this mode
is about to become the default as it fixes a number of loopholes in Nim's effect
system.) - Code ends up with fewer conservative annotations which can matter for generic code.
Downsides
- A slightly more complex compiler and language definition.