Open
Description
What it does
This lint would trigger when a trait such as std::hash::Hasher
was implemented but relying on the slow delgated method (write
) without implementing the performance improving specialised methods (write_u8
).
I have thought of three ways for this lint to trigger:
- A restriction lint that the user has to enable for the specific
impl
block, called something likemissing_overrides
- A pedantic lint which triggers when a trait implementation is delegating all the methods it has implemented, but some default methods are being provided.
- A pedantic lint which triggers when a trait impl block is relying on default implemented methods. This would be noisy and expect to be
expect
ed in quite a lot of places.
Advantage
- Newtypes which are implementing traits via delegation do not miss out on the fast path implementations (ie:
std::hash::Hasher
) - Traits which default implementations just return errors don't accidentally turn a compile time issue to a runtime issue (ie:
serde::de::Visitor
)
Drawbacks
Method 1 would require knowledge of the lint to know to enable it, which probably means the user is going to implement all the default provided methods correctly anyway. Method 2 and 3 could be too noisy, even for pedantic.
Example
#![warn(clippy::pedantic)]
use std::hash::Hasher;
struct NewType(std::hash::DefaultHasher);
impl Hasher for NewType {
fn write(&mut self, bytes: &[u8]) {
self.0.write(bytes)
}
fn finish(&self) -> u64 {
self.0.finish()
}
}
Could be written as:
use std::hash::Hasher;
struct NewType(std::hash::DefaultHasher);
impl Hasher for NewType {
fn write(&mut self, bytes: &[u8]) {
self.0.write(bytes)
}
fn write_u8(&mut self, val: u8) {
self.0.write_u8(val);
}
fn write_u16(&mut self, val: u16) {
self.0.write_u16(val);
}
fn write_u32(&mut self, val: u32) {
self.0.write_u32(val);
}
// etc, etc, etc
fn finish(&self) -> u64 {
self.0.finish()
}
}