6 ms·
Well, 1) the temporary allocator strategy; and 2) `defer` kinda go against the spirit of this observation. With (1) you get the benefits of GC with, in many ca
by mjburgess 2y ago
Well, 1) the temporary allocator strategy; and 2) `defer` kinda go against the spirit of this observation.
With (1) you get the benefits of GC with, in many cases, a single line of code. This handles a lot of use cases. Of those it doesn't, `defer` is that "other single line".
I think the issue being raised is the "convenience payoff for the syntax/semantics burden". The payoff for temp-alloc and defer is enormous: you make the memory management explicit so you can easily see-and-reason-about the code; and it's a trivial amount of code.
There feels something deeply wrong with RAII-style langauges.. you're having the burden to reason about implicit behaviour, all the while this behaviour saves you nothing. It's the worst of both worlds: hiddenness and burdensomeness.
- hmry 2y agoNeither of those gives memory safety, which is what the parent comment is about. If you release the temporary allocator while a pointer to some data is live, you get use after free. If you defer freeing a resource, and a pointer to the resource lives on after the scope exit, you get use after free.
- francasso 2y agoWhile technically true, it still simplifies memory management a lot. The tradeoff in fact is good enough that I would pick that over a borrowchecker.
- junon 2y agoI don't understand this take at all. The borrow checker is automatic and works across all variables. Defer et al requires you remember to use it, and use it correctly. It takes more effort to use defer correctly whereas Rust's borrow checker works for you without needing to do much extra at all! What am I missing?
- vouwfietsman 2y ago> The borrow checker is automatic and works across all variables. Not that I'm such a Rust hater, but this is also a simplification of the reality. The term "fighting the borrow checker" is these days a pretty normal saying, and it implies that the borrow checker may be automatic, but 90% of its work is telling you: no, try again. That is hardly "without needing to do much extra at all". That's what you're missing.
- junon 2y agoMaybe I'm spoiled because I work with Rust primarily these days but "fighting the borrow checker" isn't really common once you get it.
- vouwfietsman 2y agoA lot has been written about this already, but again I think you're simplifying here by saying "once you get it". There's a bunch of options here for what's happening: 1. The borrow checker is indeed a free lunch 2. Your domain lends itself well to Rust, other domains don't 3. Your code is more complicated than it would be in other languages to please the borrow checker, but you are unaware because its just the natural process of writing code in Rust. There's probably more things that could be going on, but I think this is clear. I certainly doubt its #1, given the high volume of very intelligent people that have negative experiences with the borrow checker.
- steveklabnik 2y ago"But after an initial learning hump, I don't fight the borrow checker anymore" is quite common and widely understood. Just like any programming paradigm, it takes time to get used to, and that time varies between people. And just like any programming paradigm, some people end up not liking it. That doesn't mean it's a "free lunch."
- vouwfietsman 2y agoI'm not sure what you mean here, since in different replies to this same thread you've already encountered someone who is, by virtue of Rusts borrow checker design, forced to change his code in a way that is, to that person, net negative. Again this person has no trouble understanding the BC, it has trouble with the outcome of satisfying the BC. Also this person is writing Vulkan code, so intelligence is not a problem. > is quite common and widely understood This is an opinion expressed in a bubble, which does not in any-way disprove that the reverse is also expressed in another bubble.
- francasso 2y agoIf your use case can be split into phases you can just allocate memory from an arena, copy out whatever needs to survive the phase at the end and free all the memory at once. That takes care of 90%+ of all allocations I ever need to do in my work. For the rest you need more granular manual memory management, and defer is just a convenience in that case compared to C. I can have graphs with pointers all over the place during the phase, I don't have to explain anything to a borrow checker, and it's safe as long as you are careful at the phase boundaries. Note that I almost never have things that need to survive a phase boundary, so in practice the borrow checker is just a nuissance in my work. There other use cases where this doesn't apply, so I'm not "anti borrow checker", but it's a tool, and I don't need it most of the time.
- Rusky 2y agoYou can explain this sort of pattern to the borrow checker quite trivially: slap a single `'arena` lifetime on all the references that point to something in that arena. This pattern is used all over the place, including rustc itself. (To be clear I agree that this is an easy pattern to write correctly without a borrow checker as well. It's just not a good example of something that's any harder to do in Rust, either.)
- francasso 2y agoI remember having multiple issues doing this in rust, but can't recall the details. Are you sure I would just be able to have whatever refs I want and use them without the borrow checker complaining about things that are actually perfectly safe? I don't remember that being the case. Edit: reading wavemode comment above "Namely, in Rust it is undefined behavior for multiple mutable references to the same data to exist, ever. And it is also not enough for your program to not create multiple mut - the compiler also has to be able to prove that it can't." that I think was at least one of the problems I had.
- steveklabnik 2y agoThe main issue with using arenas in Rust right now is that the standard library collections use the still-unstable allocator API, so you cannot use those with them. However, this is a systems language, so you can use whatever you want for your own data structures. > reading wavemode comment above This is true for `&mut T` but that isn't directly related to arenas. Furthermore, you can have multiple mutable aliased references, but you need to not use `&mut T` while doing so: you can take advantage of some form of internal mutability and use `&T`, for example. What is needed depends on the circumstances.
- wavemode 2y agoWhat you're missing is that Rust's borrowing rules are not the definition of memory safety. They are just one particular approach that works, but with tradeoffs. Namely, in Rust it is undefined behavior for multiple mutable references to the same data to exist, ever. And it is also not enough for your program to not create multiple mut - the compiler also has to be able to prove that it can't. That rule prevents memory corruption, but it outlaws many programs that break the rule yet actually are otherwise memory safe, and it also outlaws programs that follow the rule but wherein the compiler isn't smart enough to prove that the rule is being followed. That annoyance is the main thing people are talking about when they say they are "fighting the borrow checker" (when comparing Rust with languages like Odin/Zig/Jai).
- junon 2y agoRust doesn't outlaw them. It just forces you to document where safety workarounds are used.
- Rusky 2y agoThat is true of `&mut T`, but `&mut T` is not the only way to do mutation in Rust. The set of possible safe patterns gets much wider when you include `&Cell<T>`. For example see this language that uses its equivalent of `&Cell<T>` as the primary mutable reference type, and uses its equivalent of `&mut T` more sparingly: https://antelang.org/blog/safe_shared_mutability/ https://antelang.org/blog/safe_shared_mutability/
- mjburgess 2y agoThe dialetic beings with OP, and has pcw's reply and then mine. It does not begin with pcw's comment. The OP complains about rust not because they imagine Jai is memory safe, but because they feel the rewards of its approach significantly outweight the costs of Rust. pcw's comment was about tradeoffs programmers are willing to make -- and paints the picture more black-and-white than the reality; and more black and white than OP.
- MJGrzymek 2y agoNot sure about the implicit behavior. In C++, you can write a lot of code using vector and map that would require manual memory management in C. It's as if the heap wasn't there. Feels like there is a beneficial property in there.