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?)

Reply via email to