-
-
Notifications
You must be signed in to change notification settings - Fork 2.9k
Flag for disallowing Any #3470
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
Comments
I've fixed a few markup mistakes, hope you don't mind (I didn't catch them all). There are some other issues with the text of your description, e.g.
[EDIT] I also worry that the most draconian version is too strict to be useful:
|
Regarding typeshed, there is already custom logic in |
While it seems attractive to just suppress all errors from typeshed, I'd like to be cautious here. On the one hand, we should ideally fix strictness errors in typeshed rather than ignore them (unless there are conflicting strictness flags, which so far we have managed to avoid). But while we should never have a typeshed that causes errors with mypy's default flags, there are now so many optional strictness flavors that we usually don't know typeshed has a certain error until some user reports it. We'd lose this if we suppress errors in typeshed by default. On the other hand, when a new strictness flavor is introduced, we usually can't fix typeshed at the same time (typeshed is big!), so for users who run into this, we should have some way to silence that error in typeshed until we get to it. Maybe we need a separate flag to ignore typeshed errors that users can pass? (It's not easy to use the per-module config flags for this purpose since most of typeshed is toplevel modules, so there's nothing to put in front of the '*' pattern.) |
That's a good catch! Yes, this is an explicit
Yep, updated it with your example! I share your concern about most restrictive flags not being useful. There will always be places where Any is returned. If a variable/function of type # unchecked.py
def foo(i: int) -> Any:
if i >= 0:
return 1
else:
return 'negative' # checked.py
x: int = foo(1)
y: str = foo(-1) Code in |
That example seems designed to undermine the argument since you could also write x: int = foo(-1)
y: str = foo(1) I wonder if there shouldn't be a flag that "nerfs" |
Well, it becomes the responsibility of the caller to determine the type correctly. You could argue it either way. As for making |
It would flag all places where Any is used in an unsafe way, i.e. presuming the runtime type matches the compile-time type. It's amazing how often some corner case or a change in some other place of the code makes what was once safe no longer so. (Though in mypy the champion crash cause is probably cast() -- it also assumes the programmer knows what they are doing.) |
Hmm, actually, |
Going back to the original proposal, below is what documentation would look like. A couple of sidenotes:
Disallow Any Documentation
|
A few quick notes:
|
Do you mean the builtin types such as
Yes, I think it's a good idea. The option sounds very similar to
This sounds like a good idea. Otherwise the |
This option was implemented in the following PRs:
|
In general, we want to provide the user with a flag to disallow the use of implicit and explicit Any types as well as expressions with type Any, so that they can make sure all of their code is typechecked.
@ddfisher and I did some brainstorming yesterday and this proposal is what we came to.
Here are all the places that
Any
can appear in, followed by discussion of the current state of the flags and the proposal for a new flag.Types
Explicit
A user can explicitly specify an
Any
type in variable definition (x: Any = "hello"
), function definition(def foo() → Any: ...
), a cast(cast(Any, x)
), class definition (class C(Any)
),NewType
, aTypeVar
,NamedTuple
, or part of a type(List[Any]
).Implicit
Unimported
Unimported types happen when we try to use a type from an import from a module we don’t analyze. This could happen if we’re using
--follow-imports=skip
or--ignore-missing-imports
.Consider the following example
If you run
mypy test.py --follow-imports=skip
, the code typechecks from mypy’s point of view. BecauseC
is unresolved, it implicitly becomes an alias forAny
.Omitted Generics
This case occurs when the user does not explicitly specify a generic parameter for a type. For instance,
List
in a type position becomesList[Any]
. It is easy to forget to specify a generic parameter. This can also happen with e.g. lower-caselist
from builtins.We should consider disallowing omitting the generic parameter and maybe forbid using builtin types in favor of types from
typing
module. The proposal for it is here.Omitted Function Signature element
When a user does not specify an explicit type for a parameter or a return type, it becomes
Any
.For example, the function
def foo(x) → None: …
implicitly becomes:
def foo(x: Any) → None: …
From Error
Any
types can come from an ignored error. For instance:Expressions
An expression of type
Any
can come from anyAny
types described above.For instance,
x + y
gets typeAny
whenx
has typeAny
even ify
doesn't.In real-life code, it would be challenging to achieve no
Any
expressions in the entire module. Note that if the user is calling an untyped method from a different module, expression can have anAny
type, even if allAny
types are disallowed in the current module. Still, users may want the ability to disallow expressions of typeAny
completely in certain circumstances.Current State
Unimported types
Currently, there is a PR (#3405) that adds a flag to disallow unimported types.
Omitted Generics
There is currently a PR for a flag that would give a warning on omitted generic types. I believe we should at the very least have it on by default. Ideally, we should forbid omitted generics.
Omitted Function
Flag
--disallow-untyped-defs
is already implemented in #1285. This functionality should be merged into the new flag.From Error
Currently, there is no flag to disable it.
Expressions
Currently, there is no flag to disable it.
Flag
All of these are very similar in their nature and it would make sense to have one flag to rule them all.
It is generally worth it to provide a user with an option to disable each of the types of Anys.
There are several ways to do it.
Have a different flag for each type
Currently, in order to disable a type of Any, you have to use a separate flag for each type. At the very least we should name the flags with similar names because the options are very closely related to each other.
Have several “umbrella” flags
An option would be to have several flags that would cover different types. For instance,
--disallow-unimported-any-types
,--disallow-ommited-function-types
,--disallow-implicit-any-types
,--disallow-explicit-any-types
, and--disallow-all-any
.However, having this many flags is cumbersome, especially when they overlap. The documentation and usage would be confusing.
Have One Flag with List of Options
I think the best option is to have one flag that takes a list of arguments.
This could look something like this:
--disallow-any=...
where...
can beall
,unimported
,omitted
,error
,expr
We should also be able to combine several into one, like this:
--disallow-any=unimported,omitted
. This combination, for example, would disallow imported types and disallow omitted function types.If the flag parameters are
all
+ any other flag, we should give an error saying that it’s redundant and linking to documentation.The text was updated successfully, but these errors were encountered: