Overloading `^`

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).

5 Likes

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.

1 Like