@@ -4,7 +4,8 @@ You may need following tooltips to catch up with common operations.
4
4
5
5
- [ Common tools for writing lints] ( #common-tools-for-writing-lints )
6
6
- [ 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 )
8
9
- [ Checking if a type implements a specific trait] ( #checking-if-a-type-implements-a-specific-trait )
9
10
- [ Checking if a type defines a specific method] ( #checking-if-a-type-defines-a-specific-method )
10
11
- [ Dealing with macros] ( #dealing-with-macros )
@@ -15,7 +16,7 @@ Useful Rustc dev guide links:
15
16
- [ Type checking] ( https://rustc-dev-guide.rust-lang.org/type-checking.html )
16
17
- [ Ty module] ( https://rustc-dev-guide.rust-lang.org/ty.html )
17
18
18
- # Retrieving the type of an expression
19
+ ## Retrieving the type of an expression
19
20
20
21
Sometimes you may want to retrieve the type ` Ty ` of an expression ` Expr ` , for example to answer following questions:
21
22
@@ -54,7 +55,7 @@ Two noticeable items here:
54
55
created by type checking step, it includes useful information such as types
55
56
of expressions, ways to resolve methods and so on.
56
57
57
- # Checking if an expr is calling a specific method
58
+ ## Checking if an expr is calling a specific method
58
59
59
60
Starting with an ` expr ` , you can check whether it is calling a specific method ` some_method ` :
60
61
@@ -63,9 +64,11 @@ impl LateLintPass<'_> for MyStructLint {
63
64
fn check_expr (& mut self , cx : & LateContext <'tcx >, expr : & 'tcx hir :: Expr <'_ >) {
64
65
if_chain! {
65
66
// 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;
67
68
// Check the name of this method is `some_method`
68
69
if path . ident. name == sym! (some_method );
70
+ // Optionally, check the type of the self argument.
71
+ // - See "Checking for a specific type"
69
72
then {
70
73
// ...
71
74
}
@@ -74,7 +77,45 @@ impl LateLintPass<'_> for MyStructLint {
74
77
}
75
78
```
76
79
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
+ // This method should be avoided if possible
109
+ if match_def_path (cx , def_id , & paths :: RESULT ) {
110
+ // The type is a `core::result::Result`
111
+ }
112
+ }
113
+ }
114
+ ```
115
+
116
+ Prefer using diagnostic items and lang items where possible.
117
+
118
+ ## Checking if a type implements a specific trait
78
119
79
120
There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither.
80
121
@@ -102,6 +143,7 @@ impl LateLintPass<'_> for MyStructLint {
102
143
103
144
// 3. Using the type path with the expression
104
145
// we use `match_trait_method` function from Clippy's utils
146
+ // (This method should be avoided if possible)
105
147
if match_trait_method (cx , expr , & paths :: INTO ) {
106
148
// `expr` implements `Into` trait
107
149
}
@@ -114,7 +156,7 @@ impl LateLintPass<'_> for MyStructLint {
114
156
We access lang items through the type context ` tcx ` . ` tcx ` is of type [ ` TyCtxt ` ] [ TyCtxt ] and is defined in the ` rustc_middle ` crate.
115
157
A list of defined paths for Clippy can be found in [ paths.rs] [ paths ]
116
158
117
- # Checking if a type defines a specific method
159
+ ## Checking if a type defines a specific method
118
160
119
161
To check if our type defines a method called ` some_method ` :
120
162
@@ -140,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
140
182
}
141
183
```
142
184
143
- # Dealing with macros
185
+ ## Dealing with macros
144
186
145
187
There are several helpers in [ ` clippy_utils ` ] [ utils ] to deal with macros:
146
188
0 commit comments