5 ms·
For it to produce the same machine code, a couple of things need to happen: 1. The move constructors need to be equivalent to a simple memcpy. This is often no
by yakubin 5y ago
For it to produce the same machine code, a couple of things need to happen:
1. The move constructors need to be equivalent to a simple memcpy. This is often not the case. E.g. std::unique_ptr, which clears the source std::unique_ptr to null.
2. The compiler needs to either inline the move constructor to notice the optimization, or it needs to do inter-procedural optimization. Either way, it's unreliable. Sometimes it will happen, sometimes it won't. Sometimes it will happen in your current compiler version, but an update will come and it's not going to happen anymore. Generally, blindly relying on the compiler to optimize that is another case Sufficiently Smart Compiler[1]. Even if it happens, it's just not reliable. Chandler Carruth held a talk at CppCon once, where he showed how std::vector::push_back is optimized by Clang to a simple assignment and size increment, when it's preceded by an appropriate call to std::vector::reserve. The only problem was that when there were more than three calls to std::vector::push_back the optimization was turned off, so now not only did you pay the price of a function call (doesn't matter all that much), but also paid the price of increasing the number of branches that the CPU goes through (not that nice), because now on each std::vector::push_back, it needed to check whether it has enough capacity for the new size. Optimizations like that are very unstable.
And I'm sure this is going to receive mixed reactions among HN readers (not Rust again!), but Rust, although still suffers from The RAII Syndrome, when it comes to its standard library, it doesn't suffer from the problem with the move constructors, because it doesn't have move constructors. It's move-by-default, as opposed to copy-by-default in C++, and the moves are provided by the compiler, they are all the same; they can't be customized on a type-by-type basis. Which means that a Vec::push in Rust doesn't have the issue I described that std::vector::push_back has. It will always compile to some variant of memcpy.
[1]: <http://wiki.c2.com/?SufficientlySmartCompiler http://wiki.c2.com/?SufficientlySmartCompiler>
- ncmncm 5y agoIt is always irresistably tempting to claim as proof of virtue the products of what is really just good luck. Rust had the good luck to come along behind C++, but not too close behind, and so get benefit of hindsight to choose nicer defaults. I have seen people (even on HN!) earnestly assert that Rust originated the notion of language recognition for object ownership and lifetime, and move semantics—and even insist C++ copied those from Rust, badly. Rust's custodians are equally as bound by their unfortunate early choices as C++'s; sufficiently-aware readers will be able to list numerous cases where early choices are already regretted. Rust benefits from much more than hindsight: it had nothing to be backward-compatible with, beyond its C ABI subset, where C++ was bound by almost all of C's early-'70s choices. (Function prototypes (along with implicit struct copy, "//" comments, void, and const) were successfully back-ported from C++ to C, freeing C++ from need to parse K&R function declarations.) To a working programmer, history is void. Rust coders can luxuriate in its lucky defaults while sneering at C++ coders saddled with clumsy evolved syntax and backward-compatibilities. In their turn, old Rust coders will, if they are lucky enough, be sneered at by users of future languages that lucked into lessons Rust has taught by unfortunate example.
- tialaramex 5y agoThe existence of people who mistakenly believe that Rust is innovating is not at all remarkable, this happens all the time for technologies, and if you're setting HN as a high bar you are certain to be disappointed. Of course one thing you certainly can learn from other people's experience is that you're going to learn from experience :) Once upon a time Rust didn't reserve keywords for async and await. Once upon a time Rust's arrays weren't IntoIterator. But when students in 2022 pick up Rust it will seem as though Rust always had async and await and its arrays always implemented IntoIterator. Only if those students dig through old code will they discover that these things were once not true. Contrast C++ where the C++ beginner soon learns that there is a built-in array but it's awful and they mustn't use it. They might reasonably wonder why C++ hasn't fixed that. There are two related things going on here. First and most obvious Rust Editions, the Editions get to change the standard prelude (a set of standard library components which are exported to your program by default without action, such as std::result::Result::Ok which can thus refer to in your program as just Ok); add new keywords (which may not yet have a definition when added); tweak the syntax of the language and even make syntax that previously gave a warning into a hard error in the new edition. Secondly, and enabling Editions to be more powerful, the Rust language syntax was chosen to reserve room to improve and expand. Implementations are not licensed to just carve off potential future syntax for their own purposes. In particular many types of Rust token can grow to accommodate future needs. Once upon a time Rust's identifiers didn't have a raw syntax, which would have made new reserved words painful - so they grew one. This is furthered by the choice to have token-oriented macro processing. Even scary proc macros (which could in principle cause absolute havoc) in practice mostly just manipulate tokens, meaning they don't blow up mysteriously as a result of new library features. A fundamental change to token parsing is invisible to a macro that only wanted tokens anyway, while tweaks to C++ grammar will upset your pre-processor macros because those don't process tokens they just mangle raw text. I have no doubt that Rust will run into unforeseen (and perhaps unforeseeable) obstacles that render it less suited for a future some day than it is today. But I believe it is much better equipped to adapt than C++ was, and as we can see C++ managed to stick around anyway for decades.
- ncmncm 5y ago