6 ms·
The limitation is the borrow checker itself. I think it restricts too much. clang implements lifetimebound, for example, which is not viral all the way down and
by germandiago 2y ago
The limitation is the borrow checker itself. I think it restricts too much. clang implements lifetimebound, for example, which is not viral all the way down and solves some typical use cases.
I find that relying on values and restricted references and when not able to do it, in smart pointers, is a good trade-off.
Namely, I find the borrow-checker too restrictive given there are alternatives, even if not zero cost in theory. After all, the 80/20 rule helps here also.
- lumost 2y agoUsing value types for complex objects will reck performance. Why not just use a GCd language at that point?
- mjburgess 2y agoGiven the amount of cloning and Arc's in typical Rust code, it just seems to be an exercise in writing illegible Go.
- binary132 2y agoIronically Go has pretty clean and straightforward guarantees about when heap allocation happens and how to avoid gc.
- CyberDildonics 2y agoThis is not true, the heavy data will be on the heap and you can move the values around. It actually works out very well.
- germandiago 2y agoYou usually pass around bigger types through the heap internally encapsulated in an object with RAII in C++, for example. I do not think this is low-perf per se.
- lumost 2y agoYes in cpp with raii, rust value types do not work this way to my knowledge.
- pornel 2y agoA borrow checker that isn't "viral all the way down" allows use-after-free bugs. Pointers don't stop being dangling just because they're stashed in a deeply nested data structure or passed down in a way that [[lifetimebound]] misses. If a pointer has a lifetime limited to a fixed scope, that limit has to follow it everywhere. The borrow checker is fine. I usually see novice Rust users create a "viral" mess for themselves by confusing Rust references with general-purpose pointers or reference types in GC languages. The worst case of that mistake is putting temporary references in structs, like `struct Person<'a>`. This feature is incredibly misunderstood. I've heard people insist it is necessary for performance, even when their code actually returned an address of a local variable (which is a bug in C and C++ too). People want to avoid copying, so they try to store data "by reference", but Rust's references don't do that! They exist to forbid storing data. Rust has other reference types (smart pointers) like Box and Arc that exist to store by reference, and can be moved to avoid copying.
- germandiago 2y ago> Pointers don't stop being dangling just because they're stashed in a deeply nested data structure or passed down in a way that [[lifetimebound]] misses This is the typical conversation where it is shown what Rust can do by shoehorning: if you want to borrow-borrow-borrow from this data structure and reference-reference-reference from this function, then you need me. Yes, yes, I know. You can also litter programs with globals if you want. Just avoid those bad practices. FWIW, references break local reasoning in lots of scenarios. But if you really, really need that borrowing, limit it to the maximum and make good use of smart pointers when needed. And you will not have this problem. It looks to me like Rust sometimes it is a language looking for problems to give you the solution. There are patterns that are just bad or not adviced in most of your code and hence, not a problem in practice. If you code by referencing everything, then Rust borrow-checker might be great. But your program will be a salad of references all around, which is bad in itself. And do not get me started in the refactorings you will need every time you change your mind about a reference deep somewhere. Bc Rust is great, yes, you can do that cool thing. But at what cost? Is it even worth? I also see all the time people showing off the Send+Sync traits. Yes, very nice, very nice. Magic abilities. And what? I do my concurrent code by sharing as little as possible all the time. So the patterns of code where things can be messed up are quite localized. Because of this, the borrow checker is basically something that gets a lot in the way but does not add a lot of value. It might have its value in hyper-restricted scenarios where you really need it, and I cannot think of a single scenario where that would be really mandatory and really useful for safety except probably async programming (for which you can do structured concurrency and async scopes still in C++ and I did it successfully myself). So no, I would say the borrow checker is a solution looking for problems because it promotes programming styles that are not clean from the get go. And only in this style it is where the borrow checker shines actually. Usually the places where the borrow checker is useful has alternative coding patterns or lifetime techniques and for the few ones where you really want something like that, probably the code spots are small and reviewable anyway. Also, remember that Rust gives you safety from interfaces when you use libraries, except when not, bc it basically hides unsafe underneath and that makes it as dangerous as any C or C++ code (in theory). However, it should be easier to spot the problems which leads more safety in practice. But still, this is not guaranteed safety. The borrow checker is a big toll in my opinion and it promotes ways of coding that are very unergonomic by default. I'd rather take something like Swift or even Hylo any day, if it ever reaches maturity.
- nostradumbasp 2y agoThat is your personal decision to make. I would say this, despite this article pointing out 4 issues with certain design patterns there is a lot of good commercial software being written in the language every single day. My personal experience has been one where after I spent the time learning Rust I am now able to write correct code much faster than GC based languages. Its pretty close to replacing python for me these days. I am also very grateful to not deal with null/nil ever again, error handling is so convenient, simple 1 offs run super fast and don't need me to go back to fix perf/re-write, and my code is way easier to read. To each their own, but I wouldn't let a niche technical articles sway you from considering Rust as something to learn, use, and enjoy.
- germandiago 2y agoMy opinion about Rust is not leaning on this article actually. I might need to give it a bigger try to see how it feels but I am pretty sure I am not going to ever like so heavy lifetime annotations for a ton of reasons. I think a subset of the borrow checking with almost no annotations and promoting other coding patterns would make me happier.
- nostradumbasp 2y agoI respect that. Honestly though, for first pass designs of code that don't need immense performance, don't reference juggle through-out the entire application. Use smart pointers when needed, clone once in a while, etc. It'll make life way easier and unless you're in a tight loop or something you'll still gain performance. Arguably you gain some safety, and convenience as well, but again "arguably" :). The first time I tried Rust I hated it. I couldn't understand why anyone would deal with what I was dealing with. The second time I tried it, I started to get it. After I got it, I struggled to want to write code with anything else. So much of the cognitive complexity is opaque and not tucked away into personal memories of tracing the code. Sometimes that's scary, sometimes its good that its scary it means its time to refactor. Best wishes.
- germandiago 2y ago
- pjmlp 2y agoAnd full of gotchas, which remain to be seen if they will ever be fixed, it has hardly been updated after the initial POC implementation.