Live data from Hacker News

Rust--: Rust without the borrow checker

github.com

251–260 of 269 posts

Re: Rust--: Rust without the borrow checker

#251
post #248

Earlier quoted context omitted.

To learn something is generally the point. Either me, or you. I’ve been developing in rust for half a decade now and genuinely do not know what you were talking about here. I haven’t experienced it. So either there are pain points that I’m not familiar with (which I’m totally open to), or you might be mistaken about how rust works. Either way, one or both of us might learn something today.

All lessons are not equally valuable. Seemingly arbitrary reasoning for some borrow checker behavior is not interesting enough for me to learn. In the past, I would come across something and would lookup and the reasoning for it often would be "What if another thread do blah blah balh", but my program is single threaded.

Borrow checker issues do not require multiple threads or async execution to be realized. For example, a common error in C++ is to take a reference/interator into vector, then append/push onto the end of that vector, then access the original error. If that causes reallocation, the reference is no longer valid and this is UB. Rust catches this because append requires a mutable reference, and the borrow checker ensures there are no other outstanding references (read only or mutable) before taking the &mut self reference for appending.

This is generally my experience with Rust: write something the way I would in C++, get frustrated at borrow checker errors, then look into it and learn my C++ code has hidden bugs all these years, and appreciate the rust compiler’s complaints.

Re: Rust--: Rust without the borrow checker

#252

I'm the author of this repo. I see some really angry comments, some of them even personal. Obviously I didn't think that just by tinkering with a compiler, I'd get personally attacked, but anyway, fair enough. For those of you confused: yes, this started as a satirical project with the corroded lib. Then I thought "why not just remove the borrow checker?" without any real motivation. Then I just went ahead and did it…

Thanks for explaining why you made Rust--! I figured it was just whimsical play, and I find it delightful. I'm especially delighted to hear that it wasn't even hard to disable the borrow checker.

I hope you will answer the question here from @dataflow about whether, without the borrow checker, compiler optimizations will emit incorrect code. Did you have to make further modifications to disable those optimizations?

Re: Rust--: Rust without the borrow checker

#253
post #248

Earlier quoted context omitted.

All lessons are not equally valuable. Seemingly arbitrary reasoning for some borrow checker behavior is not interesting enough for me to learn. In the past, I would come across something and would lookup and the reasoning for it often would be "What if another thread do blah blah balh", but my program is single threaded.

Borrow checker issues do not require multiple threads or async execution to be realized. For example, a common error in C++ is to take a reference/interator into vector, then append/push onto the end of that vector, then access the original error. If that causes reallocation, the reference is no longer valid and this is UB. Rust catches this because append requires a mutable reference, and the borrow checker ensures…

>If that causes reallocation, the reference is no longer valid

Doesn't the append/push function return a pointer in that case? At least in `c` there are special functions that reallocate and is not done by implicitly (but I understand someone could write a function that does it).

Thus it appears that borrow checker's behavior is guided by bad designs in other languages. When bad design is patched with more design, the latter often becomes non-intuitive and restricting. That seems to have happened with the rust's borrow checker.

Re: Rust--: Rust without the borrow checker

#254

Earlier quoted context omitted.

> Sometimes, you just need to know if an idea will even work or what it would look like. I think what GP is trying to say is that the value of such exploration might be limited if you end up with something incompatible with "proper" Rust anyways. I suppose it depends on how frequently "transition through invalid Rust while experimenting and end up with valid Rust" happens instead of "transition through invalid Rust w…

In my case, I was adding a new admin api endpoint, which meant pulling through a bunch of stuff that was never meant for the api and got in a fight with the borrow checker. For me, I just wanted to see if I broke something on a feature level (it was never meant to be exposed by the api after all), and I didn’t care about memory safety at that point. Refactoring it properly just to get memory safety just to see what w…

I guess that doesn't neatly fall into the categories I described, though I think it's closer to the former than the latter.

That being said, I think what you describe sounds like a case where relaxed checks could be beneficial. It's the eternal tradeoff of requiring strong static checks, I suppose.

Re: Rust--: Rust without the borrow checker

#255

Earlier quoted context omitted.

Strictly speaking, elision just adds lifetimes based on common patterns, so yes, it wouldn't directly affect performance. I believe your parent is implying that if you skip using a lifetime and do something else instead to make it easier, that may be less performant.

I think his point is the lifetime you’d put there is identical to the lifetime that is inferred/elided. So there is literally no difference.

I thought they meant the case where you go "ugh, I don't want to write a lifetime here" and then change your code, because you have to. If you don't have to, then yes, there's literally no difference.

Re: Rust--: Rust without the borrow checker

#256
post #164

As someone who's only did a couple of small toy-projects in rust I was never annoyed by the borrow checker. I find it nothing but a small mental shift and I kinda like it. What I _do_ find annoying though and I cannot wrap my head around are lifetimes. Every time I think I understand it, I end up getting it wrong.

