I tried the old not-nil pragma back in 2000 or so, and it definitely wasn’t ready for prime time. Today I thought I’d try `strictNotNil` with the current Nim 1.6.10, so I added it in one source file and sprinkled in a few `not nil` annotations. As expected there were some legit warnings, but also several that were incorrect.
I managed to reduce one of them down to a test case that’s about as trivial as you can get: {.experimental: "strictNotNil".} type Foo* = object foo: int proc doSomething* (f: ref Foo not nil) = echo "Foo = ", f.foo proc answer* (f: ref Foo) = if f.isNil: return doSomething(f) # Error: cannot prove 'f' is not nil Run This fails with the error shown above. However, using an `else` block fixes it: proc answer* (f: ref Foo) = if f.isNil: return else: doSomething(f) # now this is ok 🤯 Run This bug makes it appear that the compiler’s control-flow analysis doesn’t understand what a `return` statement does. I find that hard to believe, since there’s a lot of non-experimental stuff in Nim that depends on this kind of analysis. So what’s going wrong here? (PS: I have found other places where testing `x.isNil` helps the compiler prove safety, but `x == nil` doesn’t. What’s the difference?)