4 ms·
The point is that while it's easy to do in C++, it's extremely error prone. Rust encourages you to write code that works with things like slices and references
by wtetzner 8y ago
The point is that while it's easy to do in C++, it's extremely error prone.
Rust encourages you to write code that works with things like slices and references instead of copying, because the compiler won't let you use them in a way that is error prone.
- SamReidHughes 8y agoThat's some nice sounding evangelism, but also completely besides the point. You seem to think I don't understand C++ and Rust. Believe me, I do. Rust inhibits use cases of array slicing that are both useful and not error prone. Last time I read a blog post about this, they picked a situation that was perfectly safe and ordinary in C++, with straightforward function-local safety reasoning.
- wtetzner 8y agoJust out of curiosity, do you have an example where Rust got in your way when trying to use an array slice?
- SamReidHughes 8y agoApproximately, here is one example. I wanted to use something like a Vec<&[u8]> as a means of passing a set of buffers to a function. Likewise it made sense to return such a value from another function, g. The way g worked was to read or hold a large buffer into memory, e.g. 1 megabyte in size, and then parse out the slices from it. So maybe you'd want to return something that looks like the C++ type struct Foo { private: vector<uint8_t> buf; public: // points into buf vector<pair<const uint8_t *, size_t>> slices; }; Well you can't do that. Obviously there are workarounds, like to return an object of type Foo holding the buf, with an api like impl Foo { fn getSlices(&self) -> Vec<&[u8]> }. Internally the object holds a Vec<(usize, usize)> or something like that, and you have a bunch of translation logic around your API's. And extra work to allocate the return value. So that's one example of Rust getting in your way. Probably some others would be uses of Interval<Buf>, and some cases where functions return Buf in https://github.com/srh/nihdb https://github.com/srh/nihdb . I wanted to use &[u8] to represent the bounds of intervals, and IIRC that generally involved passing intervals upwards into functions, but for some reason I can't remember it got annoying and I couldn't be bothered to do it.
- steveklabnik 8y agoThis is a pain point, but it’s not due to slices; it’s the “self-referential struct problem.” There are various solutions, as you note, but it can be annoying, it’s true. It’s a tough one; in the general case, it’s saving you from problems, but when you know you’re not going to hit those edge cases, it’s less than ideal.
- SamReidHughes 8y agoI didn't say it was specific to slices. The inconvenience around array slices is because they have a pointer. The non-pointery aspects of Rust slices are an advantage over C++. (E.g. not having pointer arithmetic.)
- steveklabnik 8y agoThe thread started out by saying slicing, specifically. Regardless, no worries, I was just trying to add clarity around details, just in case.
- wtetzner 8y agoIs there a theoretical reason for the "self-referential struct problem", or is it just an artifact of the current borrow-checker implementation? It doesn't seem unsafe to have a struct field refer to another member of that struct, but maybe I'm missing something.
- steveklabnik 8y agoIt's not theoretical, it's practical. Here's some code with a self-referential struct: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=13c75bfc3ab953c4126dfb86fe8f701b https://play.rust-lang.org/?version=stable&mode=debug&editio... Here, we have a self-referential struct. If you run this, you may get different numbers than me, but [src/main.rs:17] &f = Foo { x: 5, p: 0x00007ffcbbba41c0 } Here, p points to x. It's all good. The address of f is [src/main.rs:19] &f as *const Foo = 0x00007ffcbbba41b8 We move f into oh_no. Its address changes: [src/main.rs:25] &f as *const Foo = 0x00007ffcbbba3f28 ... but p does not: [src/main.rs:26] &f = Foo { x: 5, p: 0x00007ffcbbba41c0 } Any access of p is now a use-after-free. Does that make sense?