Unary minus performs integral promotion because all the arithmetic operators on integral types do it. This convention was probably established for performance reasons (typically int was the size best suited for integral operations on the hardware) and perhaps because it's sometimes useful not to be limited to the range of smaller integral types.
I've seen bugs where people do:
uint64_t i = 1 << 33; // use 64-bit type to ensure enough bits to hold the result
But this is a bug because the result of 1 << 33
doesn't depend on what it's assigned to. (Today we have warnings about this). The solution, which is ugly, is to manually force one of the operands to be large enough: uint64_t i = static_cast<uint64_t>(1) << 33
Integral promotion happens to avoid the same sort of bug with smaller types, which would have been the common case back when C was designed this way:
short a = 30000, b = 20000
int i = a + b;
In any case "It doesn't have to be logical. It's the law."