]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/missing_trait_methods.rs
bump version to 1.80.1+dfsg1-1~bpo12+pve1
[rustc.git] / src / tools / clippy / clippy_lints / src / missing_trait_methods.rs
CommitLineData
2b03887a
FG
1use clippy_utils::diagnostics::span_lint_and_help;
2use clippy_utils::is_lint_allowed;
3use clippy_utils::macros::span_is_local;
4use rustc_hir::def_id::DefIdMap;
5use rustc_hir::{Impl, Item, ItemKind};
6use rustc_lint::{LateContext, LateLintPass};
7use rustc_middle::ty::AssocItem;
4b012472 8use rustc_session::declare_lint_pass;
2b03887a
FG
9
10declare_clippy_lint! {
11 /// ### What it does
12 /// Checks if a provided method is used implicitly by a trait
49aad941 13 /// implementation.
2b03887a 14 ///
31ef2f64
FG
15 /// ### Why restrict this?
16 /// To ensure that a certain implementation implements every method; for example,
17 /// a wrapper type where every method should delegate to the corresponding method of
18 /// the inner type's implementation.
19 ///
2b03887a
FG
20 /// This lint should typically be enabled on a specific trait `impl` item
21 /// rather than globally.
22 ///
2b03887a 23 /// ### Example
ed00b5ec 24 /// ```no_run
2b03887a
FG
25 /// trait Trait {
26 /// fn required();
27 ///
28 /// fn provided() {}
29 /// }
30 ///
31 /// # struct Type;
32 /// #[warn(clippy::missing_trait_methods)]
33 /// impl Trait for Type {
34 /// fn required() { /* ... */ }
35 /// }
36 /// ```
37 /// Use instead:
ed00b5ec 38 /// ```no_run
2b03887a
FG
39 /// trait Trait {
40 /// fn required();
41 ///
42 /// fn provided() {}
43 /// }
44 ///
45 /// # struct Type;
46 /// #[warn(clippy::missing_trait_methods)]
47 /// impl Trait for Type {
48 /// fn required() { /* ... */ }
49 ///
50 /// fn provided() { /* ... */ }
51 /// }
52 /// ```
53 #[clippy::version = "1.66.0"]
54 pub MISSING_TRAIT_METHODS,
55 restriction,
56 "trait implementation uses default provided method"
57}
58declare_lint_pass!(MissingTraitMethods => [MISSING_TRAIT_METHODS]);
59
60impl<'tcx> LateLintPass<'tcx> for MissingTraitMethods {
61 fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) {
62 if !is_lint_allowed(cx, MISSING_TRAIT_METHODS, item.hir_id())
63 && span_is_local(item.span)
64 && let ItemKind::Impl(Impl {
65 items,
66 of_trait: Some(trait_ref),
67 ..
68 }) = item.kind
69 && let Some(trait_id) = trait_ref.trait_def_id()
70 {
71 let mut provided: DefIdMap<&AssocItem> = cx
72 .tcx
73 .provided_trait_methods(trait_id)
74 .map(|assoc| (assoc.def_id, assoc))
75 .collect();
76
77 for impl_item in *items {
78 if let Some(def_id) = impl_item.trait_item_def_id {
79 provided.remove(&def_id);
80 }
81 }
82
9c376795
FG
83 cx.tcx.with_stable_hashing_context(|hcx| {
84 for assoc in provided.values_sorted(&hcx, true) {
85 let source_map = cx.tcx.sess.source_map();
86 let definition_span = source_map.guess_head_span(cx.tcx.def_span(assoc.def_id));
2b03887a 87
9c376795
FG
88 span_lint_and_help(
89 cx,
90 MISSING_TRAIT_METHODS,
91 source_map.guess_head_span(item.span),
e8be2606 92 format!("missing trait method provided by default: `{}`", assoc.name),
9c376795
FG
93 Some(definition_span),
94 "implement the method",
95 );
96 }
9ffffee4 97 });
2b03887a
FG
98 }
99 }
100}