Option::as_deref() not turning &Vec into slice

I've got some code dealing with hashmaps of vectors, and I encountered a problem that I don't quite understand. Since I have a HashMap<Vec<_>>, calling get() returns an Option<&Vec<_>>. I would like to turn this into a Option<&[_]>, and Option::as_deref() seems like it would do exactly that. However, calling as_deref() seems to have no effect at all and just gives me back the original type.

Some example code showing the same problem:

let foo: Option<Vec<u32>> = Some(vec![1, 2, 3]);
let bar: Option<&Vec<u32>> = foo.as_ref();
let baz: Option<&[u32]> = bar.as_deref(); // Does not compile: expected slice `[u32]`, found struct `Vec`

&T (i.e. &Vec<u32> in this case) derefs to &T per this blanket implementation and that's what you're invoking there.

On the other hand, Vec<u32> (no &) derefs to &[u32]. To invoke this, you'll need:

let baz: Option<&[u32]> = bar.map(std::ops::Deref::deref);

See this playground.

A more practical way to map it would be bar.map(Vec::as_slice).

5 Likes

To further explain the purpose of as_deref: it's meant to be called on &Option<Vec<T>>, not Option<&Vec<T>>, i. e. you could skip the first as_ref step, as it's designed to be an alternative to that. In other words, it's a shorthand for the whole of .as_ref().map(ops::Deref::deref).

I do agree that it not doing anything on Option<&T> can seem confusing, and the documentation could probably be improved to point that out explicitly, and name the alternative – IMO it could also call out the longer alternative that it's a shorthand for that I mentioned above.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.