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