Fixes#3547
This removes some type safety in exceptional cases, like code that interacts
directly with cached_property objects, but that seems like a price worth
paying.
Correctly detects calls to `register()` with a function of incompatible return
type. Correctly recognizes the `register()`, `dispatch()`, and
`_clear_cache()` methods on a generic function, as well as the `registry`
mapping.
Possible future improvements: it would be amazing if `register()` checked if
the first argument of the registered callable is indeed of valid type. This
would require Callable[] to support varargs. It would also be great if we
could read the arguments of the remaining arguments during `@singledispatch()`
and cross-check them during `register()` with the currently registered
implementation. Again, this would require Callable[] to become much more
advanced.
The documentation[1] says:
A comparison function is any callable that accept two arguments,
compares them, and returns a negative number for less-than, zero for
equality, or a positive number for greater-than.
This doesn't seem possible with the comparison function defined as
returning bool.
[1] https://docs.python.org/3.6/library/functools.html#functools.cmp_to_key