We were discussing the finer points of some arithmetic operations in C++ and Rust today. We somewhat quickly found where C++ defines the behavior of << for example, but I could not actually find where Rust describes its behavior.
The Working Draft C++ Standard 2023-05-10 section 7.6.7 states:
"The operands shall be of integral or upscoped enumeration type and integral promotions are performed. The type of the result is that of the promoted left operand. The behavior is undefined if the right operand is negative, or greater then or equal to the width of the promoted left operand.
The value of E1 << E2 is the unique value congruent to E1 x 2^E2 modulo 2^N where N is the width of the type of the result.
(Note 1: E1 is left-shifted E2 bit positions; vacated bits are zero-filled.)
The value of E1 >> E2 is E1/2^E2, rounded down.
(Note 2: E1 is right-shifted E2 bit positions, Right-shift on signed integral types is an arithmetic right shift, which performs sign-extension.)
It may be worth noting that this description of C++ is not consistent with the information in Arithmetic operators - cppreference.com under the heading "Built-in bitwise shift operators". I'm unsure when things changed, but the current standard fits my understanding of what most compilers do.
From the cppreference website: "For negative a, the behavior of a << b is undefined". The C++ standard I quoted is clearly defined for all signed values of a.