Closed

Description
Having such simplified code:
fn main() {
let result: Result<String, String> = Ok("ok".to_string());
let ref_result = &result;
let x = ref_result.unwrap();
}
gives:
error[E0507]: cannot move out of borrowed content
--> src/main.rs:4:13
|
4 | let x = ref_result.unwrap();
| ^^^^^^^^^^ cannot move out of borrowed content
error: aborting due to previous error
error: Could not compile `playground`.
Thanks to irc Kimundi & Amarnath I got the solution & expanation:
// use:
let x = ref_result.as_ref().unwrap();
Explanation:
unwrap
requires full ownership because it moves values- see
self
in signature?
- see
ref_result
is only borrowing, (ref_result
is a reference, a reference means borrowing)
Using .as_ref()
works because:
It creates a brand new Result
with references to inner value, like:
from initial:
`&Result<T, V>`
to brand new one:
`Result<&T, &V>`
See implementation of Result.as_ref
here
If i got this correctly, using unwrap
on &Result
will always be corrupted.
My question is, could this be handled internally somehow by Rust?
And/Or better compilation error would be awesome for noobs like me :)
I'm not sure what the message should look like but the current one is a bit general.
Metadata
Metadata
Assignees
Labels
Type
Projects
Milestone
Relationships
Development
No branches or pull requests
Activity
ExpHP commentedon Feb 10, 2018
You are correct, though there is one exception for the case where both
T
andE
implCopy
. In this case,Result<T, E>
implsCopy
, and thus calling aself
function on a&Result<T, E>
becomes allowed.This is no trivial matter, and is something that would probably require an RFC and require lots of discussion (and probably additions to the language) to make happen. Consider
Option
, which is in a similar boat:Both
unwrap()
andunwrap_or_default()
are functions with the signaturefn(Option<T>) -> T
, but only one of them can used together with withas_ref()
to behave like afn(&Option<T>) -> &T
. Hence there would need to be something else in the signature to reflect this difference in capability; some way to indicate thatunwrap()
can be made polymorphic over ownership versus references.(well, okay; technically the
where T: Default
bound is a difference between the signatures, and is in fact the key thing that makes.as_ref().unwrap_as_default()
fail to compile; but attempting to apply this information in any sort of general fashion seems nontrivial, and I fear it could pose problems for specialization)One final thought: It is unfortunate that default match binding modes will further blur the line between
&Result<T, E>
andResult<&T, &E>
, potentially making issues like this feel even more subtle to beginners. But this was already anticipated...ghost commentedon Feb 11, 2018
I don't get it. How the code for that would look like?
Anyway, If it's really non trivial case then a better error message will be good enough I think.
What do you @ExpHP think?
Maybe I'm even able to fix it. I hope I don't overestimate my skills ;)
ExpHP commentedon Feb 11, 2018
Seems possible. The question is, what is the scope of the lint? Just
Option
andResult
? Does the compiler try to "guess" for the presence of methods likeas_ref()
based on their signature? Should it also suggestclone
, which is also frequently often the right solution for Option?I will cc @estebank who has been prolific with diagnostic hints and may have better ideas.
ExpHP commentedon Feb 11, 2018
I guess I was thinking of something like
The new
&?
syntax would make the signatures ofunwrap
andunwrap_or_default
different enough to clearly demonstrate why one can be called on references while the other cannot.However, an idea like this would need to go through the RFC process, where I imagine it would be quite contentious, and where it would be competing against other ideas that solve similar problems.
ghost commentedon Feb 11, 2018
Now I got it, thanks for explanation.
Anyway kill me, but I'm not sure I like it yet. :) It's a bit parallel (a few meanings of
&?
) and implicit? I don't know.. .However I would happily see better compilation error, maybe I'm able even to contribute it?
estebank commentedon Feb 11, 2018
There're a couple of tickets open to turn the error into something along the lines of
This wouldn't be helpful enough, but it is incremental improvement.
It could be possible that the machinery to suggest implementing
trait
s that have a given method could be used to suggestas_ref()
here, but I would tackle both action items separately.ghost commentedon Feb 19, 2018
Maybe it could be also added to https://doc.rust-lang.org/error-index.html ?
asquared31415 commentedon Jul 1, 2022
Currently in 1.62.0 stable the output is now
However that suggestion is still wrong, and applying it will cause an error with regards to type inference which will lead you down a path that won't work. The ideal suggestion is to put the
.as_ref()
before the.unwrap()
.estebank commentedon Jul 7, 2022
CC #90286
estebank commentedon Aug 19, 2022
Triage: current output in beta is correct:
Dylan-DPC commentedon Jun 29, 2023
Current error:
estebank commentedon Jun 29, 2023
I believe that there won't be any changes to the stdlib here, and the diagnostic is already "good enough". I'd like to fix the
consider calling as_ref or as_mut
to be a structured suggestion, but at least is there. I believe it is safe to close this ticket at this time.