about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-09-02 11:21:48 +0000
committerbors <bors@rust-lang.org>2023-09-02 11:21:48 +0000
commitb65e5445351ed80dfb7cab4ddc2c1c575292d9ca (patch)
tree57426d42744a394b8e48cfd90221def51e21fe8c
parent7cf96dabb7700160823a90ee1a0302069948ebad (diff)
parente1a3f635fcdbac410449c869416af9ebd3fee2f5 (diff)
downloadrust-b65e5445351ed80dfb7cab4ddc2c1c575292d9ca.tar.gz
rust-b65e5445351ed80dfb7cab4ddc2c1c575292d9ca.zip
Auto merge of #10626 - blyxyas:book-trait_checking, r=flip1995
Clippy Book Chapter Updates Reborn: Trait Checking

This PR adds a new chapter to the book: "Trait Checking". No major changes from the source (just some typos, re-phrasing, the usual).

## Notes

- Does not require any other PR to be merged.
- To talk about the whole project, please use the tracking issue for the project #10597 (It also contains a timeline, discussions and more information)

changelog: Add a new "Trait Checking" chapter to the book
-rw-r--r--book/src/SUMMARY.md1
-rw-r--r--book/src/development/trait_checking.md105
2 files changed, 106 insertions, 0 deletions
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 4c705346715..b02457307d7 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -18,6 +18,7 @@
     - [Lint Passes](development/lint_passes.md)
     - [Emitting lints](development/emitting_lints.md)
     - [Type Checking](development/type_checking.md)
+    - [Trait Checking](development/trait_checking.md)
     - [Method Checking](development/method_checking.md)
     - [Macro Expansions](development/macro_expansions.md)
     - [Common Tools](development/common_tools_writing_lints.md)
diff --git a/book/src/development/trait_checking.md b/book/src/development/trait_checking.md
new file mode 100644
index 00000000000..fb263922cf8
--- /dev/null
+++ b/book/src/development/trait_checking.md
@@ -0,0 +1,105 @@
+# Trait Checking
+
+Besides [type checking](type_checking.md), we might want to examine if
+a specific type `Ty` implements certain trait when implementing a lint.
+There are three approaches to achieve this, depending on if the target trait
+that we want to examine has a [diagnostic item][diagnostic_items],
+[lang item][lang_items], or neither.
+
+## Using Diagnostic Items
+
+As explained in the [Rust Compiler Development Guide][rustc_dev_guide], diagnostic items
+are introduced for identifying types via [Symbols][symbol].
+
+For instance, if we want to examine whether an expression implements
+the `Iterator` trait, we could simply write the following code,
+providing the `LateContext` (`cx`), our expression at hand, and
+the symbol of the trait in question:
+
+```rust
+use clippy_utils::is_trait_method;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_span::symbol::sym;
+
+impl LateLintPass<'_> for CheckIteratorTraitLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+		let implements_iterator = cx.tcx.get_diagnostic_item(sym::Iterator).map_or(false, |id| {
+    		implements_trait(cx, cx.typeck_results().expr_ty(arg), id, &[])
+		});
+		if implements_iterator {
+			// [...]
+		}
+
+    }
+}
+```
+
+> **Note**: Refer to [this index][symbol_index] for all the defined `Symbol`s.
+
+## Using Lang Items
+
+Besides diagnostic items, we can also use [`lang_items`][lang_items].
+Take a look at the documentation to find that `LanguageItems` contains
+all language items defined in the compiler.
+
+Using one of its `*_trait` method, we could obtain the [DefId] of any
+specific item, such as `Clone`, `Copy`, `Drop`, `Eq`, which are familiar
+to many Rustaceans.
+
+For instance, if we want to examine whether an expression `expr` implements
+`Drop` trait, we could access `LanguageItems` via our `LateContext`'s
+[TyCtxt], which provides a `lang_items` method that will return the id of
+`Drop` trait to us. Then, by calling Clippy utils function `implements_trait`
+we can check that the `Ty` of the `expr` implements the trait:
+
+```rust
+use clippy_utils::implements_trait;
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+
+impl LateLintPass<'_> for CheckDropTraitLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        let ty = cx.typeck_results().expr_ty(expr);
+        if cx.tcx.lang_items()
+            .drop_trait()
+            .map_or(false, |id| implements_trait(cx, ty, id, &[])) {
+                println!("`expr` implements `Drop` trait!");
+            }
+    }
+}
+```
+
+## Using Type Path
+
+If neither diagnostic item nor a language item is available, we can use
+[`clippy_utils::paths`][paths] with the `match_trait_method` to determine trait
+implementation.
+
+> **Note**: This approach should be avoided if possible, the best thing to do would be to make a PR to [`rust-lang/rust`][rust] adding a diagnostic item.
+
+Below, we check if the given `expr` implements the `Iterator`'s trait method `cloned` :
+
+```rust
+use clippy_utils::{match_trait_method, paths};
+use rustc_hir::Expr;
+use rustc_lint::{LateContext, LateLintPass};
+
+impl LateLintPass<'_> for CheckTokioAsyncReadExtTrait {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        if match_trait_method(cx, expr, &paths::CORE_ITER_CLONED) {
+            println!("`expr` implements `CORE_ITER_CLONED` trait!");
+        }
+    }
+}
+```
+
+[DefId]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/def_id/struct.DefId.html
+[diagnostic_items]: https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-items.html
+[lang_items]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir/lang_items/struct.LanguageItems.html
+[paths]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_utils/src/paths.rs
+[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
+[symbol]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/symbol/struct.Symbol.html
+[symbol_index]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_span/symbol/sym/index.html
+[TyCtxt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html
+[rust]: https://github.com/rust-lang/rust