←back to thread

Pitfalls of Safe Rust

(corrode.dev)
168 points pjmlp | 1 comments | | HN request time: 0.223s | source
Show context
thrance ◴[] No.43604610[source]
I'd add memory leaks to the list. Sometimes you feel compelled to wrap your data in an Rc or Arc (reference counted pointers for those unfamiliar) to appease the borrow checker. With capture semantics of closures and futures and such it's quite easy to fall into a referential cycle, which won't be freed when dropped.
replies(2): >>43607031 #>>43607085 #
1. pornel ◴[] No.43607085[source]
I don't think it's a common concern in Rust. It used to be a problem in Internet Explorer. It's a footgun in Swift, but Rust's exclusive ownership and immutability make cycles very difficult to create by accident.

If you wrap a Future in Arc, you won't be able to use it. Polling requires exclusive access, which Arc disables. Most combinators and spawn() require exclusive ownership of the bare Future type. This is verified at compile time.

Making a cycle with `Arc` is impossible unless two other criteria are met:

1. You have to have a recursive type. `Arc<Data>` can't be recursive unless `Data` already contains `Arc<Data>` inside it, or some abstract type that could contain `Arc<Data>` in it. Rust doesn't use dynamic types by default, and most data types can be easily shown to never allow such cycle.

It's difficult to make a cycle with a closure too, because you need to have an instance of the closure before you can create an Arc, but your closure can't capture the Arc before it's created. It's a catch-22 that needs extra tricks to work around, which is not something that you can just do by accident.

2. Even if a type can be recursive, it's still not enough, because the default immutability of Arc allows only trees. To make a cycle you need the recursive part of the type to also be in a wrapper type allowing interior mutability, so you can modify it later to form a cycle (or use `Arc::new_cycle` helper, which is an obvious red flag, but you still need to upgrade the reference to a strong one after construction).

It's common to have Arc-wrapped Mutex. It's possible to have recursive types, but having both together at the same time are less common, and then still you need to make a cycle yourself, and dodge all the ownership and borrow checking issues required to poll a future in such type.