]> git.lizzy.rs Git - rust.git/blobdiff - doc/common_tools_writing_lints.md
Auto merge of #7873 - xFrednet:7869-string-index-ice, r=Manishearth
[rust.git] / doc / common_tools_writing_lints.md
index 9dd4c8a5f7a703b935629d733e7b1cfa0735b8e7..1a6b7c8cb47a9db623f64fe5868d29d5f1dd5a40 100644 (file)
@@ -6,11 +6,12 @@ You may need following tooltips to catch up with common operations.
   - [Retrieving the type of an expression](#retrieving-the-type-of-an-expression)
   - [Checking if an expression is calling a specific method](#checking-if-an-expr-is-calling-a-specific-method)
   - [Checking if a type implements a specific trait](#checking-if-a-type-implements-a-specific-trait)
-  - [Checking if a type defines a method](#checking-if-a-type-defines-a-method)
+  - [Checking if a type defines a specific method](#checking-if-a-type-defines-a-specific-method)
   - [Dealing with macros](#dealing-with-macros)
 
 Useful Rustc dev guide links:
 - [Stages of compilation](https://rustc-dev-guide.rust-lang.org/compiler-src.html#the-main-stages-of-compilation)
+- [Diagnostic items](https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html)
 - [Type checking](https://rustc-dev-guide.rust-lang.org/type-checking.html)
 - [Ty module](https://rustc-dev-guide.rust-lang.org/ty.html)
 
@@ -45,11 +46,13 @@ Similarly in [`TypeckResults`][TypeckResults] methods, you have the [`pat_ty()`]
 to retrieve a type from a pattern.
 
 Two noticeable items here:
-- `cx` is the lint context [`LateContext`][LateContext].
-  The two most useful data structures in this context are `tcx` and `tables`,
-  allowing us to jump to type definitions and other compilation stages such as HIR.
-- `tables` is [`TypeckResults`][TypeckResults] and is created by type checking step,
-  it includes useful information such as types of expressions, ways to resolve methods and so on.
+- `cx` is the lint context [`LateContext`][LateContext]. The two most useful
+  data structures in this context are `tcx` and the `TypeckResults` returned by
+  `LateContext::typeck_results`, allowing us to jump to type definitions and
+  other compilation stages such as HIR.
+- `typeck_results`'s return value is [`TypeckResults`][TypeckResults] and is
+  created by type checking step, it includes useful information such as types
+  of expressions, ways to resolve methods and so on.
 
 # Checking if an expr is calling a specific method
 
@@ -60,7 +63,7 @@ impl LateLintPass<'_> for MyStructLint {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
         if_chain! {
             // Check our expr is calling a method
-            if let hir::ExprKind::MethodCall(path, _, _args) = &expr.kind;
+            if let hir::ExprKind::MethodCall(path, _, _args, _) = &expr.kind;
             // Check the name of this method is `some_method`
             if path.ident.name == sym!(some_method);
             then {
@@ -73,20 +76,21 @@ impl LateLintPass<'_> for MyStructLint {
 
 # Checking if a type implements a specific trait
 
-There are two ways to do this, depending if the target trait is part of lang items.
+There are three ways to do this, depending on if the target trait has a diagnostic item, lang item or neither.
 
 ```rust
-use crate::utils::{implements_trait, match_trait_method, paths};
+use clippy_utils::{implements_trait, is_trait_method, match_trait_method, paths};
+use rustc_span::symbol::sym;
 
 impl LateLintPass<'_> for MyStructLint {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
-        // 1. Using expression and Clippy's convenient method
-        // we use `match_trait_method` function from Clippy's toolbox
-        if match_trait_method(cx, expr, &paths::INTO) {
-            // `expr` implements `Into` trait
+        // 1. Using diagnostic items with the expression
+        // we use `is_trait_method` function from Clippy's utils
+        if is_trait_method(cx, expr, sym::Iterator) {
+            // method call in `expr` belongs to `Iterator` trait
         }
 
-        // 2. Using type context `TyCtxt`
+        // 2. Using lang items with the expression type
         let ty = cx.typeck_results().expr_ty(expr);
         if cx.tcx.lang_items()
             // we are looking for the `DefId` of `Drop` trait in lang items
@@ -95,22 +99,27 @@ impl LateLintPass<'_> for MyStructLint {
             .map_or(false, |id| implements_trait(cx, ty, id, &[])) {
                 // `expr` implements `Drop` trait
             }
+
+        // 3. Using the type path with the expression
+        // we use `match_trait_method` function from Clippy's utils
+        if match_trait_method(cx, expr, &paths::INTO) {
+            // `expr` implements `Into` trait
+        }
     }
 }
 ```
 
-> Prefer using lang items, if the target trait is available there.
-
-A list of defined paths for Clippy can be found in [paths.rs][paths]
+> Prefer using diagnostic and lang items, if the target trait has one.
 
 We access lang items through the type context `tcx`. `tcx` is of type [`TyCtxt`][TyCtxt] and is defined in the `rustc_middle` crate.
+A list of defined paths for Clippy can be found in [paths.rs][paths]
 
 # Checking if a type defines a specific method
 
 To check if our type defines a method called `some_method`:
 
 ```rust
-use crate::utils::{is_type_diagnostic_item, return_ty};
+use clippy_utils::{is_type_diagnostic_item, return_ty};
 
 impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
     fn check_impl_item(&mut self, cx: &LateContext<'tcx>, impl_item: &'tcx ImplItem<'_>) {
@@ -133,7 +142,7 @@ impl<'tcx> LateLintPass<'tcx> for MyTypeImpl {
 
 # Dealing with macros
 
-There are several helpers in Clippy's utils to deal with macros:
+There are several helpers in [`clippy_utils`][utils] to deal with macros:
 
 - `in_macro()`: detect if the given span is expanded by a macro
 
@@ -197,4 +206,5 @@ assert_eq!(differing_macro_contexts(x_is_some_span, x_unwrap_span), true);
 [LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
 [TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
 [pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
-[paths]: ../clippy_lints/src/utils/paths.rs
+[paths]: ../clippy_utils/src/paths.rs
+[utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/lib.rs