Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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