Because of experience with C++. There destructor is called at the end of the scope which leads to subtle (and very hard to find) bugs when people assume it doesn't.
Error in the other direction (destructor is not called when people expect it to be called, but later) just leads to easy-to-fix error message during compilation, worst case. Which is easily fixable.
Because it's scope is not what you think it is. You can find details in the reference.
In short, any temporary created during the evaluation of expression lives until the entire expression is evaluated. This means that temporaries are dropped once the expression's value is bound to a local variable or return value of the block. Without that rule, the following examples wouldn't work:
let x = func(string.as_ref());
// ^^^^^^^^^^^^^^^ this temporary must live until `func` returns
if let Some(str_mut) = mutex.lock().unwrap().get_mut(idx) {
str_mut.do_stuff();
// ^^^^^^^ guard must live until the `if`-expression fully evaluates,
// so that the guarded value is properly synchronized
}
To make your example work, you must explicitly drop the RwLock read guard before writing (or always acquire the write guard.
Well, in my opinion, it's not working in C++. Short-lived temporaries are a common cause of memory safety violations. But in general, if your algorithm requires something to be dropped at specific places, it's better to call drop explicitly. It clearly communicates to the reader that the drop behaviour is very subtle, and protects both against incorrectly inferred scopes and potential future modifications of the algorithm that may miss the subtleties of drop order.