Live data from Hacker News

Rust--: Rust without the borrow checker

github.com

201–210 of 269 posts

Re: Rust--: Rust without the borrow checker

#201
post #78

Earlier quoted context omitted.

It does seem like satire. The very first example is: fn main() { let a = String::from("hello"); let b = a; println!("{a}"); // Works! Prints: hello } This is not “I have correct code but Rust can’t tell it’s correct.” This is “wow, this code is intentionally outrageously wrong, obviously dereferences a pointer that is invalid, and happens to work anyway.”

> this code is intentionally outrageously wrong Can you explain why? Why can't both a and b point at the same string object? Does `let b = a;` do something like a destructive move?

The rust way isn't intuitive if you're coming from C, but b = a does indeed transfer the ownership to b and a is now invalid/unusable. You would need to make a mutable reference if you want two variables that point to the same object.

    error[E0382]: borrow of moved value: `a`
     --> main.rs:4:16
      |
    2 |     let a = String::from("hello");
      |         - move occurs because `a` has type `String`, which does not implement the `Copy` trait
    3 |     let b = a;
      |             - value moved here
    4 |     println!("{a}");  // Works! Prints: hello
      |                ^ value borrowed here after move
      |
      = note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
    help: consider cloning the value if the performance cost is acceptable
      |
    3 |     let b = a.clone();
      |              ++++++++

Re: Rust--: Rust without the borrow checker

#202
post #78

Earlier quoted context omitted.

It does seem like satire. The very first example is: fn main() { let a = String::from("hello"); let b = a; println!("{a}"); // Works! Prints: hello } This is not “I have correct code but Rust can’t tell it’s correct.” This is “wow, this code is intentionally outrageously wrong, obviously dereferences a pointer that is invalid, and happens to work anyway.”

> this code is intentionally outrageously wrong Can you explain why? Why can't both a and b point at the same string object? Does `let b = a;` do something like a destructive move?

> Does `let b = a;` do something like a destructive move?

Yes. Semantically, Rust performs destructive moves by default, and as a result using `a` after `let b = a;` would normally result in a hard error [0].

The way destructive moves are (currently?) actually implemented, however, is as a shallow memcpy of the value in question coupled with compiler checks that the moved-from thing isn't used. As a result, if you disable the compiler check simple uses of the moved-from value immediately after the move could still work since the compiler doesn't take explicit steps to modify the moved-from value immediately after a move.

[0]: https://rust.godbolt.org/z/Wdr6G1GsK

Re: Rust--: Rust without the borrow checker

#203

Earlier quoted context omitted.

What the point, though? You will get compiling code, but later you would need to reachitecture code to avoid violating rust rules.

Sometimes, you just need to know if an idea will even work or what it would look like. If you have to refactor half the codebase (true story for me once), it makes the change a much harder sell without showing some benefits. IE, it keeps you from discovering better optimizations because you have to pay the costs upfront.

> 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 while experimenting and end up with invalid Rust", as well as how hard it is to fix the invalid Rust in the latter case.

Re: Rust--: Rust without the borrow checker

#204

Earlier quoted context omitted.

Did I write that I hated somebody? I don't think I wrote anything of the sort. I can't say my thoughts about Bjarne for example rise to hatred, nobody should have humoured him in the 1980s, but we're not talking about what happened when rich idiots humoured The Donald or something as serious as that - nobody died, we just got a lot of software written in a crap programming language, I've had worse Thursdays. And alth…

Correct me if I'm wrong, but I don't think you think that C++ programmers actually want to write "broken garbage", so when you say "millions of people want broken garbage" the implication is that a) they do write broken garbage, b) they're so stupid don't even know that is what they are doing. I can't really read else than in the same vein as an apartheid-era white South-African statement starting "all blacks ...", i…

Are you seriously comparing discrimination based on factors noone can control to a group literally defined by a choice they made? And you think that's a good faith argument?

Re: Rust--: Rust without the borrow checker

#205

The more I write code in other languages where I think hard about ownership ("does this method ultimately grab the object and throw a ref onto some long-lived data structure somewhere? Then it owns it, so I better clone it") the more robust my code in other languages generally gets. Same with mutation. Generally better to make a copy of something and then mess with it and throw it away than to try to mutate-then-unmu…

> Generally better to make a copy of something

> Eliminate loads of spooky-action-a-distance bugs

