However, comparing compilation speed across languages and compiler implementations is a bit difficult.
They might have some more comprehensive optimization passes eating extensive cycles, but even rustc debug builds are extremely slow in comparison to the Go standard compiler.
(One of my benchmarks for "Go has really made it" is when someone starts selling an optimized Go compiler that does the expensive optimizations. You could still ideally use the standard Go compiler to develop, but then you'd test and deploy with the slow optimized compiler.)
As the OP pointed out, Rust debug builds are still much slower than Go builds, so lack of optimizations can't be a big part of the story. The simplicity of the language and the deliberate design of the compiler for speed seem to be the main factors.
I'm not claiming this is true by any means, but it wouldn't surprise me that much that merely the work to tell if a bit of Rust code in, say, Servo, is legal Rust in the presence of a rich type system and the borrow checker and all the other such things going on is more work than it would be to compile the roughly-equivalent Go module entirely. Compared to Rust, Go does not so much "cut corners" as cut entire dimensions out of the picture, and then cut some more corners for good measure.
Were I going to start the company to produce the compiler, the question of "why isn't gccgo about 2x faster than Go?" is one of the first I'd examine, though. I personally have zero idea what the answer is. Or, indeed, if it's even still true. However, I am active enough in the Go community that if good benchmarks were going around I'd expect to have seen them. (They'd probably make it to HN.)
I am frankly too lazy to set up gccgo for comparisons again, but if I recall correctly, it takes considerably longer to compile whilst providing similar quality output. Thus, I would ask the opposite question that you presented:
If gccgo isn't notably faster than gc, why is compilation so much slower?
If one compiler spends more time generating identical quality output with an identical input language, it is hard to argue against the fact that there are wasted cycles at play. It may of course partly be due to an immature Go frontend. Who knows.
However, then we can draw on two facts to kill that this should be a significant part of the issue: The post states that for most projects, the majority of the compile time is spent in LLVM, not Rust. Second (my memory may fail me here, but this is easy to measure), for larger projects, Go also smoke clang/gcc, which do not have Rusts fancy features.
But, as I stated in my parent comment, these cross-language, cross-compiler comparisons are quite difficult to make. This is also why I attack comments talking about one compiler doing more "work" than another. It cannot be directly compared.
All we know for certain, is that rustc is far too slow for our liking.
Work is not just the optimization.
Having Rust track lifetimes and warn about ownership bugs, races, etc, is also productive work for the compiler -- and happens during the debug builds too.
I stated in my parent comment that cross-language/cross-compiler comparisons is tricky exactly because of the vast differences in both frontends (lifetime tracking, warning generation) and backends (code generation, optimization). So yes, I know there are different amounts of work related with different languages.
However, I believe the compile time differences significantly outweigh the compile time differences.
A, true, by the time it hits LLVM Rust's lifetime's analysis has already happened...
> However, I believe the compile time differences significantly outweigh the compile time differences.
I meant to say "the compile time differences are significantly greater than the language-independent differences".
(This is true for performance and optimisation is general: fast enough is good enough.)
Once it takes seconds, we can talk about "fast enough".
Is that minutes for every compile, or for an (infrequent) full compile?
"Clang" is a thing not a person, therefore it's appropriate to use et cetera, not et alii. The former is for things, the latter for people (usually limited to authors of academic papers).
Anyway, you could argue that the use of "et al." in English has a restriction that doesn't come from the original Latin. Many of the Google results I found do claim that there's a convention of using "etc." for things and "et al." for people, although that seems to conflict with the idea that "et al." primarily stands for "et alia". But they mostly don't claim that that convention is a hard rule. And I don't think it makes much sense to establish one, considering the original meaning.
[edit: reworded for clarity]
With Go, on my laptop, 30 seconds is the time it takes to perform a complete, optimized build of a medium-sized application, all dependencies and the standard library from source.
It's always so... frustrating whenever I go from a Go project back to our large C/C++ mixed codebase...
https://dave.cheney.net/2016/11/19/go-1-8-toolchain-improvem...
This is a genuine case of survivorship bias in action.
I guarantee you that there are people not using Clang or writing, let's say, C++ because of slow compile times. You just never hear about how much they hate using them, because those people no longer are using them.
Well, the Go standard compiler doesn't do much.
Practically every VM that tried to use LLVM as a JIT gave up as it was too slow. WebKit eventually abandoned their LLVM backend and wrote their own, B3.
JITs are of course a specialized use case, but there are also known issues with compilation speed in LLVM. For example, LLVM is single-threaded, so compiling a single very large compilation module can be much slower than it needs to be - and this is an issue hit by Rust due to how crates are designed. But you are also very correct that Rust is generating overly-complex LLVM IR for LLVM to compile, which is another problem there.
Also worth noting that while once clang beat gcc in compilation speed, as clang's optimizations have caught up to gcc the difference has vanished, and on many benchmarks today gcc compiles more quickly.
And it doesn't even seem to work effectively as a target for JIT. It can do the machine code emitting part of a JIT well, but that wasn't really the problem and it doesn't seem to work well at the real problem of optimising code for a high-level language. You need to optimise yourself, by writing basically your own compiler pipeline, before emitting LLVM.
See for example the Rubinius implementation of Ruby.
I've edited my original comment to include the clarification.
[0] http://polly.llvm.org/docs/Performance.html#compile-time-imp...
That said, it's generally not seen as part of the main stack, which would be LLVM, Clang, compiler-rt, and maybe lld, libc++, and libc++abi. (The latter three being fully optional replacements where most people use the standard system components instead).