-
-
Notifications
You must be signed in to change notification settings - Fork 2.8k
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
What to do about inferring types from multiple scopes? #4492
Comments
I am in favor of option 1. I think I mentioned this some time ago, and I didn't change my mind. My argument is simple: I don't like implicit Also the number 40 seems relatively small. |
An additional argument for option 1 is that the function where the second assignment happens may be non-annotated. In this case the inferred type will be e.g. |
I think option 1 is the most reasonable. Partial types are already
something of a stretch (there are lots of situations where they don't
trigger properly) and the cross-scope behavior is just too fragile to care
much about.
While adding 40 new annotations may be a bit painful (I've had to do
similar things to that codebase for other mypy changes, and sometimes the
hard thing is figuring out what type to put in), it seems to be the most in
line with common sense.
|
Ok, let's go with option 1. |
Turns out that my figure of about 40 annotations was too optimistic -- I wasn't counting all kinds of partial types. A better figure is about 80 annotations for the S codebase. I think that the adaptation work is still reasonable and option 1 is still the best one. |
I found some further cases. It looks like the C codebase needs around 40 annotations and S around 140. The most common case in S is an attribute initialized to I'm about half way through the migration of Dropbox codebases. It has been enough work that it might make sense to make it easier. First, we could have a per-file option that ignores missing annotations (and will just infer
|
Off-line we decided on a compromise solution. IIRC it's something like add a global flag to enable or disable the current behavior, and force disabling the behavior in fine-grained mode; and when the current behavior is disabled, show an error with a suggestion for the type. E.g.
This would either be allowed (default in non-fine-grained mode) or produce an error on |
Previously if partial types were inferred from assignments in multiple scopes, like in the example below, fine-grained incremental mode could display bogus messages, since only one of the scopes could be reprocessed in one incremental update: ``` x = None def f() -> None: global x x = '' ``` This PR fixes the issue by always inferring partial types within a single fine-grained incremental target. This is always enabled in fine-grained incremental mode and can also be turned on in other modes through a new (but hidden) `--local-partial-types` option. This was complicated by various edge cases that are covered by the new test cases and/or documented in comments. If the new option is not enabled, the old behavior should (mostly) be preserved, module some fixes that may affect also the default mode. Work towards #4492.
…#4553) Previously if partial types were inferred from assignments in multiple scopes, like in the example below, fine-grained incremental mode could display bogus messages, since only one of the scopes could be reprocessed in one incremental update: ``` x = None def f() -> None: global x x = '' ``` This PR fixes the issue by always inferring partial types within a single fine-grained incremental target. This is always enabled in fine-grained incremental mode and can also be turned on in other modes through a new (but hidden) `--local-partial-types` option. This was complicated by various edge cases that are covered by the new test cases and/or documented in comments. If the new option is not enabled, the old behavior should (mostly) be preserved, module some fixes that may affect also the default mode. Work towards python#4492.
Typically mypy infers the type of the variable from the first assignment. In some cases mypy infers the type from two assignments. The first assignment creates internally a partial type, which is missing some information. The second assignment completes the type. Example:
In some cases the assignments can be in two different scopes. Example:
This feature has apparently been supported a while, but it has some issues:
None
, the inferred type will becomeNone
, which is usually not what the user wanted.None
in class body #4416).There are a few alternatives which might be reasonable, instead of the current behavior:
Any
for any missing partial type information. For example, if the initial assignment isx = []
and the only additional assignments are in nested scopes, inferList[Any]
as the type ofx
. This way the type ofx
is defined entirely by the contents of a single scope, which solves the above problems. This also introduces an additional problem -- implicitAny
types. We might want to have a strictness flag that falls back to requiring a type annotation (as in option 1 above).Currently my biggest concern is fine-grained incremental mode. There it may be possible to support the current behavior by introducing a new concept: "bound targets". I'll add a writeup about this to #4464.
@gvanrossum @msullivan @ilevkivskyi Thoughts?
The text was updated successfully, but these errors were encountered: