"auto" return type
Per Guido Van Rossum's suggestion, I am re-posting what was initially opened as an issue at python/typing (https://github.com/python/typing/issues/727). I am unsure if this issue should go here or rather to mypy's tracker. I have looked through issues in both `typing` and `mypy` and couldn't find anything related. Consider the following code: ```py import typing as tp class A: x: int def f1() -> A: return A() def f2() -> tp.Any: return f1() x = f1() x.x = "" # [1] y = f2() y.x = "" # [2] ``` Upon checking with mypy, an expected `Incompatible types in assignment (expression has type "str", variable has type "int")` error is emited at [1], but not at [2]. This makes sense, as type of `y` is `Any`. However, e.g. [jedi](https://jedi.readthedocs.io/en/latest/) autocompletion library is smart enough to deduce that `f2() -> A`. While in the above degenerate example it would be trivial to just property annotate the `f2`, the real scenario has `A` and `f1` defined in some library, and `f2`, which does something more useful than just calling `f1` is defined in user-code. Specific class `A` is not intended to be directly instantiated by the user, moreover, it may be buried deeply inside module hierarchy, which may also change between library releases. My suggestion is to introduce `typing.Auto` which, when used in return type annotation, would instruct type checker (mypy or any other) to infer return type from the type of expression in return statement. In case of multiple return statements, the pragmatical approach would probably be to infer the base-most class, possibly issuing an error or a warning if types are completely unrelated. Another possibility is to optionally have mypy treat `typing.Any` return types in a manner suggested for the above-described `typing.Auto` but I suspect that this would be a breaking change. P.S. `typing.Auto` should also be usable within `typing.Tuple`. I am not sure whether it would be desirable to allow inference of tuple in cases when return type is annotated as `typing.Auto`.
I believe that relying on a type checker-specific type inferencing behavior, intentionally left undefined by PEP 484, is what one normally indicate buy not specifying any concrete type, so just leaving "f2" not annotated in this case. If a type checker is able to deduce which type "f2" returns, it will. Having to use some special type for that will only unnecessarily clutter the code of all the small internal functions that otherwise don't need to be explicitly type hinted.
On Wed, May 27, 2020 at 7:22 AM Mikhail Golubev via Typing-sig < typing-sig@python.org> wrote:
I believe that relying on a type checker-specific type inferencing behavior, intentionally left undefined by PEP 484, is what one normally indicate buy not specifying any concrete type, so just leaving "f2" not annotated in this case. If a type checker is able to deduce which type "f2" returns, it will. Having to use some special type for that will only unnecessarily clutter the code of all the small internal functions that otherwise don't need to be explicitly type hinted.
+1 agreed, there is no need for Auto. For example: pytype infers without that, it was designed to always infer. The presence of an annotation is *generally* considered a sign that the user wants something different than inference currently comes up with, so it tends to be blindly trusted. Obviously when you've got inference ability you could run that in a mode that highlights inference vs annotation incompatibilities or suggests alternatives to Any (as Any is by definition compatible with everything) - but that would be a type checker specific feature with no guaranteed correct behavior. (inferred things tend to be a lot messier looking and logically pedantic than a manual *intended* annotation) Any is the weird case. It may be slapped on code to appease a code base or tooling that isn't yet ready to understand the ideal type. I generally advise against ever using it as a naked lone return type as it tends to destroy type information flowing through a code base when applied that way. There's a good chance an Any return type should be accompanied by bugs being filed as to why that was necessary at the moment. -gps
I've spent a considerable amount of time manually deducing a return type from various libraries (usually I have Mypy set to not allow missing annotations).
I agree with Gregory here. Inferring function return types and inserting
the corresponding type hints where they are absent can be a feature of a
particular type checker, no need to add a special name for that.
One of the roles of type hinting in general is documentational. By
specifying the return type of a function explicitly you spare a future
reader from having to analyze the implementation and figuring it out
themselves. Specifying that a function returns Any, perhaps questionable
from API design point of view, is otherwise still useful. Such annotation
indicates that a caller should be ready for, well, any value. Specifying
Auto, on the other hand, doesn't tell anything. It's just a plug to please
the type checker, forcing a human being reading the code to deduce the type
manually all other again.
On Wed, May 27, 2020 at 8:11 PM Gregory P. Smith
On Wed, May 27, 2020 at 7:22 AM Mikhail Golubev via Typing-sig < typing-sig@python.org> wrote:
I believe that relying on a type checker-specific type inferencing behavior, intentionally left undefined by PEP 484, is what one normally indicate buy not specifying any concrete type, so just leaving "f2" not annotated in this case. If a type checker is able to deduce which type "f2" returns, it will. Having to use some special type for that will only unnecessarily clutter the code of all the small internal functions that otherwise don't need to be explicitly type hinted.
+1 agreed, there is no need for Auto. For example: pytype infers without that, it was designed to always infer.
The presence of an annotation is *generally* considered a sign that the user wants something different than inference currently comes up with, so it tends to be blindly trusted.
Obviously when you've got inference ability you could run that in a mode that highlights inference vs annotation incompatibilities or suggests alternatives to Any (as Any is by definition compatible with everything) - but that would be a type checker specific feature with no guaranteed correct behavior. (inferred things tend to be a lot messier looking and logically pedantic than a manual *intended* annotation)
Any is the weird case. It may be slapped on code to appease a code base or tooling that isn't yet ready to understand the ideal type. I generally advise against ever using it as a naked lone return type as it tends to destroy type information flowing through a code base when applied that way. There's a good chance an Any return type should be accompanied by bugs being filed as to why that was necessary at the moment.
-gps
-- Mikhail Golubev Software Developer JetBrains http://www.jetbrains.com The drive to develop
On 2020-05-26, at 13:32, kshpitsa@gmail.com wrote:
My suggestion is to introduce `typing.Auto` which, when used in return type annotation, would instruct type checker (mypy or any other) to infer return type from the type of expression in return statement. In case of multiple return statements, the pragmatical approach would probably be to infer the base-most class, possibly issuing an error or a warning if types are completely unrelated.
I like this idea. I've spent a considerable amount of time manually deducing a return type from various libraries (usually I have Mypy set to not allow missing annotations). Andrew
On 27 May 2020, at 17:49, Andrew Udvare
wrote: On 2020-05-26, at 13:32, kshpitsa@gmail.com wrote:
My suggestion is to introduce `typing.Auto` which, when used in return type annotation, would instruct type checker (mypy or any other) to infer return type from the type of expression in return statement. In case of multiple return statements, the pragmatical approach would probably be to infer the base-most class, possibly issuing an error or a warning if types are completely unrelated.
I like this idea. I've spent a considerable amount of time manually deducing a return type from various libraries (usually I have Mypy set to not allow missing annotations).
Andrew
(resending, as orignally I replied to just Andrew I think) Ironically, I take your story (which is also my story) and the time spent on decucing return types as an argument *against* return type inference. Specifying types (parameters and returns) at function boundaries (internal and public-facing) is IMO a nice compromise between verbosity of specifying types everywhere and total inference everywhere possible, in my experience it helps a lot when reading the code or otherwise working on it. Jakub
On Wed, May 27, 2020 at 8:49 AM Andrew Udvare
I like this idea. I've spent a considerable amount of time manually deducing a return type from various libraries (usually I have Mypy set to not allow missing annotations).
While I do not like the typing.Auto idea either, I think this is a genuine use case that is currently hard to support - opting a function out of "don't allow missing annotations" while still keeping it turned on for the rest of the code. It feels like it should be a directive rather than a type, though, analogous to `# type: ignore`. Perhaps `# type: auto`? We would still need the `# type` comment for ignore directives after all, even if it is not now needed to annotate actual types. martin
participants (6)
-
Andrew Udvare
-
Gregory P. Smith
-
Jakub Stasiak
-
kshpitsa@gmail.com
-
Martin DeMello
-
Mikhail Golubev