rust-lang / rust-lang/rust-clippy
Suggest Option::as_deref{_mut} when calling Option::as_{ref,mut} on Option<Box<T>>
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 13.5k
- Forks
- 2.2k
- Avg merge
- 2d 10h
- Merged PRs (30d)
- 32
Description
What it does
Suggest replacing calls to Option::<Box<T>>::as_ref and Option::<Box<T>>::as_mut with calls to Option::<Box<T>>::as_deref and Option::<Box<T>>::as_deref_mut.
Calling as_ref and as_mut on an Option<Box<T>> results in &Box<T> or &mut Box<T>, which are references to a pointer, or a double indirection. Changing these Option::as_ref and Option::as_mut calls to Option::as_deref and Option::as_deref_mut forces resolving the underlying &T and &mut T once, which amortizes the cost of following the double pointer over multiple uses of the option field.
These suggestions could also be implemented for other smart pointers like Rc and Arc.
Categories (optional)
- Kind: performance?
What is the advantage of the recommended code over the original code
The inner Box is derefed once.
Drawbacks
None.
Example
struct StateNotPresentError;
impl std::error::Error for StateNotPresentError {}
impl std::fmt::Display for StateNotPresentError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("State not present for extraction")
}
}
struct State;
struct Interpreter {
state: Option<Box<State>>,
}
fn heap_size(interp: &Interpreter) -> Result<String, Box<dyn std::error::Error> {
let state = interp.state.as_ref().ok_or(StateNotPresentError)?;
unimplemented!("Heap size not implemented");
// access `state` multiple times
}
fn eval(interp: &mut Interpreter) -> Result<String, Box<dyn std::error::Error> {
let state = interp.state.as_mut().ok_or(StateNotPresentError)?;
unimplemented!("Eval not implemented");
// access `state` multiple times
}
Could be written as:
struct StateNotPresentError;
impl std::error::Error for StateNotPresentError {}
impl std::fmt::Display for StateNotPresentError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("State not present for extraction")
}
}
struct State;
struct Interpreter {
state: Option<Box<State>>,
}
fn heap_size(interp: &Interpreter) -> Result<String, Box<dyn std::error::Error> {
let state = interp.state.as_deref().ok_or(StateNotPresentError)?;
unimplemented!("Heap size not implemented");
// access `state` multiple times
}
fn eval(interp: &mut Interpreter) -> Result<String, Box<dyn std::error::Error> {
let state = interp.state.as_deref_mut().ok_or(StateNotPresentError)?;
unimplemented!("Eval not implemented");
// access `state` multiple times
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start from the requested examples for Option<Box>::as_ref and as_mut, and review the proposed as_deref and as_deref_mut replacements. Determine the lint scope, including whether other smart pointers such as Rc and Arc are included. Done means the intended suggestions and their boundaries are defined well enough to implement and test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- devtools
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100