Skip to content

Commit 04e0667

Browse files
mrkmndzfacebook-github-bot
authored andcommitted
Documenting Invalid type variable (#297)
Summary: This behavior is confusing and slightly non-standard (python/typeshed#4045), thus it ought to be explained in detail on this page. Pull Request resolved: #297 Reviewed By: shannonzhu Differential Revision: D22964776 Pulled By: mrkmndz fbshipit-source-id: ae3b168049d84cb721762ce6ac6d2c8a0c05e187
1 parent 68ab1eb commit 04e0667

File tree

1 file changed

+29
-0
lines changed

1 file changed

+29
-0
lines changed

docs/errors.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,35 @@ This is usually caused by failing to import the proper module.
170170
Pyre will raise error 21 instead ("Undefined import") when the import statement is present, but the module to be imported could not be found in the search path.
171171
If the module provides stub files, please provide their location via the `--search-path` commandline parameter.
172172

173+
### 34: Invalid type variable
174+
175+
Type variables can only be used as types when they have already been placed "in scope".
176+
A type variable can be placed into scope via:
177+
178+
* Generic class declarations
179+
* for example, `class C(Generic[T]):` puts `T` into scope for the body of the class
180+
* The **parameter** types of a generic function
181+
* for example, `def foo(x: T)` puts `T` into scope for the body and return type annotation of the function
182+
183+
Something notably absent from this list is "inside of a `typing.Callable` type".
184+
This means that `Callable[[T], T]` does not spell the type of a generic function, but rather a specific identity function, with the `T` defined by an outer scope.
185+
Therefore, if you want to spell the signature of a function that takes/returns a generic function, you will need to declare it separately via a callback protocol:
186+
187+
```python
188+
T = TypeVar("T")
189+
190+
def returns_identity() -> Callable[[T], T]: ... # Rejected
191+
192+
class IdentityFunction(Protocol):
193+
def __call__(self, x: T) -> T: ...
194+
195+
def returns_identity() -> IdentityFunction: # Accepted
196+
def inner(x: T) -> T:
197+
return x
198+
return inner
199+
```
200+
201+
173202
### 35: Invalid type variance
174203
In brief, read-only data types can be covariant, write-only data types can be contravariant, and data types that support both reads and writes must be invariant.
175204
If a data type implements any functions accepting parameters of that type, we cannot guarantee that writes are not happening. If a data type implements any functions returning values of that type, we cannot guarantee that reads are not happening.

0 commit comments

Comments
 (0)