-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
mypy reports used-before-def
with TypeAlias
es despite from __future__ import annotations
#14539
Comments
I think mypy's behavior is correct here. The |
I think that's arguable — in an ideal world, perhaps mypy would never have allowed forward references in runtime contexts in |
In my (outsider's) opinion, @erictraut is not wrong, technically. But I'd raise the question what mypy should do here, not what it currently does. Ultimately, both my uses cases above are for type annotations only, even though one of the two cases passes via definition of a helper |
use-before-def
despite from __future__ import annotations
used-before-def
with TypeAlias
es despite from __future__ import annotations
Another point to take into account: |
Just updated mypy from 0.960 to 1.3.0 and hit this, and wow this is not correct behavior. Mypy handles unresolved references just fine; it's the Python runtime that chokes on them. If the reference is in a TYPE_CHECKING conditional, thus specifically hidden from the Python runtime and only meant for mypy, there is thus absolutely no problem with referencing something before it's defined. Mypy knows what you're doing, and Python has no idea it exists; this is manifestly not an error and flagging it as such (and requiring the annoying "wrap it in a string" forward-reference pattern) is user-hostile. And mypy knows about TYPE_CHECKING conditionals, so it can absolutely condition its checks on this. (Unresolved references outside of a TYPE_CHECKING conditional are clearly an error and mypy would be correct to flag them, as they would cause Python to choke as well.) In the meantime I'm just going to disable the |
The Mypy is behaving correctly in this case. This is not a bug. Recommend closing. |
Wow, that is news to me. I thought it would make sense to put as much as possible into type checking blocks, in line with the following linter rules that I use:
|
Yikes, those look to me like very bad linting rules. Every time you use |
There are a few reasons why you might want to move as much code as possible inside an
I agree that it leads to worse type-checking, and I also personally try to use I think we can be pragmatic and recognise that different people are making different trade-offs in the way they choose to write their code. |
This is false, weakly in theory but strongly in practice. The Python runtime has a number of behaviors that are actively hostile to type-checking, and which aren't issues in languages that have robust type systems built in - the most important one is circular imports which is impossible to resolve without it, but @AlexWaygood lists several additional important ones. Without TYPE_CHECKING blocks I'd have abandoned mypy fairly quickly, because at best it would have required drastically restructuring my code base for circular-import reasons, and likely would have simply been fundamentally incompatible. Keeping their use to a minimum is definitely correct practice (using them solely for the purpose of establishing names that the type system needs but the runtime doesn't), but they're not an escape hatch, they're a required feature of the type system due to the fundamental disconnect between Python's module system and a good type system's requirements for a module system. It wouldn't be unreasonable to, say, flag uses of a TypeAlias variable in runtime code as errors. If said variable is defined in a TYPE_CHECKING block it would actively be helpful, since that is guaranteed to be a ReferenceError at runtime. But saying that one use of a forward-referenced name in code not executed by the runtime (in an annotation) is fine, while another use in code not executed by the runtime (in TYPE_CHECKING) isn't, is just wrong. It's just a beta reduction. |
Bug Report
from __future__ import annotations
helps avoidNameError
s with later-defined entities inpython
, but seems to ineffective withuse(d)-before-def
inmypy
.To Reproduce (edited example code, see edit history for previous version if I mis-edited anything):
Expected Behavior
No error
Actual Behavior
bug.py:8: error: Name "MyClass" is used before definition [used-before-def]
Your Environment
mypy.ini
(and other config files): noneRelated: #14163, #14166
Interestingly, no error on playground on master:
https://mypy-play.net/?mypy=master&python=3.11&gist=f323516535c0d04cf4e0a2f2c985f4ff
The text was updated successfully, but these errors were encountered: