-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Clarify generic function documentation #4618
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
Conversation
This explains that a variable of a generic type must be able to be resolved to a non-generic type, hopefully preventing the confusion that made me (and possibly others) think python#4590 is a bug.
docs/source/generics.rst
Outdated
|
||
T = TypeVar('T') # Declare type variable | ||
|
||
def first(seq: Sequence[T]) -> T: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no need to repeat the two "good" examples -- this example should be only concerned with what doesn't work.
docs/source/generics.rst
Outdated
@@ -223,6 +223,26 @@ example we use the same type variable in two generic functions: | |||
def last(seq: Sequence[T]) -> T: | |||
return seq[-1] | |||
|
|||
Note that a variable cannot have a type variable in its type unless the type variable is bound in a containing generic class or function: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please break the long line. Also, maybe drop the leading "Note that" -- the previous section also starts like that and it's a bit repetitive.
docs/source/generics.rst
Outdated
@@ -223,20 +223,15 @@ example we use the same type variable in two generic functions: | |||
def last(seq: Sequence[T]) -> T: | |||
return seq[-1] | |||
|
|||
Note that a variable cannot have a type variable in its type unless the type variable is bound in a containing generic class or function: | |||
A variable cannot have a type variable in its type unless the type | |||
variable is bound in a containing generic class or function: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm, sadly I just realized this is not quite correct, since this is possible:
T = TypeVar('T')
S = TypeVar('S')
def repeat(n: int) -> Callable[[Callable[[T], T]], Callable[[T], T]]:
def outer(func: Callable[[S], S]) -> Callable[[S], S]:
def inner(x: S) -> S:
for i in range(n):
x = func(x)
return x
return inner
return outer
fff = repeat(3)
reveal_type(fff) # 'def [T] (def (T`-1) -> T`-1) -> def (T`-1) -> T`-1'
But I don't want to include such an example here -- I just wish to find a way to write it that doesn't exclude it.
Also this much simpler example should be invalid but isn't:
def foo() -> T:
pass
a = foo()
So I'm not sure what to do. Maybe @ilevkivskyi has an idea?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
def foo() -> T: pass
seems to be an unidiomatic way of writing
def foo() -> Any: pass
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They don't mean the same thing in mypy. The former returns a type containing <nothing>
(meaning it has no values).
@gvanrossum it seems like you don't need your strange nested example to contradict the wording in your explanation. I ran I kind of have an idea of where and how type variables can and can't be used, based on the existing documentation and my own tinkering. But I can't imagine how to explain it precisely and rigorously, in a way that most mypy users will be able to understand. I think someone will have to help me with this. |
Yeah, I went overboard with the complicated example. You'll note that all the examples where a type variable legitimately appears are types that are (or contain) generic functions. So maybe we should use that? |
I propose to drop the example and just keep the sentence explaining the constraint. I'll just edit this myself so we can finish this up. |
The actual errors are sufficiently different from what's shown that it's better not to show the example, IMO.
And, belatedly, thanks! |
This explains that a variable of a generic type must be able to be resolved to a non-generic type, hopefully preventing the confusion that made me (and possibly others) think #4590 is a bug.
@gvanrossum, I used some of the wording in your explanation almost verbatim. I'm guessing you don't mind.