about summary refs log tree commit diff
diff options
context:
space:
mode:
authorblyxyas <blyxyas@gmail.com>2023-04-07 13:08:29 +0200
committerblyxyas <blyxyas@gmail.com>2023-04-07 13:11:18 +0200
commit90e6ddc8e77eadf5cc83bc94a1d81dfb51c64371 (patch)
tree9c80c57468fb360fc232d8d0756b2f8ceb40c66e
parentb8cbce8e6aea52f694efe058df546e8028b224ef (diff)
downloadrust-90e6ddc8e77eadf5cc83bc94a1d81dfb51c64371.tar.gz
rust-90e6ddc8e77eadf5cc83bc94a1d81dfb51c64371.zip
New chapter: "Type Checking"
-rw-r--r--book/src/SUMMARY.md1
-rw-r--r--book/src/development/type_checking.md126
2 files changed, 127 insertions, 0 deletions
diff --git a/book/src/SUMMARY.md b/book/src/SUMMARY.md
index 0649f7a631d..cbd73376dfa 100644
--- a/book/src/SUMMARY.md
+++ b/book/src/SUMMARY.md
@@ -13,6 +13,7 @@
 - [Development](development/README.md)
     - [Basics](development/basics.md)
     - [Adding Lints](development/adding_lints.md)
+    - [Type Checking](development/type_checking.md)
     - [Common Tools](development/common_tools_writing_lints.md)
     - [Infrastructure](development/infrastructure/README.md)
         - [Syncing changes between Clippy and rust-lang/rust](development/infrastructure/sync.md)
diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md
new file mode 100644
index 00000000000..ff08cb1e524
--- /dev/null
+++ b/book/src/development/type_checking.md
@@ -0,0 +1,126 @@
+# Type Checking
+
+When we work on a new lint or improve an existing lint, we might want
+to retrieve the type `Ty` of an expression `Expr` for a variety of
+reasons. This can be achieved by utilizing the [`LateContext`][LateContext]
+that is available for [`LateLintPass`][LateLintPass].
+
+## `LateContext` and `TypeckResults`
+
+The lint context [`LateContext`][LateContext] and [`TypeckResults`][TypeckResults]
+(returned by `LateContext::typeck_results`) are the two most useful data structures
+in `LateLintPass`. They allow us to jump to type definitions and other compilation
+stages such as HIR.
+
+> Note: `LateContext.typeck_results`'s return value is [`TypeckResults`][TypeckResults]
+> and is created in the type checking step, it includes useful information such as types of
+> expressions, ways to resolve methods and so on.
+
+`TypeckResults` contains useful methods such as [`expr_ty`][expr_ty],
+which gives us access to the underlying structure [`Ty`][Ty] of a given expression.
+
+```rust
+pub fn expr_ty(&self, expr: &Expr<'_>) -> Ty<'tcx>
+```
+
+As a side note, besides `expr_ty`, [`TypeckResults`][TypeckResults] contains a
+[`pat_ty()`][pat_ty] method that is useful for retrieving a type from a pattern.
+
+## `Ty`
+
+`Ty` struct contains the type information of an expression.
+Let's take a look at `rustc_middle`'s [`Ty`][Ty] struct to examine this struct:
+
+```rust
+pub struct Ty<'tcx>(Interned<'tcx, WithStableHash<TyS<'tcx>>>);
+```
+
+At a first glance, this struct looks quite esoteric. But at a closer look,
+we will see that this struct contains many useful methods for type checking.
+
+For instance, [`is_char`][is_char] checks if the given `Ty` struct corresponds
+to the primitive character type.
+
+### `is_*` Usage
+
+In some scenarios, all we need to do is check if the `Ty` of an expression
+is a specific type, such as `char` type, so we could write the following:
+
+```rust
+impl LateLintPass<'_> for MyStructLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        // Get type of `expr`
+        let ty = cx.typeck_results().expr_ty(expr);
+        
+        // Check if the `Ty` of this expression is of character type
+        if ty.is_char() {
+            println!("Our expression is a char!");
+        }
+    }
+}
+```
+
+Furthermore, if we examine the [source code][is_char_source] for `is_char`,
+we find something very interesting:
+
+```rust
+#[inline]
+pub fn is_char(self) -> bool {
+    matches!(self.kind(), Char)
+}
+```
+
+Indeed, we just discovered `Ty`'s [`kind` method][kind], which provides us
+with [`TyKind`][TyKind] of a `Ty`.
+
+## `TyKind`
+
+`TyKind` defines the kinds of types in Rust's type system.
+Peeking into [`TyKind` documentation][TyKind], we will see that it is an
+enum of 27 variants, including items such as `Bool`, `Int`, `Ref`, etc.
+
+### `kind` Usage
+
+The `TyKind` of `Ty` can be returned by calling [`Ty.kind` method][kind].
+We often use this method to perform pattern matching in Clippy.
+
+For instance, if we want to check for a `struct`, we could examine if the
+`ty.kind` corresponds to an [`Adt`][Adt] (algebraic data type) and if its
+[`AdtDef`][AdtDef] is a struct:
+
+```rust
+impl LateLintPass<'_> for MyStructLint {
+    fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
+        // Get type of `expr`
+        let ty = cx.typeck_results().expr_ty(expr);
+        // Match its kind to enter the type
+        match ty.kind {
+            ty::Adt(adt_def, _) if adt_def.is_struct() => println!("Our `expr` is a struct!"),
+            _ => ()
+        }
+    }
+}
+```
+
+## Useful Links
+
+Below are some useful links to further explore the concepts covered
+in this chapter:
+
+- [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)
+
+[Adt]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variant.Adt
+[AdtDef]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/adt/struct.AdtDef.html
+[expr_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.expr_ty
+[is_char]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.is_char
+[is_char_source]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_middle/ty/sty.rs.html#1831-1834
+[kind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html#method.kind
+[LateContext]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/struct.LateContext.html
+[LateLintPass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
+[pat_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TypeckResults.html#method.pat_ty
+[Ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html
+[TyKind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html
+[TypeckResults]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html