This line of thinking so sickens me. Many things are not easy when done right. That is no excuse to avoid understanding how to do them right. Sure, making endless copies is easier. But this is why machines now need 16GB of ram and four cores to run the calculator.

Re: Rust--: Rust without the borrow checker

#206

It would be great if it only allowed multiple mutable borrows. That's the only one that always bugs me, for mostly innocuous stuff.

This isn’t actually unsafe unless shared across threads right? Maybe the borrow checker needs to be more nuanced to differentiate this rather then outright banning it all together. It would increase the logic of the borrow checker by a lot though.

> This isn’t actually unsafe unless shared across threads right?

Multiple mutable borrows do not need multiple threads to cause UB. Consider the following:

    fn main() {
        let mut v = vec![0, 1, 2];
        let e = &mut v[0];
        v.push(3);
        *e = 4;
    }
rustc refuses to compile this code due to multiple mutable borrows of `v` [0]:

    error[E0499]: cannot borrow `v` as mutable more than once at a time
     --> :4:5
      |
    3 |     let e = &mut v[0];
      |                  - first mutable borrow occurs here
    4 |     v.push(3);
      |     ^ second mutable borrow occurs here
    5 |     *e = 4;
      |     ------ first borrow later used here
If rustc allowed multiple mutable borrows here, `v.push(3)` would cause the underlying vec to reallocate, which invalidates `e`, and so `*e = 4` would cause UB.

[0]: https://rust.godbolt.org/z/bsxKTWG3K

Re: Rust--: Rust without the borrow checker

#207

Earlier quoted context omitted.

It does. The UB is false positives to the question "Is this a valid program".

No one disputes that C++ accepts some invalid programs, I never claimed otherwise. I said that C++'s type system will reject some programs that are in principle correct, as opposed to what Spivak originally claimed about C++ accepting all correct programs as valid. The fact that some people can only think in terms of all or nothing is really saying a lot about the quality of discourse on this topic. There is a huge m…

Sorry, then I misunderstood you, do you have an example, of a correct rejected C++ program?

Re: Rust--: Rust without the borrow checker

#208

The more I write code in other languages where I think hard about ownership ("does this method ultimately grab the object and throw a ref onto some long-lived data structure somewhere? Then it owns it, so I better clone it") the more robust my code in other languages generally gets. Same with mutation. Generally better to make a copy of something and then mess with it and throw it away than to try to mutate-then-unmu…

> Generally better to make a copy of something > Eliminate loads of spooky-action-a-distance bugs This line of thinking so sickens me. Many things are not easy when done right . That is no excuse to avoid understanding how to do them right. Sure, making endless copies is easier. But this is why machines now need 16GB of ram and four cores to run the calculator.

> But this is why machines now need 16GB of ram and four cores to run the calculator.

This has more to do with the fact that the web stack has become the de-facto app development platform, and thus we inherit the bloat and optimization oversights of that platform.

You're not going to make a 16GB calculator just because you personally prefer copies over shared ownership in a language that gives you the tools to avoid bloat in a myriad of ways.

Re: Rust--: Rust without the borrow checker

#209

Earlier quoted context omitted.

No one disputes that C++ accepts some invalid programs, I never claimed otherwise. I said that C++'s type system will reject some programs that are in principle correct, as opposed to what Spivak originally claimed about C++ accepting all correct programs as valid. The fact that some people can only think in terms of all or nothing is really saying a lot about the quality of discourse on this topic. There is a huge m…

Sorry, then I misunderstood you, do you have an example, of a correct rejected C++ program?

Many cases that require any kind of cast are this.

Re: Rust--: Rust without the borrow checker

#210

I've been thinking of writing a language with Rust's ergonomics but less of the memory safety stuff. I prefer using no dynamic allocations, in which case the only memory safety feature I need is leaking references to locals into outer scopes. As for the thread safety stuff, most of my stuff is single-threaded.

I've been wishing for Rust to become more ergonomic, what ergonomics does Rust currently have that other languages lack?

To add to the sibling comments, a world-class LSP enabling you to get a great experience in any editor/IDE out of the box. This is not at all exclusive to Rust of course, most strongly typed languages have one at this point, but I've been working in Python lately and this is what I miss the most. (I'm using an LSP in Python, but it isn't as good at the best of times, and it seems like no matter how many times I fix it's configuration it's broken again the next day.)
Post reply on HN