-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use clippy_utils::diagnostics::span_lint_and_help; | ||
use clippy_utils::is_lint_allowed; | ||
use clippy_utils::macros::span_is_local; | ||
use rustc_hir::def_id::DefIdMap; | ||
use rustc_hir::{Impl, Item, ItemKind}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_middle::ty::AssocItem; | ||
use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// Checks if a provided method is used implicitly by a trait | ||
/// implementation. A usage example would be a wrapper where every method | ||
/// should perform some operation before delegating to the inner type's | ||
/// implemenation. | ||
/// | ||
/// This lint should typically be enabled on a specific trait `impl` item | ||
/// rather than globally. | ||
/// | ||
/// ### Why is this bad? | ||
/// Indicates that a method is missing. | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// trait Trait { | ||
/// fn required(); | ||
/// | ||
/// fn provided() {} | ||
/// } | ||
/// | ||
/// # struct Type; | ||
/// #[warn(clippy::missing_trait_methods)] | ||
/// impl Trait for Type { | ||
/// fn required() { /* ... */ } | ||
/// } | ||
/// ``` | ||
/// Use instead: | ||
/// ```rust | ||
/// trait Trait { | ||
/// fn required(); | ||
/// | ||
/// fn provided() {} | ||
/// } | ||
/// | ||
/// # struct Type; | ||
/// #[warn(clippy::missing_trait_methods)] | ||
/// impl Trait for Type { | ||
/// fn required() { /* ... */ } | ||
/// | ||
/// fn provided() { /* ... */ } | ||
/// } | ||
/// ``` | ||
#[clippy::version = "1.66.0"] | ||
pub MISSING_TRAIT_METHODS, | ||
restriction, | ||
"trait implementation uses default provided method" | ||
} | ||
declare_lint_pass!(MissingTraitMethods => [MISSING_TRAIT_METHODS]); | ||
|
||
impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods { | ||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { | ||
if !is_lint_allowed(cx, MISSING_TRAIT_METHODS, item.hir_id()) | ||
&& span_is_local(span) | ||
&& let ItemKind::Impl(Impl { | ||
items, | ||
of_trait: Some(trait_ref), | ||
.. | ||
}) = item.kind | ||
&& let Some(trait_id) = trait_ref.trait_def_id() | ||
{ | ||
let mut provided: DefIdMap<&AssocItem> = cx | ||
.tcx | ||
.provided_trait_methods(trait_id) | ||
.map(|assoc| (assoc.def_id, assoc)) | ||
.collect(); | ||
|
||
for impl_item in *items { | ||
if let Some(def_id) = impl_item.trait_item_def_id { | ||
provided.remove(&def_id); | ||
} | ||
} | ||
|
||
for assoc in provided.values() { | ||
let source_map = cx.tcx.sess.source_map(); | ||
let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id)); | ||
|
||
span_lint_and_help( | ||
cx, | ||
MISSING_TRAIT_METHODS, | ||
source_map.guess_head_span(item.span), | ||
&format!("missing trait method provided by default: `{}`", assoc.name), | ||
Some(definition_span), | ||
"implement the method", | ||
); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
### What it does | ||
Checks if a provided method is used implicitly by a trait | ||
implementation. A usage example would be a wrapper where every method | ||
should perform some operation before delegating to the inner type's | ||
implemenation. | ||
|
||
This lint should typically be enabled on a specific trait `impl` item | ||
rather than globally. | ||
|
||
### Why is this bad? | ||
Indicates that a method is missing. | ||
|
||
### Example | ||
``` | ||
trait Trait { | ||
fn required(); | ||
|
||
fn provided() {} | ||
} | ||
|
||
#[warn(clippy::missing_trait_methods)] | ||
impl Trait for Type { | ||
fn required() { /* ... */ } | ||
} | ||
``` | ||
Use instead: | ||
``` | ||
trait Trait { | ||
fn required(); | ||
|
||
fn provided() {} | ||
} | ||
|
||
#[warn(clippy::missing_trait_methods)] | ||
impl Trait for Type { | ||
fn required() { /* ... */ } | ||
|
||
fn provided() { /* ... */ } | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#![allow(unused, clippy::needless_lifetimes)] | ||
#![warn(clippy::missing_trait_methods)] | ||
|
||
trait A { | ||
fn provided() {} | ||
} | ||
|
||
trait B { | ||
fn required(); | ||
|
||
fn a(_: usize) -> usize { | ||
1 | ||
} | ||
|
||
fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] { | ||
a.as_ref() | ||
} | ||
} | ||
|
||
struct Partial; | ||
|
||
impl A for Partial {} | ||
|
||
impl B for Partial { | ||
fn required() {} | ||
|
||
fn a(_: usize) -> usize { | ||
2 | ||
} | ||
} | ||
|
||
struct Complete; | ||
|
||
impl A for Complete { | ||
fn provided() {} | ||
} | ||
|
||
impl B for Complete { | ||
fn required() {} | ||
|
||
fn a(_: usize) -> usize { | ||
2 | ||
} | ||
|
||
fn b<T: AsRef<[u8]>>(a: &T) -> &[u8] { | ||
a.as_ref() | ||
} | ||
} | ||
|
||
fn main() {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
error: missing trait method provided by default: `provided` | ||
--> $DIR/missing_trait_methods.rs:22:1 | ||
| | ||
LL | impl A for Partial {} | ||
| ^^^^^^^^^^^^^^^^^^ | ||
| | ||
help: implement the method | ||
--> $DIR/missing_trait_methods.rs:5:5 | ||
| | ||
LL | fn provided() {} | ||
| ^^^^^^^^^^^^^ | ||
= note: `-D clippy::missing-trait-methods` implied by `-D warnings` | ||
|
||
error: missing trait method provided by default: `b` | ||
--> $DIR/missing_trait_methods.rs:24:1 | ||
| | ||
LL | impl B for Partial { | ||
| ^^^^^^^^^^^^^^^^^^ | ||
| | ||
help: implement the method | ||
--> $DIR/missing_trait_methods.rs:15:5 | ||
| | ||
LL | fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] { | ||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
error: aborting due to 2 previous errors | ||
|