I want to add a new exception or two. It is a longer story, that you
can find at the bottom :).
Lets create a namespace for custom errors! I don't want to propose new
exceptions that just get dumped in to the main namespace, so why not
make one like `errors` in pandas or `exceptions` in scikit-learn.
I would suggest introducing `np.exceptions`.
We already have custom errors and warnings:
* TooHardError (used by `np.shares_memory()`)
* ModuleDeprecationWarning (not sure what this is)
And a few private ones around ufunc "no loops" or casting failures (for
delayed printing and formatting convenience).
No need to move them all now, but maybe it is time to create a module
where we put them all? With the intention that when the stars align,
we will deprecate their main namespace aliases (either soon or in
Beyond the error I just wanted, there were things brought up before,
such as either `BroadcastError` or `ShapeMismatch`.
Adding the namespace would make them more discoverable and just remove
an annoying road-block for adding new ones.
I will argue that the cost is practically zero. I do not want custom
exceptions for too many things, but there are probably good reasons to
have more than we do have right now, and even the ones we have seem
enough for a namespace.
The long story is that following one of those many threads, I decided
that it looks worthwhile to introduce a new error class:
I would want to use this for any/most promotion related failures. That
* `np.result_type` or `np.promote_types` will give this if there is no
valid way to promote
* UFuncs will either give this error when there is no implementation
or use it to raise a reliable error for "operation not defined for
the inputs". 
This would inherit from `TypeError` "of course". The why is a ball of
yarn, that includes having a better shot at *finally* getting rid of
the annoying comparison deprecation/future warning , eventually
allowing more informative promotion errors, and that it might just be
 I first thought we should use the same error, but you can argue
that `InvalidPromotion` doesn't include "this ufunc only works for
floating point values".
And yes, "no loop" can also mean "not implemented", but that may be
need to be distinguished explicitly if really needed.
 e.g. `np.array(["asdf"]) == 0`