What was the rationale behind that design decision? Why isn't there an alternative method that borrows instead?
You can always add .as_ref()
before methods that take ownership to make them work by reference.
To answer the other question, the rationale for the decision seems to be given in Change `is_some_and` to take by value by camsteffen · Pull Request #98354 · rust-lang/rust · GitHub
Consistent with other function-accepting
Option
methods.
The linked discussions in that ticket goes over the pros and cons, including references to the as_ref()
workaround.
It also more general / sidesteps a potential future is_some_and_mut
request. My contrived example.
(Didn't seem to come up in the conversation, so maybe not a huge use case...)
I want to clarify that I was concerned about the content of Some
being moved out, but a simple (contrived) example shows why my concerns were unsustained:
fn f(){
let v = vec![0];
// BTW, I find it misleading that
// the diagnostics suggest `clone`
Some(v).is_some_and(|_| true);
drop(v);
}
It doesn't compile, but there's a simple fix:
fn f(){
let v = vec![0];
Some(&v).is_some_and(|_| true);
drop(v);
}
I'ts so obvious now that I wrote it: &T
is Copy
, so Option<&T>
is Copy
too! Therefore, no move occurs.
I've been learning Rust and its borrow-ck for months, and I thought that borrow would still be an error. I'm glad I proved myself wrong!
Edit: This doesn't compile either:
fn f(){
let v = vec![0];
// `(&Some(v)).as_ref()` doesn't work either
Some(v).as_ref().is_some_and(|_| true);
drop(v);
}
I remember seeing it referenced (indirectly) in this comment: https://github.com/rust-lang/rust/issues/93050#issuecomment-1166319932
Also consider
&self
is useless for aOption<&mut T>
.
It's not even about Copy
!
The move happens when you create the Option
:
let v = vec![0];
let some_v = Some(v);
drop(v);
...will also move v
into some_v
and fail to compile.
You created an Option<Vec<i32>>
, which, by definition, owns a Vec<i32>
[1].
When you do the same with Option<&Vec<i32>>
, it owns a &Vec<i32>
, and you don't move out of v
to create that.
as_ref
helps with the case where you have a reference to an Option
owning a value (&Option<T>
), but you want an Option
that you own, but which only has a reference to the value (Option<&T>
). This is common when you have a reference to a struct that stores owned data in an Option
. But it is not helpful in your case, because your Vec<i32>
is not stored in an Option
in the first place (it's stored in v
).
If you had this, then you could use as_ref
(this does compile):
let some_v = Some(vec![0]); //the `Vec<i32>` is stored in (owned by) an Option
let some_ref_v: Option<&Vec<i32>> = some_v.as_ref(); // desugars to (&some_v).as_ref();
drop(some_v);
↩︎enum Option<T> { Some(T), // ^--here None }
@FZs has provided an explanation, but URLO is the forum for questions about non-compiling code and the like.
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.