What is guaranteed in languages in practice
In theory, what is guaranteed in a language is the things that are in its (official) specification; if the specification is silent or says that something is not guaranteed, it isn't, regardless of how implementations behave.
More and more I have come to believe that this is mistaken, and that in practice what is guaranteed in a language is what programmers code to, regardless of what the specification says. This is because of simple pragmatics: a new implementation that does not run most of the existing code is generally pretty useless to people. Thus, a new implementation that breaks from established practice does not get much traction and adoption, even if its differences are blessed by the specifications.
(Or in short, people don't care why it doesn't run their old code, they just care that it doesn't.)
You can change this state of affairs, but it takes a long time and the new implementations have to have something desirable that will get people to overcome their inertia and actually change their code instead of just sticking with the existing, working implementation. Of course you can try to give people no choice, for example by no longer selling the old implementation, but this can backfire on you in various ways.
(There are many examples of such slow changes; consider how long it took to get C programs to be 64-bit clean and large file aware, and note how it only really started happening once there was 64-bit hardware out there.)
The corollary to this pragmatic view is that if you want people to stick to what is documented, you need to get them coding to it from the start. I can think of two ways to encourage this:
- make your first implementation enforce the specification, especially the things the specification says that programmers can't count on.
- have multiple implementations from the start, ideally ones with useful
differences, so that people are pushed towards coding to the documented
(For this to work you need people to be interested in moving their code between the implementations.)
Unfortunately both are easier said than done.