Hacker News new | ask | show | jobs
by notyoutube 1033 days ago
Isn't that one weird trick more or less defeating the whole purpose of rust's ownership/borrowing model by moving the problems one level up the ladder?

Having seen that kind of opinion stated elsewhere, it seems what most people would like is rust minus borrowing, and I feel I would get behind that too.

2 comments

> what most people would like is rust minus borrowing

It's already possible. Use Rust reference-counted smart pointers[1] for shareable immutable references and internal mutability[2] for non-shareable mutable references checked at runtime instead of compile time.

[1] https://doc.rust-lang.org/book/ch15-04-rc.html

[2] https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...

I think this is one of the main things Rust users don’t promote enough (I don’t see this in the article for instance).

let lock = Arc::new(RwLock::new(1));

This plus a few unwrapping things is enough to get you almost std::shared_ptr and then you can fight the borrow checker some other day.

> this is one of the main things Rust users don’t promote enough

This is probably because using internal mutability not to achieve a valid design goal (such as a controlled side-effect on an otherwise immutable entity), but to side-step the borrow checker for ease of programming, is not considered idiomatic Rust and even though it makes a good educational tool, it should rather not end up in production codebases.

Firstly, when using regular references, you cannot create multiple mutable references. This rule prevents subtle bugs such as data races. When using internal mutability, you still keep that protection, but it is (undesirably) delayed from compile time to runtime, potentially causing an unavoidable crash/panic.

Secondly, when using regular references, you cannot create even a single mutable reference when an immutable reference already exists. This rule prevents subtle bugs such as unexpected mutation ("from under you") of data that was passed-in as immutable. When using internal mutability, you throw away that protection, since multiple immutable reference owners can request a mutable reference (even if only one at a time).

  use std::rc::Rc;
  use std::cell::RefCell;
  
  let entity1 = Rc::new(RefCell::new(42));
  let /* immutable */ entity2 = entity1.clone();
    
  *entity1.borrow_mut() += 27;
  assert_ne!(*entity2.borrow_mut(), 42);
How would memory management work without the borrow checker?
Reference-counted[1], just like, say, Swift.

[1] https://en.wikipedia.org/wiki/Reference_counting