-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Description
Reading the current documentation about Option<T>.unwrap()
at
http://doc.rust-lang.org/std/option/enum.Option.html#method.unwrap
it is not clear to me what the effect of unwrap()
is. I was supposing calling this function returns the value stored in the Option type and replaces it by an None
value. However, this seems not to be the case as the second assertion in the following example program passes fine:
fn main() {
let
let x = Some("air");
assert_eq!(x.unwrap(), "air");
assert_eq!(x.is_some(), true);
}
(You can run the program online at http://goo.gl/F9OnFk).
In addition, the current documentation says:
Returns the inner T of a Some(T).
Does this means the value contained in the Some(T)
is moved out or cloned or is a borrow taken? Also, T
is a type and I don't think that the function really returns a type, but a value of type T
. Therefore, should the quoted sentence maybe reworded towards something along the lines of:
Returns the value of type T as it is contained in the Some(T).
Please let me know what you think about these points. I am more than happy to provide a PR to improve the documentation, but I don't know all the answers to the questions I have raised above and I am also not sure if my claims are correct :/
Activity
apasel422 commentedon Mar 25, 2015
unwrap
moves the value out of the option if it isSome
, or panics if it isNone
. In your example, the call tounwrap
performs an implicit copy ofx
becausex
is of typeOption<&str>
, andOption<T>
implementsCopy
whenT
implementsCopy
(as&str
does).This example will not compile, because
Foo
does not implementCopy
:The error is:
The documentation could be updated to mention moving, but this is implicit in the method's
self
parameter, which is by-value.jviereck commentedon Mar 25, 2015
@apasel422 thanks a lot for your explanation! Still, I don't think I grasped how the
unwrap
works completely yet. Here is an example:I understand that moving a value from a borrowed object is not possible and that's why the first attempt fails. However, I don't see why the second attempt works. In a sense, the new type after the call to
entry_ref.body
can be written asOption<S>
withS ≡ &mut &mut Item
. In that case the call toOption<S>.unwrap()
as done inentry_ref.body.as_mut().unwrap()
looks to me again as a move. But asentry_ref.body
is borrowed, I don't see why this move is different from the first move attempt in my code, which failed.Is there a special rule to the
Option<T>.unwrap()
method, which makes the later case work but the first not or am I missing something on how the borrow/move rules in rust work?apasel422 commentedon Mar 25, 2015
Basically, in order to call
unwrap
, you need to have an ownedOption
. This is the case in your "ATTEMPT WORKS" code becauseas_mut
goes from&mut Option<T>
toOption<&mut T>
.The code under "ATTEMPT FAILED" doesn't compile because
entry_ref
is borrowed (let entry_ref = &mut EntryMutBorrow
), not becauseentry_ref.body
contains a borrowed value.For example, the following code does compile:
jviereck commentedon Mar 25, 2015
Thanks again @apasel422! The point that you need an owned
Option
makes sense to me and was something I was not that much aware about before :)What I don't see at this point is why
entry_ref.body
in my example is not an ownedOption
already. As you can see in this code example:It seems that
entry_ref.body
is of the owning typeOption<&mut Item>
already. From reading your last comment it sounds to me thatentry_ref.body
is supposed to be of type&mut Option<T>
withT≡&mut Item
here. But that is something I don't see yet :/Any comments is highly appreciated!
PS: @apasel422, I hope digging deeper on this issue is okay for you? From your comments so far I think I can fix the
Option.unwrap
documentation but still I would love to have a good overall understanding how the interaction withOption<T>
really works :)apasel422 commentedon Mar 25, 2015
In that example, the type of
entry_ref.body
is indeedOption<&mut Item>
, but it is not owned from the perspective of the compiler, because it is accessed through a reference (entry_ref
).jviereck commentedon Mar 25, 2015
Ahh, I think now I get it - thanks a lot @apasel422. Are these the (hidden) steps the compiler is doing when executing
entry_ref.body.as_mut().unwrap();
?entry_ref.body
is of typeOption<&mut Item>
Option<T>.as_mut()
is given byfn as_mut<'r>(&'r mut self) -> Option<&'r mut T>
, which means for calling theas_mut()
, theself
must be a mutable borrow.entry_ref.body
is NOT a mutable borrow, the compiler takes an implicit mutable borrow likeself=(&mut entry_ref.body)
and uses the result as theself
argument when callingas_mut
.Option.as_mut(&mut entry_ref.body)
does type check and returns a fully ownedOption<&'r mut T>
type. Here I am using the term "fully owned" to differentiate to the case of the previousentry_ref.body
which is not owned due to the access through the reference ofentry_ref
.as_mut
is now fully owned, the call toOption<T>.unwrap()
type checks.I've got to say: I love and be impressed what the rust compiler is doing underneath here (once you understand it :) )!
@apasel422, thank you sooo much for these helpful and very educational comments!!!
steveklabnik commentedon Mar 26, 2015
So, given all this: is there anything actionable we can do to improve these docs? What would you suggest, @jviereck ?
jviereck commentedon Mar 26, 2015
@steveklabnik, how do you feel about this:
unwrap moves the value out of the option if it is Some, or panics if it is None
sounds much better and is more precise compared to the current description ofOption<T>.unwrap()
, which isReturns the inner T of a Some(T).
. Therefore, I would love to exchange them..as_mut().unwrap()
and how it works to the existing documentation?steveklabnik commentedon Mar 27, 2015
I like it! would you like to submit a PR or should I take care of it?
I'm not sure.
apasel422 commentedon Mar 27, 2015
I don't think we need to add anything about
as_mut().unwrap()
, because there's nothing special about it. It just follows Rust's ownership and borrowing rules.However,
Option
's documentation in general does need work, both convention-wise and content-wise.Fix wording for Option<T>.unwrap. Fixes rust-lang#23713
Option<T>.unwrap
#23791rollup merge of rust-lang#23791: jviereck/fix-23713