Behavioral changes can certainly be breaking changes. A Rust upgrade that doesn’t break compilation but changes the program’s behavior can be an even more serious problem than an upgrade that simply breaks compilation. This is because, depending on how comprehensive the application’s tests are, it can silently break the program. On the other hand, any behavioral change at all, including bug fixes, can break stuff.
AFAIK the only official policy on when behavioral changes are acceptable is this short section in RFC 1105:
This RFC is largely focused on API changes which may, in particular, cause
downstream code to stop compiling. But in some sense it is even more pernicious
to make a change that allows downstream code to continue compiling, but causes
its runtime behavior to break.
This RFC does not attempt to provide a comprehensive policy on behavioral
changes, which would be extremely difficult. In general, APIs are expected to
provide explicit contracts for their behavior via documentation, and behavior
that is not part of this contract is permitted to change in minor
revisions. (Remember: this RFC is about setting a minimum bar for when major
version bumps are required.)
This policy will likely require some revision over time, to become more explicit
and perhaps lay out some best practices.
In reference to this, I feel obligated to point out that rejection of leading plus was not documented. On the other hand, it is documented that leading and trailing whitespace is rejected.
I guess the main criteria is the subjective judgement whether the change in question will cause serious problems for a significant number of people, and weigh that against the benefit it brings to other people. In this case, the potential for breakage has been raised and dismissed in the PR and the associated issue. The team has taken quite some time and consideration with this decision, which is good I guess. Although I am not happy with some of the reasons for the decision (tl;dr an earlier PR of mine unintentionally forced their hand).