Comment by dathinab
6 months ago
> is unfixably slow
it's not at all unfixable, I mean sure there is a limit to speed improvements but many of the things you mention aren't really as fundamental as they seem
one one hand you don't have to go crazy with generics, `dyn` is a thing and not being generic is often just fine. Actually it's not rare to find it projects code guidelines to avoid unnecessary monopolization e.g. use `&mut dyn FnMut()` over `impl FnMut()` and similar. And sure there is some issue with people spreading some "always use generics it's faster, dynamic dispatch is evil FUD" but that's more a people then a language problem.
on the other hand rust gives very limited guarantees about how exactly a lot of stuff happens under the hood, including the rust calling convention, struct layout etc. As long as rust don't change "observed" side effects it can to whatever it wants. Dynamic/Static dispatch is in general not counted as a observed side effect so the compiler is free to not monomorphe things if it can make it work. While it already kinda somewhat doesn't monomorphize some part (e.g. T=usize,T=u64 on 64bit systems) there is a lot of untapped potential. Sure there are big limits on how far this can go. But if combined with not obsessing with generics and other improvements I think rust can have very reasonable compile times, especially in a dev->unit test loop. And many people are already fine with them now so nothing I'm overly worried about tbh.
> neatness of the generated machine code
Why would you care about that in a language where you close to never have to look at assembly of it or anything similar? It's also not really what any other languages pursue, even in modern C that is more a side effect then a intend.
Through without question kilobytes large type signatures are an issue (but the mangling isn't, IMHO if you don't use a tool to unmangle symbols on the fly that is a you problem).
It's unfixable in the sense that the problem isn't with how fast the compiler is, it's that you give it a ton of extra work. You could try to convince the library devs to use more dyn, but it'd require a culture shift. I don't think the compiler going behind the users back and second guessing whether to use static dispatch or inlining is something a low-level language should do. Java, sure.
In fact I define a systems language as something that allows the dev to describe intended machine behavior more conveniently, as opposed to a higher-level language, where the user describes desired behavior and the compiler figures out the rest.
It's not all inherent language-semantics issues like monomorphization. rustc currently generates LLVM IR in a fairly naive/brute-force-ish way. The resulting machine code is as good as you'd get with more carefully generated LLVM IR, because LLVM is very good at optimizing, but it takes longer to get there. Some of the work that LLVM currently does could instead be done in earlier compilation passes, and they could do it faster by exploiting relevant context that LLVM doesn't have. But again, this'd require significant architectural changes, which is why it hasn't already happened.
Also it could maybe make sense for debug builds to let the compiler choose whether to use static or dynamic dispatch, with an attribute to force static dispatch in those cases where it's absolutely required. (I vaguely recall some kind of attempt to do that, that got stuck because it had trouble dealing with associated constants or something like that. But I can't find it now.)