rust-lang / rust-lang/rust-clippy
New lint: types implementing `Deref` should impl `AsRef<Self::Target>` and `Borrow<Self::Target>` (same with mut versions)
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
If a type implements Deref but does not implement AsRef<<Self as Deref>::Target> and Borrow<<Self as Deref>::Target> or the type implements DerefMut and is missing AsMut or BorrowMut for Target the lint warns about the missing implementations.
The lint suggestion should be machine-applicable.
Lint Name
deref_missing_as_ref_borrow
Category
style
Advantage
- Smart pointers in Rust usually have those traits implemented and implementing them is keeping things consistent.
- In generic code it is often better to use
AsRef/Borrowbounds (or theirmutversions) rather thanDeref. Some types implementAsReffor multiple return types - e.g.&strcan be treated as bytes.Borrowbound allows treatingTand&Tthe same. Without these traits implemented the smart pointer can not be used in such generic code.
Drawbacks
T: Borrow<U> has an additional restriction that, if implemented, {Partial}Eq, {Partial}Ord, and Hash of U are homomorphic with their implementations on T. It could be the case that the trait is deliberately not implemented because this restriction cannot be satifsfied. The lint could somehow try to take it into account (e.g. try to figure out if the impl just delegates to U) or an argument could be made that a such type should not impl Deref because of potential confusion - functions like sort_by_key could behave differently just because of (de)reference operators. Maybe a different lint should warn about that.
Example
pub struct MySmartPtr<T> {
ptr: *const T,
}
impl<T> Deref for MySmartPtr<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
// AsRef<T>, Borrow<T> missing
Could be written as:
```rust
pub struct MySmartPtr<T> {
ptr: *const T,
}
impl<T> Deref for MySmartPtr<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
unsafe { &*self.ptr }
}
}
impl<T> AsRef<T> for MySmartPtr<T> {
fn as_ref(&self) -> &T {
&*self
}
}
impl<T> Borrow<T> for MySmartPtr<T> {
fn borrow(&self) -> &T {
&*self
}
}
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
The issue names the proposed deref_missing_as_ref_borrow lint but does not identify implementation files or tests. Start by locating existing Clippy lint implementations and their registration and UI-test patterns, then assess how the stated Deref and DerefMut cases and machine-applicable suggestions fit those patterns; done means the lint behavior and diagnostic suggestions are covered by tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100