Static type annotations in CPython

Sorry, I forgot to reply here. My thoughts are mainly that we should stand by the consistent position of avoiding type hints in the stdlib. In this instance, they don’t have a runtime cost (as they’re extraneous to runtime/core pathlib), so performance is less of a factor.

From Barney’s GitHub comment:

I don’t see the point in splitting them across repositories otherwise, as it makes it too easy for things to go out-of-sync.

I agree, ideally the annotations should be in one place. From the perspective of static checkers, though, they won’t see the annotations contained within pathlib/types.py, as the whole stdlib is overriden by typeshed. As such, there’s still risk of the type annotations getting out of sync (or the annoyance of needing to make changes in two places).

A

1 Like

I discovered a comment from @srittau on a PR regarding wsgiref.types that mentions exactly this case: gh-86178: Add wsgiref.types by srittau · Pull Request #32335 · python/cpython · GitHub

[…]

  • While this is currently not the case, type checkers could in theory use the implementation module to type check instead of typeshed. In fact, I have an idea to optionally direct type checkers to the stdlib in cases like this, so it’s possible that this comment would get outdated during the life time of Python 3.11.

I’m wondering whether support in static type checkers for “partially directing to the stdlib” would remove the concern, given that pathlib.types isn’t imported at runtime.

1 Like

Semi-OT (since the topic of runtime type information is used to argue against PEP 781: Make TYPE_CHECKING a built-in constant - PEPs - Discussions on Python.org):

Is it correct to state that runtime type information will always be significantly incomplete as long as there are no static type annotations in CPython (because type stubs are not evaluated at runtime)? If so does a decision not to add static type annotations to the standard libary imply that runtime type information is not a priority?

Only if you pick a definition of “runtime type” that is different from Python’s definition (~duck typing+EAFP).[1]

At runtime, you have all the information about the runtime type, but very limited information about the author’s original intent in designing that type. But since Python doesn’t care about intent - it cares about what works - that information isn’t necessary for a runtime type.

That’s one implication. Another is that it’s unreasonably expensive to provide useful/correct static types when practically the entire stdlib is protocol based, and so the likelihood is that the information will be incorrect or limited, which makes the tradeoff for adding them not worth it (and so the implication is “don’t do it if it’s too costly”).

The places where runtime type intent matters are in things like dataclasses, where the caller is passing intent into the stdlib. Anything in the stdlib that might be passed in here can be recognised directly, and so doesn’t benefit from adding an additional layer of abstraction.


  1. And yes, static typing chose a different definition. Arguably, this makes it more useful - when the places where actual types are referenced in code match the static annotations, you get two different paths to proving correctness. ↩︎

5 Likes