struct S x end
Base.:(^)(s::S, p) = S(s.x ^ p)
S(1) ^ -2.0
S(1) ^ -2 # ERROR: MethodError: no method matching inv(::S)
It looks like you can not completely define ^ for a type, without defining a multiplicative inverse inv. Does anybody know what else it needs? Is there a better way to overload operators without leaving bugs like this behind?
See the ^ doc string. In short, S(1) ^ -2 isn’t calling ^, it’s calling a different function, literal_pow. This is an ugly special case implemented at an early stage of compilation. It applies only to ^, not to any other function, thankfully.
The workaround is to do, for example, S(1) ^ Int(-2) instead.
BTW, literal_pow isn’t public. If you must overload it, guard it behind an isdefined(Base, :literal_pow).
Interestingly NaNMath.jl defines functions with the same names as Base (or other respective stdlib packages e.g. Statistics.jl) except that it defines pow instead of dealing with ^ or even literal_pow.