> 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);
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.