Skip to content

Commit 748a593

Browse files
committed
Add new utils for defninition identification.
1 parent 70d5c8c commit 748a593

File tree

5 files changed

+670
-26
lines changed

5 files changed

+670
-26
lines changed

book/src/development/adding_lints.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -759,8 +759,7 @@ for some users. Adding a configuration is done in the following steps:
759759
Here are some pointers to things you are likely going to need for every lint:
760760

761761
* [Clippy utils][utils] - Various helper functions. Maybe the function you need
762-
is already in here ([`is_type_diagnostic_item`], [`implements_trait`],
763-
[`snippet`], etc)
762+
is already in here ([`implements_trait`], [`snippet`], etc)
764763
* [Clippy diagnostics][diagnostics]
765764
* [Let chains][let-chains]
766765
* [`from_expansion`][from_expansion] and
@@ -790,7 +789,6 @@ get away with copying things from existing similar lints. If you are stuck,
790789
don't hesitate to ask on [Zulip] or in the issue/PR.
791790

792791
[utils]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/index.html
793-
[`is_type_diagnostic_item`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.is_type_diagnostic_item.html
794792
[`implements_trait`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/ty/fn.implements_trait.html
795793
[`snippet`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/source/fn.snippet.html
796794
[let-chains]: https://github.com/rust-lang/rust/pull/94927

book/src/development/common_tools_writing_lints.md

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,8 @@ to check for. All of these methods only check for the base type, generic
8585
arguments have to be checked separately.
8686

8787
```rust
88-
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
8988
use clippy_utils::paths;
89+
use clippy_utils::res::MaybeDef;
9090
use rustc_span::symbol::sym;
9191
use rustc_hir::LangItem;
9292

@@ -97,12 +97,12 @@ impl LateLintPass<'_> for MyStructLint {
9797

9898
// 1. Using diagnostic items
9999
// The last argument is the diagnostic item to check for
100-
if is_type_diagnostic_item(cx, ty, sym::Option) {
100+
if ty.is_diag_item(cx, sym::Option) {
101101
// The type is an `Option`
102102
}
103103

104104
// 2. Using lang items
105-
if is_type_lang_item(cx, ty, LangItem::RangeFull) {
105+
if ty.is_lang_item(cx, LangItem::RangeFull) {
106106
// The type is a full range like `.drain(..)`
107107
}
108108

@@ -124,26 +124,28 @@ diagnostic item, lang item or neither.
124124

125125
```rust
126126
use clippy_utils::ty::implements_trait;
127-
use clippy_utils::is_trait_method;
128127
use rustc_span::symbol::sym;
129128

130129
impl LateLintPass<'_> for MyStructLint {
131130
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
132-
// 1. Using diagnostic items with the expression
133-
// we use `is_trait_method` function from Clippy's utils
134-
if is_trait_method(cx, expr, sym::Iterator) {
135-
// method call in `expr` belongs to `Iterator` trait
136-
}
137131

138-
// 2. Using lang items with the expression type
132+
// 1. Get the `DefId` of the trait.
133+
// via lang items
134+
let trait_id = cx.tcx.lang_items().drop_trait();
135+
// via diagnostic items
136+
let trait_id = cx.tcx.get_diagnostic_item(sym::Eq);
137+
138+
// 2. Check for the trait implementation via the `implements_trait` util.
139139
let ty = cx.typeck_results().expr_ty(expr);
140-
if cx.tcx.lang_items()
141-
// we are looking for the `DefId` of `Drop` trait in lang items
142-
.drop_trait()
143-
// then we use it with our type `ty` by calling `implements_trait` from Clippy's utils
144-
.is_some_and(|id| implements_trait(cx, ty, id, &[])) {
145-
// `expr` implements `Drop` trait
146-
}
140+
if trait_id.is_some_and(|id| implements_trait(cx, ty, id, &[])) {
141+
// `ty` implements the trait.
142+
}
143+
144+
// 3. If the trait requires additional generic arguments
145+
let trait_id = cx.tcx.lang_items().eq_trait();
146+
if trait_id.is_some_and(|id| implements_trait(cx, ty, id, &[ty])) {
147+
// `ty` implements `PartialEq<Self>`
148+
}
147149
}
148150
}
149151
```
@@ -159,7 +161,7 @@ paths for Clippy can be found in [paths.rs][paths]
159161
To check if our type defines a method called `some_method`:
160162

161163
```rust
162-
use clippy_utils::ty::is_type_lang_item;
164+
use clippy_utils::res::MaybeDef;
163165
use clippy_utils::{sym, return_ty};
164166

165167
impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
@@ -173,7 +175,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
173175
// We can also check it has a parameter `self`
174176
&& signature.decl.implicit_self.has_implicit_self()
175177
// We can go further and even check if its return type is `String`
176-
&& is_type_lang_item(cx, return_ty(cx, impl_item.hir_id), LangItem::String)
178+
&& return_ty(cx, impl_item.hir_id).is_lang_item(cx, LangItem::String)
177179
{
178180
// ...
179181
}

book/src/development/method_checking.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ the [`ExprKind`] that we can access from `expr.kind`:
1616
use rustc_hir as hir;
1717
use rustc_lint::{LateContext, LateLintPass};
1818
use rustc_span::sym;
19-
use clippy_utils::is_trait_method;
19+
use clippy_utils::res::{MaybeDef, MaybeTypeckRes};
2020

2121
impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint {
2222
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
@@ -28,7 +28,7 @@ impl<'tcx> LateLintPass<'tcx> for OurFancyMethodLint {
2828
// (It's necessary if we want to check that method is specifically belonging to a specific trait,
2929
// for example, a `map` method could belong to user-defined trait instead of to `Iterator`)
3030
// See the next section for more information.
31-
&& is_trait_method(cx, self_arg, sym::OurFancyTrait)
31+
&& cx.ty_based_def(self_arg).opt_parent(cx).is_diag_item(cx, sym::OurFancyTrait)
3232
{
3333
println!("`expr` is a method call for `our_fancy_method`");
3434
}
@@ -56,7 +56,7 @@ Let us take a look at how we might check for the implementation of
5656
`our_fancy_method` on a type:
5757

5858
```rust
59-
use clippy_utils::ty::is_type_diagnostic_item;
59+
use clippy_utils::res::MaybeDef;
6060
use clippy_utils::return_ty;
6161
use rustc_hir::{ImplItem, ImplItemKind};
6262
use rustc_lint::{LateContext, LateLintPass};
@@ -71,7 +71,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
7171
// We can also check it has a parameter `self`
7272
&& signature.decl.implicit_self.has_implicit_self()
7373
// We can go even further and even check if its return type is `String`
74-
&& is_type_diagnostic_item(cx, return_ty(cx, impl_item.hir_id), sym::String)
74+
&& return_ty(cx, impl_item.hir_id).is_diag_item(cx, sym::String)
7575
{
7676
println!("`our_fancy_method` is implemented!");
7777
}

clippy_utils/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub mod msrvs;
6666
pub mod numeric_literal;
6767
pub mod paths;
6868
pub mod qualify_min_const_fn;
69+
pub mod res;
6970
pub mod source;
7071
pub mod str_utils;
7172
pub mod sugg;

0 commit comments

Comments
 (0)