Bug Report
Some obtuse code results in a false positive for the possibly-undefined error code.
To Reproduce
Run mypy --enable-error-code possibly-undefined file.py on this file:
decorator = lambda f: f
def unreachable() -> None:
raise NotImplementedError()
def do_it(x: bool, y: None) -> None:
if x:
decorated()
var = 0
else:
match y:
case None:
var = 1
case _:
unreachable()
print(var)
@decorator
def decorated() -> None:
pass
This is as small as I've gotten the reproducer. All these parts seem to be significant:
- the outer
if and an inner match
- the
decorated call being separate to the match
- the
match being a match (replacing the match with the equivalent if y is None: ... else: ... construct works fine)
- the
match having exhaustive arms with the unreachable call being unreachable (as far as mypy can tell) (e.g. deleting the case None: entirely works fine)
- the
unreachable call existing (inlining case _: raise NotImplementedError() works fine)
decorator being a lambda (or an class with __call__ method) (using def decorator(f): return f works fine)
decorated being defined after do_it in the file (changing the order works fine) (NB. it's just decorated, decorator and unreachable can be defined before or after do_it and still reproduce the behaviour)
Expected Behavior
This to pass type checking.
In particular, have same behaviour as any of the very similar ablations mentioned above, e.g. both of these work:
- changing
decorator = lambda f: f to def decorator(f): return f
- moving
decorated to be before do_it
Actual Behavior
file.py:19: error: Name "var" may be undefined [possibly-undefined]
Found 1 error in 1 file (checked 1 source file)
Your Environment
- Mypy version used: 1.11.2
- Mypy command-line flags:
--enable-error-code possibly-undefined
- Mypy configuration options from
mypy.ini (and other config files): None
- Python version used: 3.10
Bug Report
Some obtuse code results in a false positive for the
possibly-undefinederror code.To Reproduce
Run
mypy --enable-error-code possibly-undefined file.pyon this file:This is as small as I've gotten the reproducer. All these parts seem to be significant:
ifand an innermatchdecoratedcall being separate to thematchmatchbeing amatch(replacing thematchwith the equivalentif y is None: ... else: ...construct works fine)matchhaving exhaustive arms with theunreachablecall being unreachable (as far as mypy can tell) (e.g. deleting thecase None:entirely works fine)unreachablecall existing (inliningcase _: raise NotImplementedError()works fine)decoratorbeing a lambda (or an class with__call__method) (usingdef decorator(f): return fworks fine)decoratedbeing defined afterdo_itin the file (changing the order works fine) (NB. it's justdecorated,decoratorandunreachablecan be defined before or afterdo_itand still reproduce the behaviour)Expected Behavior
This to pass type checking.
In particular, have same behaviour as any of the very similar ablations mentioned above, e.g. both of these work:
decorator = lambda f: ftodef decorator(f): return fdecoratedto be beforedo_itActual Behavior
Your Environment
--enable-error-code possibly-undefinedmypy.ini(and other config files): None