My understanding (which might be wrong) is that you can rely on Rust not making incompatible ABI decisions between builds of the same optimization level on the same compiler version. In other words: you don't need to export a C ABI as long as you're able to enforce that every crate is built dynamically with the same compiler and flags.
That is of course still a significant restriction!
I don't know how you arrived at that. C++ has the exact opposite ABI problems: it has a far-too-stable ABI that leaks thanks to poor abstractions (header files and template expansion in first-party code). Institutional C++ users have far too many implicit ABI dependencies to ever sign off on breakages, so C++ stdlib maintainers are unable to optimize much of the `std` namespace.
This in contrast to Rust, which actually does fulfill the "off-the-shelf" promise for most use cases. It's really refreshing to be able to do `cargo build` on nearly any host and get a single binary.
Can one link two rust static libraries communicating with actual rust symbols (not just C ones), one built with gcc-rs (assuming that this is possible yet), the other built with rustc with its default x86_64-pc-windows-msvc abi ? if not, it's at the exact same state ABI-wise than C++
I'm being facetious, but it really is both: it's too unstable in ways that are bad, and also too stable in other ways that are bad.
Edit: since you updated your comment: Rust is not in the same position as C++. C++ has an unstable ABI that it cannot break; Rust has an unstable ABI that it can (and regularly does break). Rust works around this with developer tooling; C++ largely ignores the problem and requires developers to learn the secret rules through blood and tears.
how does that work for companies that may use proprietary rust libraries? the proprietary lib authors won't recompile their shit for you just because you upgraded to the latest rustc
As pointed out, the C ABI is stable. If companies absolutely feel the need to distribute Rust shared libraries and cannot guarantee the compiler being used, then it's a reasonable choice. I suspect that isn't very common, however.
More realistically, the answer is to change the interface: Rust is pretty popular in software architectures where the unit of operation is a networked or IPC'd service; vendors can distribute binaries that communicate at that layer instead.
The real answer is that Rust doesn’t really seek a solution for this problem. That’s fine, but C++ does and it pays an appropriate price for doing so. That’s just how things are.
For one, because it's easier in Rust (this goes back to the developer experience and tooling again). But we've now gone from "here's how Rust and C++'s ABI guarantees differ" to "proprietary vendors might not have the easiest time in either language," which is a significant deviation.
On a side note: I like Swift for the most part, but the last time I looked at upcoming language features they seemed like a kitchen-sink approach that's bloating the language and would better have been left to libraries. I've read this sentiment in more than one place, too.