Live data from Hacker News

Turning off Rust's borrow checker completely (2022)

iter.ca

31–40 of 63 posts

Re: Turning off Rust's borrow checker completely (2022)

#31
post #26
post #24

Earlier quoted context omitted.

> No it's not, it's extremely common. Arc-Mutex yes, Arc-Box no. It's like "I want a shared, immutable reference to something recursive, or unsized". The heap part makes no sense because it's already allocated there if you use an Arc : https://doc.rust-lang.org/std/sync/struct.Arc.html > The type Arc provides shared ownership of a value of type T, allocated in the heap. Moreover, you don't even need the box for a dyn…

> Arc-Mutex yes, Arc-Box no. Yeah, looks like Arc-Box is kind of pointless, but isn't there some thread locality reason why people wrap `Box` in `Arc`? I remember reading something about it a while ago but maybe I'm misremembering.

To play devil's advocate:

`Arc` places the refcounts immediately before `T` in memory. If you are desperate to have `T` and `T`'s refcounts be on different cachelines to reduce false sharing in some contrived scenario, `Arc>` would technically accomplish this. I think a more realistic optimization would be to pad the start of `T` however.

`Box>` and `Arc>` are thin pointers (size ≈ size_of::()) even when `Box` is a fat pointer (size ≈ 2*size_of::() because `T` is `str`, `[u8]`, `dyn SomeTrait`, etc.). While various "thin" crates are typically saner alternatives for FFI or memory density (prefixing lengths/vtables in the pointed-at data instead of incurring double-indirection and double-allocation), these double boxes are a quick and dirty way of accomplishing guaranteed thin pointers with only `std` / `alloc`.

I would not call either of these use cases "extremely common" however.

Re: Turning off Rust's borrow checker completely (2022)

#32
post #30

I have limited experience with Rust and the combination of slow compile time and borrow checker is irritating. My rust code was less than a thousand lines and it takes like 10-20 seconds to compile. Rust really made me appreciate garbage collection after the number of times I resorted to things like Arc >.

I highly recommend checking out makepad [1] - they have +100k of rust code and the compile time is around 10-15 seconds on commodity hardware. However they are obsessed about performance. They reason for such speedy compile times is that makepad almost has no dependencies. [1] https://github.com/makepad/makepad/

IMHO Makepad also has an exceptionally readable Rust code style, which is a very rare thing (maybe that simple Rust style even contributes to the good build times, dunno) - but also: from the pov of a C programmer, 200 kloc in 10..15 seconds is still quite bad ;)

Re: Turning off Rust's borrow checker completely (2022)

#33
post #30

Earlier quoted context omitted.

I highly recommend checking out makepad [1] - they have +100k of rust code and the compile time is around 10-15 seconds on commodity hardware. However they are obsessed about performance. They reason for such speedy compile times is that makepad almost has no dependencies. [1] https://github.com/makepad/makepad/

IMHO Makepad also has an exceptionally readable Rust code style, which is a very rare thing (maybe that simple Rust style even contributes to the good build times, dunno) - but also: from the pov of a C programmer, 200 kloc in 10..15 seconds is still quite bad ;)

How quickly can you verify the memory safety of that C program in addition to compiling it though? When comparing like to like, C no longer looks so fast.

Re: Turning off Rust's borrow checker completely (2022)

#34
post #25

Earlier quoted context omitted.

I feel like people like OP, who don't understand UB and its consequences, would benefit the most from the strict compiler, but can be bothered the least to learn what it's saying.

I understand what it’s saying. I just disagree that it has to be done for every compilation. Often, as a human, I can reason that it is safe (or reasonably safe for what bug I am attempting to fix). I’m not talking about released software, I’m talking about software I am developing in the moment that I am developing it.

> as a human, I can reason that it is safe

This assumption has been tested at societal scale and proven false, at great cost.

Re: Turning off Rust's borrow checker completely (2022)

#35
It's been a while since I've programmed in Rust, and I was initially surprised that the get() call returned garbage. Could anyone explain why that is? I mostly program in C++ and C#.

After thinking about it, my intuition is that:

