Your observation of the resulting output is correct, but not your conclusion about how it got there is not. The compiler doesn’t try to verify that the Arc is actually necessary, because there’s no point in optimizing the rare case where someone used an Arc but failed to Send it to another thread. The common case is that the author knows they won’t be sending it to another thread and so they use an Rc, or they know that they will so they use an Arc.
The C++ language standard folks had to make a different choice. For historical reasons the C++ compiler is not able to prevent the program author from misusing a non–thread–safe smart pointer by sending it to another thread, so all smart pointers are required to be thread–safe. The compiler may try to optimize away the extra locking, and it may or may not succeed in any given program. It may not be able to prove that it is safe to do so even when you as the author know that it will be.
Incidentally, every Rust program comes with a free test runner which is multithreaded; it runs multiple tests in parallel. This trips people up from time to time because the compiler will insist that certain types be thread–safe (tagged with the Send trait, in Rust) even though the author is not actually using any threads.