Skip to content

Commit a276cd2

Browse files
committed
Add clippy docs to check for a specific type
1 parent d134ddd commit a276cd2

File tree

1 file changed

+47
-7
lines changed

1 file changed

+47
-7
lines changed

doc/common_tools_writing_lints.md

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ You may need following tooltips to catch up with common operations.
44

55
- [Common tools for writing lints](#common-tools-for-writing-lints)
66
- [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
7-
- [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
7+
- [Checking if an expr is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
8+
- [Checking for a specific type](#checking-for-a-specific-type)
89
- [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
910
- [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method)
1011
- [Dealing with macros](#dealing-with-macros)
@@ -15,7 +16,7 @@ Useful Rustc dev guide links:
1516
- [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
1617
- [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
1718

18-
# Retrieving the type of an expression
19+
## Retrieving the type of an expression
1920

2021
Sometimes you may want to retrieve the type `Ty` of an expression `Expr`, for example to answer following questions:
2122

@@ -54,7 +55,7 @@ Two noticeable items here:
5455
created by type checking step, it includes useful information such as types
5556
of expressions, ways to resolve methods and so on.
5657

57-
# Checking if an expr is calling a specific method
58+
## Checking if an expr is calling a specific method
5859

5960
Starting with an `expr`, you can check whether it is calling a specific method `some_method`:
6061

@@ -63,9 +64,11 @@ impl LateLintPass<'_> for MyStructLint {
6364
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
6465
if_chain! {
6566
// Check our expr is calling a method
66-
if let hir::ExprKind::MethodCall(path, _, _args, _) = &expr.kind;
67+
if let hir::ExprKind::MethodCall(path, _, [_self_arg, ..], _) = &expr.kind;
6768
// Check the name of this method is `some_method`
6869
if path.ident.name == sym!(some_method);
70+
// Optionally, check the type of the self argument.
71+
// - See "Checking for a specific type"
6972
then {
7073
// ...
7174
}
@@ -74,7 +77,44 @@ impl LateLintPass<'_> for MyStructLint {
7477
}
7578
```
7679

77-
# Checking if a type implements a specific trait
80+
## Checking for a specific type
81+
82+
There are three ways to check if an expression type is a specific type we want to check for.
83+
All of these methods only check for the base type, generic arguments have to be checked separately.
84+
85+
```rust
86+
use clippy_utils::ty::{is_type_diagnostic_item, is_type_lang_item};
87+
use clippy_utils::{paths, match_def_path};
88+
use rustc_span::symbol::sym;
89+
use rustc_hir::LangItem;
90+
91+
impl LateLintPass<'_> for MyStructLint {
92+
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
93+
// Getting the expression type
94+
let ty = cx.typeck_results().expr_ty(expr);
95+
96+
// 1. Using diagnostic items
97+
// The last argument is the diagnostic item to check for
98+
if is_type_diagnostic_item(cx, ty, sym::Option) {
99+
// The type is an `Option`
100+
}
101+
102+
// 2. Using lang items
103+
if is_type_lang_item(cx, ty, LangItem::RangeFull) {
104+
// The type is a full range like `.drain(..)`
105+
}
106+
107+
// 3. Using the type path
108+
if match_def_path(cx, def_id, &paths::RESULT) {
109+
// The type is a `core::result::Result`
110+
}
111+
}
112+
}
113+
```
114+
115+
Prefer using diagnostic items and lang items where possible.
116+
117+
## Checking if a type implements a specific trait
78118

79119
There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither.
80120

@@ -114,7 +154,7 @@ impl LateLintPass<'_> for MyStructLint {
114154
We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate.
115155
A list of defined paths for Clippy can be found in [paths.rs][paths]
116156

117-
# Checking if a type defines a specific method
157+
## Checking if a type defines a specific method
118158

119159
To check if our type defines a method called `some_method`:
120160

@@ -140,7 +180,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
140180
}
141181
```
142182

143-
# Dealing with macros
183+
## Dealing with macros
144184

145185
There are several helpers in [`clippy_utils`][utils] to deal with macros:
146186

0 commit comments

Comments
 (0)