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
Optionmethods.
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
&selfis 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.