
On Fri, Dec 24, 2021 at 11:53:22AM +0200, Serhiy Storchaka wrote:
Some library provide function foo() which returns an instance of private type _Foo and people start using it as a type hint.
If people want to shoot themselves in the foot, is it our job to stop them? Typically the only promise we make is that the interpreter won't segfault, not to protect coders from making bad decisions in their code. If _Foo is private, you shouldn't be using it as a type hint, not even indirectly through a function prototype. *Everything* about _Foo is subject to change without notice, including its very existence. It seems a bit strange to accept the risk of unpredictable changes to a private implementation detail, while worrying about backwards- incompatible changes to a public function.
A new version converts foo() into a class. It is usually a safe backward compatible change, except that now all type hints became wrong.
It is a safe backwards compatible change only if you don't care about the type of foo. As soon as you use foo as a function prototype, then you now care about its type, just as much as if you inspected it with type() or isinstance(). In other words, it's not *actually* a backwards compatible change in a language like Python where functions are first-class objects. We can just get away with that in a context where the type of the callable usually doesn't matter, just as we usually don't care if the repr() changes. In this case, if we introduce function prototypes, then people will learn that changing a factory function to a class is a breaking change for people who do type-checking, just as changing the repr of objects is a breaking change for people who use doctests. On the other hand, changing a function to a callable instance should not be a breaking change, if we follow my earlier suggestion that objects with a `__call__` method should be usable as prototypes too. -- Steve