It's important for core infrastructure to have multiple competing implementations. On a related note, does Rust have a standard yet or are they still doing the reference implementation thing?
> I was under the impression that llvm is better than gcc?
And I thought that tabs were better than spaces, BSD beat Linux, Emacs was the one true god... what were we arguing about again?
It really depends on how strictly you define the term specification. The Rust Reference is not required to be accurate. Though many other language compilers/implementations don’t fully implement their respective specs so, :shrug:.
If I have a question whose answer isn't obvious, it's far more likely that I have to go trawling around in RFCs than that there's an answer in the reference.
I think most languages of a similar age (eg Go, Swift) are doing better.
Rust dearly needs a stable specification, it is the main blocker why the language hasn't been more widely adopted.
E.g., if someone thinks "I'm going to target 2015 because I want my code to run on the rustc shipped with various slow-moving Linux distros", it doesn't help, because you might still not be able to target their code, unless they specifically target an older version of rustc, which nobody does.
There has been discussion of a Rust LTS channel alongside stable/beta/nightly, which would try to solve that problem, but it has not been prioritized yet: https://github.com/rust-lang/rfcs/pull/2483
An actual frozen language is also a possibility, but probably won't happen until more work happens on an independent specification. Which, in fact, people are also working on: https://ferrous-systems.com/blog/sealed-rust-the-pitch/
[1] https://github.com/rust-lang/rfcs/blob/master/text/0066-bett...
For many practical purposes I think the closest thing to a language definition is the set of testsuites visible to Crater.
(That is: when the compiler people are considering a change, they don't say "we can't change this because we're past 1.0 and the change is technically backwards-incompatible", or "we can't change this because the Reference specifies the current behaviour"; they say "let's do a Crater run and see if anything breaks".)
It’s a bit weird how laser-focused the Rust community is on backwards compatibility, not seeming to believe that forward compatibility is also important.
e.g., if I write code targeting C++17, I can be reasonably sure it compiles with an older version of the compiler, as long as that version also claims to support C++17, modulo bugs. Not the case if I write code targeting Rust 2015 as they’re still adding features to that from time to time. Let alone Rust 2018 which changes every 6 weeks.
Will there ever be a version of Rust that the community agrees “OK, this language definition is not changing unless we find some major soundness bug” ?
This is a big blocker for mainstream adoption in Linux distributions since the maintainer wants to be able to land one specific version of rustc in the repositories, not rely on people downloading new versions with rustup continuously. But old versions of rustc are effectively useless due to the lack of forward compatibility guarantees.
(And has a number of other disadvantages too, like constant cognitive load having to re-learn the language every 6 weeks).
Also, editions could be a snapshot of the language definition at a point in time, without being a snapshot of the compiler. There are still new versions of Clang and GCC coming out with new bugfixes, better optimizations, improved error messages, support for different hardware, WIP support for future language editions, etc., without changing the C++17 standard.
While the cadence may be faster, the pace of language change in Rust is slower than other popular languages such as C++ or JS.
https://en.cppreference.com/w/cpp/compiler_support
Right now with C++20 around the corner, C++14 is still the safest bet for portable code, whereas in Rust we still see relevant crates that depend on nightly.
* The new lifetime model (non-lexical lifetimes)
* Async fn
* Procedural macros
* ? operator
* Import name resolution changes
* impl Trait
* C-style unions
Here's the list of features added in C++17 and C++20:
* constexpr if
* Modules
* Structured binding
* Type deduction helpers
* Coroutines
* <=> operator
* Concepts
* Expanded the set of expressions and statements that qualify as constexpr to the point that it's a very different feature from what it was in C++11.
In the same amount of time, C++ has added roughly the same number of features, but I would qualitatively say that C++'s feature additions are more impactful than Rust's feature additions, especially in terms of making newer code unrecognizable to programmers used only to the old version.
That's what I meant by pace versus cadence--overall, C++ has changed more, but it tends to change in triennial bursts instead of every six weeks.
The 3 years for each ISO revision, plus around three until the standard is actually usable in a portable way.
My old dusty non-maintained MFC applications still compile on latest Visual Studio.
There are supported versions of RHEL that still only support C++11, FWIW.
I mention the reason in my prior comment: to allow people to continually upgrade their compiler version without needing to change any code. Rust doesn't have a stable ABI, so all crates in a Rust project ultimately need to be built with the same compiler (and furthermore, crates must always be able to interoperate regardless of which edition they're on). That means that every new version of the compiler needs to support every old edition, because the alternative is to have users stuck on old versions of not just the compiler but also on old versions of dependencies that have since begun using features only supported by newer compilers. In Rust's case avoiding such a fundamental fracture in the community was more important, since, after all, there's still nothing stopping anyone from voluntarily sticking with an older version of the compiler if they're willing to deliberately endure such a situation.
> (And has a number of other disadvantages too, like constant cognitive load having to re-learn the language every 6 weeks).
This is quite hyperbolic. Rust introduces no more features than any other language, it simply rolls them out on a more fine-grained schedule. Furthermore, Rust hardly requires re-learning every six weeks; a "feature" introduced by a new version is often nothing more than a new convenience method in the standard library. The fact that we have established that Rust goes out of its way even to keep "old" code compiling and compatible with the rest of the ecosystem should demonstrate how little it demands that users re-learn anything.
g++ 4.4 implemented several key parts of C++11, including notably rvalue references, and adapted libstdc++ to use rvalue references in C++11 mode. However, the committee had to make major revisions to rvalue references subsequent to this implementation, to the point that you can't use libstdc++ 4.4's header files (such as <vector>) with a compliant C++11 compiler. So when you try to use newer clang (which prefers to use system libstdc++ for ABI reasons) on systems with 4.4 installed (because conservative IT departments), the result is lots and lots of pain.
Furthermore, it absolutely is the case that newer versions of compilers will interpret old language standards differently than older versions of the compiler. You don't notice it for the most part because the changes tend to revolve around pretty obscure language wordings involving combinations of features that most people won't hit. Compilers are going to try hard not to care about language versions past the frontend of the compiler--if the specification change lies entirely in the middle or backend, then that change is likely to be retroactively applied to past versions because otherwise the plumbing necessary is too difficult.
I'd be curious to know whether this would provide cross-language outlining during LTO using gcc. I believe some form of this is possible with llvm?
Now, in terms of end results, llvm and gcc each have their qualities. When llvm was released, gcc typically produced faster binaries but llvm optimizations were easier to understand. Since then, both have evolved and I haven't tried to catch up.
Bottom line: having two back-ends for rust or any other language is good. Among other things, it's a good way to check for bugs within an implementation of the compiler, it can be used to increase the chances of finding subtle bugs in safety-critical code, etc.
https://robert.ocallahan.org/2018/11/comparing-quality-of-de...
Could you site sources please?
https://joelaro.wordpress.com/2015/09/30/gcc-optimization-fd...
The most recent restrict bug the rustc developers found (which made they disable restrict again) was found in both LLVM and GCC (they made a C reproducer, so they could test in both). See: https://github.com/rust-lang/rust/issues/54878 (rustc) https://bugs.llvm.org/show_bug.cgi?id=39282 (LLVM) https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87609 (GCC).
https://reviews.llvm.org/D9375
I even filed a version of it myself:
https://bugs.llvm.org/show_bug.cgi?id=27955
I'm actually surprised that Rust enabled noalias usage with this known outstanding issue. When I worked on Rust years ago, it was definitely common knowledge on the compiler "team" that this was broken.
I'm equally surprised that GCC had that bug, since their pointer aliasing model is equipped to correctly handle this situation (and is why they were able to fix it quickly).
> The C standard uses the term byte to mean the minimum addressable unit in the implementation, which is char, which means a byte on these targets is 16 bits. This is in conflict with the widespread use of byte to mean 8 bits exactly. This is an unfortunate disagreement between C terminology and widespread industry terminology that TI can't do anything about.
In the past, architectures differed wildly in number of bits per byte, e.g 36 for the machine where the Pascal language was created.
Today, the industry mostly standardized on 8 bits per byte, but see e.g the PIC architecture for an example relevant today with a different choice: 8 bit bytes for data, but 10 bit bytes for instructions.
I think that's an anachronistic/incorrect usage. A lot of machines (including several with 36-bit words that you mentioned) supported larger basic addressable units of memory, but didn't call these larger units "bytes", and distinguished between "bytes" and "words". In fact, one of the elements of the early RISC philosophy was that CPU support for byte accesses (as opposed to word accesses) was extraneous, based on statistics gathered from real programs. Early MIPS/Alpha/etc. machines did not support byte addressing, but the people using them still called 8 bits a byte.
> https://en.wikipedia.org/wiki/GNU_Compiler_Collection#Archit...
And the number of architectures by LLVM:
> https://en.wikipedia.org/wiki/LLVM#Back_ends
GCC supports vastly more targets.
That is my experience too.
GCC for code with high level of nesting, meaning high potential for inlining (typically C++), is close to unbeatable. Including even compared Highly optimised compilers like Intel ICC.
LLVM's IR is not stable by design. [1, 2]
[1] http://lists.llvm.org/pipermail/llvm-dev/2016-February/09487... [2] http://llvm.org/docs/DeveloperPolicy.html#ir-backwards-compa...
> while GCC refuses to do so over the decades for political and strategic reasons.
That was a long time ago. Since GCC 4.5 (released in 2010) GCC supports external plugins. [3,4] These plugins, like the rest of GCC, use GENERIC and GIMPLE as their IR.
[3] https://gcc.gnu.org/gcc-4.5/changes.html [4] https://gcc.gnu.org/onlinedocs/gccint/Plugins.html