Closed sswybd closed 10 hours ago
And for the f1sr
function, even if we dealt with the temporary value dropped issue in the following code, the same error as above would still be imminent.
#![allow(unused)]
fn main() {
let mut ra= &mut S(5);
let binding = &*ra;
let rval = f1sr(&binding);
compute(ra, rval);
}
#[derive(Default, Debug)]
struct S(i32);
fn f1sr<'b, 'a>(rb: &'b &'a S) -> &'b S { *rb }
fn compute(ra: &mut S, rval: &S) {
std::mem::take(ra);
}
I think you're confusing the purpose of the example, but I can see the last mention of compute
might be misleading.
The purpose of the example is to show what's possible inside the f
functions, and f1sr
works as shown. The reason you are running into a compilation error is because your compute takes ra: &mut S
, instead of &S
.
You can't have a mutable and a shared borrow to the same thing at the same time, so in a sense all / most of the examples were broken if you wanted to have a compute
that took both.
So does this mean that the example usages are only "examples", not that strict and should be slightly modified for real cases (for compilation success) sometimes. The f1sr
, f1lr
, etc. themselves are the things that matter, not the latter usage of them?
And this modification also includes we should for example add let binding = &*ra;
to then use let rval = f1sr(&binding);
.
So does this mean that the example usages are only "examples", not that strict and should be slightly modified for real cases (for compilation success) sometimes
That's contextual, but generally yes.
You are right that practically none of the code snippets are self-contained, so you can't just randomly copy-paste them and expect them to work "as-is" (we're a cheat sheet after all, not Rust by Example).
That said, all snippets should be correct and work in the context they are portrayed in (if not, that's a bug) and the expectation is we make it clear what that context is.
In this particular case the footnote
f_lr cases can fail because returning &'a S from &'a mut S to caller means there would now exist two references (one mutable) to same S which is illegal
even touches the problem of the overlapping borrow issue you ran into.
The f1sr, f1lr, etc. themselves are the things that matter, not the latter usage of them?
In this case, yes.
And this modification also includes we should for example add let binding = &*ra; to then use let rval = f1sr(&binding);.
This should not be necessary, but that depends a bit on the code you are coming from. While Rust respects what you declare explicitly inside signatures, what happens inside function bodies is a different story.
Rust might sometimes apply "compiler magic" to fix references (e.g., deref, coercions, shorten lifetimes) for you, so that doesn't have a simple answer, has even changed between editions, and is a known 'issue' that makes using the language easy, but learning it hard.
I recommend taking some time to read Language Sugar.
All that said, we should probably add a footnote regarding compute to make it clear it takes two ordinary references.
This answers all my questions. Thanks a lot!
In https://cheats.rs/#memory-lifetimes's "References to References" section, there is the sample code like this:
I wrote the following code, which is basically the same and directly runnable:
This code is invalid since the reborrow of
rval
's lifetime is interrupted by the mutable borrowra
. The sample code here is therefore incorrect.