KotlinIsland / basedmypy

Based Python static type checker with baseline, sane default settings and based typing features
https://kotlinisland.github.io/basedmypy/
Other
144 stars 4 forks source link

only narrow locally defined variables #345

Open DetachHead opened 2 years ago

DetachHead commented 2 years ago
foo: int | None = None

def bar():
    global foo
    foo = None
    baz()
    if foo is None: # error: condition is always True
        ...

def baz():
    global foo
    foo = 1
KotlinIsland commented 2 years ago

I think this should be an option and off by default, it's too disruptive to the expected usage of mypy.

Zeckie commented 2 years ago

I think this should be an option and off by default, it's too disruptive to the expected usage of mypy.

Why do you say this is too disruptive (given basedmypy is already quite disruptive)? Is it due to the effect it will have on code that is not in a function?

Should variables accessed using nonlocal also not be narrowed?

KotlinIsland commented 2 years ago

It's designed like this intentionally for good reason, and there isn't anything to support the alternative like other languages:

var a: Int? = 0
fun main() {
    a ?: return
    a + 1 // error: a could be null
    a!! + 1 // no error
}

If this was to be default then I would expect there to be some systems available to support it, perhaps mutation tracking.

DetachHead commented 2 years ago

i usually work around it by defining a new local variable (which is the recommended solution in dart), which seems safer than using a non-null assertion

var a: Int? = 0
fun main() {
    val b = a
    b ?: return
    a + 1 // error: a could be null
    b + 1 // no error
}