Skip to content

Commit

Permalink
missing_trait_methods: lint methods in definition order
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexendoo committed Jul 26, 2024
1 parent 345c94c commit 10fb062
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 27 deletions.
44 changes: 18 additions & 26 deletions clippy_lints/src/missing_trait_methods.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_lint_allowed;
use clippy_utils::macros::span_is_local;
use rustc_hir::def_id::DefIdMap;
use rustc_hir::def_id::DefIdSet;
use rustc_hir::{Impl, Item, ItemKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::AssocItem;
use rustc_session::declare_lint_pass;

declare_clippy_lint! {
Expand Down Expand Up @@ -68,33 +67,26 @@ impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
}) = 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))
let trait_item_ids: DefIdSet = items
.iter()
.filter_map(|impl_item| impl_item.trait_item_def_id)
.collect();

for impl_item in *items {
if let Some(def_id) = impl_item.trait_item_def_id {
provided.remove(&def_id);
}
for assoc in cx
.tcx
.provided_trait_methods(trait_id)
.filter(|assoc| !trait_item_ids.contains(&assoc.def_id))
{
span_lint_and_then(
cx,
MISSING_TRAIT_METHODS,
cx.tcx.def_span(item.owner_id),
format!("missing trait method provided by default: `{}`", assoc.name),
|diag| {
diag.span_help(cx.tcx.def_span(assoc.def_id), "implement the method");
},
);
}

cx.tcx.with_stable_hashing_context(|hcx| {
for assoc in provided.values_sorted(&hcx, true) {
let source_map = cx.tcx.sess.source_map();
span_lint_and_then(
cx,
MISSING_TRAIT_METHODS,
source_map.guess_head_span(item.span),
format!("missing trait method provided by default: `{}`", assoc.name),
|diag| {
let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id));
diag.span_help(definition_span, "implement the method");
},
);
}
});
}
}
}
8 changes: 8 additions & 0 deletions tests/ui/missing_trait_methods.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,12 @@ impl B for Complete {
}
}

trait MissingMultiple {
fn one() {}
fn two() {}
fn three() {}
}

impl MissingMultiple for Partial {}

fn main() {}
38 changes: 37 additions & 1 deletion tests/ui/missing_trait_methods.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,41 @@ help: implement the method
LL | fn b<'a, T: AsRef<[u8]>>(a: &'a T) -> &'a [u8] {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 2 previous errors
error: missing trait method provided by default: `one`
--> tests/ui/missing_trait_methods.rs:58:1
|
LL | impl MissingMultiple for Partial {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: implement the method
--> tests/ui/missing_trait_methods.rs:53:5
|
LL | fn one() {}
| ^^^^^^^^

error: missing trait method provided by default: `two`
--> tests/ui/missing_trait_methods.rs:58:1
|
LL | impl MissingMultiple for Partial {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: implement the method
--> tests/ui/missing_trait_methods.rs:54:5
|
LL | fn two() {}
| ^^^^^^^^

error: missing trait method provided by default: `three`
--> tests/ui/missing_trait_methods.rs:58:1
|
LL | impl MissingMultiple for Partial {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: implement the method
--> tests/ui/missing_trait_methods.rs:55:5
|
LL | fn three() {}
| ^^^^^^^^^^

error: aborting due to 5 previous errors

0 comments on commit 10fb062

Please sign in to comment.