Lifetimes are the input to the borrow checker, so it doesn't make much sense to say you have never been bothered by the borrow checker but you are bothered by lifetimes.

Ah, that's a fair point. In that case then yes, I have been bothered by the borrow checker very much indeed lol.

Re: Rust--: Rust without the borrow checker

#257
post #253

Earlier quoted context omitted.

Borrow checker issues do not require multiple threads or async execution to be realized. For example, a common error in C++ is to take a reference/interator into vector, then append/push onto the end of that vector, then access the original error. If that causes reallocation, the reference is no longer valid and this is UB. Rust catches this because append requires a mutable reference, and the borrow checker ensures…

>If that causes reallocation, the reference is no longer valid Doesn't the append/push function return a pointer in that case? At least in `c` there are special functions that reallocate and is not done by implicitly (but I understand someone could write a function that does it). Thus it appears that borrow checker's behavior is guided by bad designs in other languages. When bad design is patched with more design, th…

In C++? No. The vector container is auto resizing. When it hits capacity limits it doubles the size of the allocation and copies the contents to the new memory. An insertion operation will give you an iterator reference to the newly inserted value, but all existing references may or may not remain valid after the call.

This meant “guided by bad design.” The borrow checker wasn’t written to handle this one use case. It was designed to make all such errors categorically impossible.

Re: Rust--: Rust without the borrow checker

#258

Earlier quoted context omitted.

> It will even work fine as long as you don't write code which invokes UB (which does include code which would not pass the borrow checker, as the borrow checker necessarily rejects valid programs in order to forbid all invalid programs). To be clear, by "this" I meant "[allowing] code that would normally violate Rust's borrowing rules to compile and run successfully," which both of us seem to believe to be UB.

Not quite, there is code which fails borrow checking but is safe and sound. That is part of why a number of people have been waiting for Polonius and / or the tree borrows model, most classic are relatively trivial cases of "check then update" which fail to borrow check but are obviously non-problematic e.g. pub fn get_or_insert ( map: &'_ mut HashMap , ) -> &'_ String { if let Some(v) = map.get(&22) { return v; } ma…

That gets a bit tricky in terms of what you mean by valid programs. I presume what you mean is that you can't write a compiler that accepts every function which always returns the borrowed reference and reject every piece of code which fails to do so.

Though it's technically a bit different than the halting problem as this issue remains even if you assume that the function terminates -- you only want to show that the reference is returned assuming the code terminates if it isn't returned because it enters an infinite loop that's not a leak.

Re: Rust--: Rust without the borrow checker

#259
post #253

Earlier quoted context omitted.

>If that causes reallocation, the reference is no longer valid Doesn't the append/push function return a pointer in that case? At least in `c` there are special functions that reallocate and is not done by implicitly (but I understand someone could write a function that does it). Thus it appears that borrow checker's behavior is guided by bad designs in other languages. When bad design is patched with more design, th…

In C++? No. The vector container is auto resizing. When it hits capacity limits it doubles the size of the allocation and copies the contents to the new memory. An insertion operation will give you an iterator reference to the newly inserted value, but all existing references may or may not remain valid after the call. This meant “guided by bad design.” The borrow checker wasn’t written to handle this one use case. I…

I got how c++ vectors work. Rust `Vec`s work similarly IIRC. But the problem in C++ is that it allowed you to make a `Vec` from a raw pointer.

Anywany, IMHO rust has thrown the baby out with bath water. To make such errors (ie bad design) categorically impossible, it also made a huge class of valid programs also impossible. And in-turn to patch that, it gave yet another bunch of stuff (IIRC `Rc`, `RefCell`) that people are supposed to learn (they have horrible interfaces IMHO) by which some of the programs could be implemented.

I think someone else should give it another shot. May be they can come up with a better solution than this "borrow checker"..

Re: Rust--: Rust without the borrow checker

#260
post #224

Earlier quoted context omitted.

> If you rely on actual virtual memory instead of specially designed file format, saving large files will become prohibitively slow. On each save you have to stream the entire document from page file to actual memory, serialize the document, produce the entire file, then replace. And then when resuming editing after the save, you probably have to load the visible portion back from disk. How large is large? Loading an…

> How large is large? About the same size as amount of physical memory. For Word 97, minimum system requirement was 8MB RAM. That’s not just for the word, also the entire OS. > Loading and saving a few GiB from my SSD is pretty fast Indeed, that’s one of the reasons why modern word processors stopped doing complicated tricks like the ones I described, and instead serialize complete documents. > a special file format…

> That’s not the brightest idea: inflates disk bandwidth by at least a factor of 2.

Who cares for a word processor?

You are right, that you care for a database.

> The guy will be fine. The program might allocate a large buffer on startup but will only use the small initial slice because chromebooks don’t come with particularly large screens. Linux kernel does not automatically commit allocated memory.

That's just dynamic memory allocation in disguise via virtual memory.

Post reply on HN