- the Vec was passed by value to the function, which in Rust means something different than passing a std::vector in c++ to a function, due to...

- Due to the language semantics, its reference counter remained 1 while inside the function, but decreased to 0 when returning to main, since in Rust if it isn't a borrow (ref) then it's a "steal" - the callee "steals" the Vec completely from the caller. Or something like that.

- Since the reference counter is 0 when returning to main, the Vec is released, akin to calling its destructor if this was C++.

- SOMETHING changed the value of either the internal pointer to the heap inside the stack-allocated Vec (so now it points to garbage), OR something overwrote the Vec's content with some garbage. I'm not sure what that something is, and why would it do that.

I apologize if my explanation/intuition above is garbage in itself, like I said it's been a while since I programmed in Rust.

Edit: formatting

Re: Turning off Rust's borrow checker completely (2022)

#36

Earlier quoted context omitted.

> and if it’s after the code I care about observing, it doesn’t matter That's not how undefined behavior works, though. Undefined behavior doesn't have an "after." By definition it leaves your entire program in an undefined state, which means its behavior cannot be reasoned about temporally or spatially in this way. Sure, in a simple or trivial case you might "get lucky", but merely by introducing undefined behavior…

It isn’t about the “after” it’s about the “before”. For example, if I insert some code that divides by zero “later” but causes some new behavior I’m interested in, that’s what I’m interested in. The divide by zero is annoying, but can be addressed later. If the compiler forced me to check ever integer division wasn’t a divide by zero, that would be annoying in this case. The borrow checker is like this. It forces you…

The parent's point is that there is no separation between "before" or "after", it all ends up in the same artifact. And when you write invalid code, you have no guarantees about the compiled artifact anymore.

There is an example of C code (fairly sure I saw it on HN) where violating a UB rule caused an entirely dead piece of code to suddenly be executed, which even made sense after explanation.

In the linked article, Rust-minus-borrow-checker somehow caused an invalid number to appear inside a compile-time static array.

Sure, poke around the results of UB all you want. Curiosity is great. But at some point you'll have to compile your hypothesis as part of valid code, to be able to trust the results.

Re: Turning off Rust's borrow checker completely (2022)

#37

Earlier quoted context omitted.

I understand what it’s saying. I just disagree that it has to be done for every compilation. Often, as a human, I can reason that it is safe (or reasonably safe for what bug I am attempting to fix). I’m not talking about released software, I’m talking about software I am developing in the moment that I am developing it.

> as a human, I can reason that it is safe This assumption has been tested at societal scale and proven false, at great cost.

I didn’t say I could do it successfully or that it even matters. Only that I am able to and execute, at my own discretion. You know, have agency.

Re: Turning off Rust's borrow checker completely (2022)

#38
post #35

It's been a while since I've programmed in Rust, and I was initially surprised that the get() call returned garbage. Could anyone explain why that is? I mostly program in C++ and C#. After thinking about it, my intuition is that: - the Vec was passed by value to the function, which in Rust means something different than passing a std::vector in c++ to a function, due to... - Due to the language semantics, its referen…

[deleted]

Re: Turning off Rust's borrow checker completely (2022)

#39
post #9

Earlier quoted context omitted.

You can’t really hate something that you profess to not deeply understand.

I can hate something for any reason I wish. They are my feelings that I wield. Who are you to tell me what I can and cannot feel?

You certainly can, though I submit that's a hollow emotion at best.

Re: Turning off Rust's borrow checker completely (2022)

#40
post #35

It's been a while since I've programmed in Rust, and I was initially surprised that the get() call returned garbage. Could anyone explain why that is? I mostly program in C++ and C#. After thinking about it, my intuition is that: - the Vec was passed by value to the function, which in Rust means something different than passing a std::vector in c++ to a function, due to... - Due to the language semantics, its referen…

You're mostly correct, it is moved into the function (pass by value), and then, at the end of the function's scope, the destructor is called automatically (as the compiler inserts a call to `drop()` at the end of the function) which de-allocates the vec, causing the reference obtained in `main()` become a dangling pointer.
Post reply on HN