Also, promotion is the default. Specific methods are allowed to override this.
Often, this is done for performance reasons. For example, there is a specialized method for complex + real that works as if both arguments were promoted to the same complex type, but is faster (because it only needs to add the real parts).
For even more nuance, div returns integers, but not necessarily with an Integer type e.g. 2.0 == div(2.5, 1). So after the totally separate promotion of the inputs to Rational{Int}, an output type of Rational{Int} could be reasonable for div. It just wasn’t chosen.