Skip to content

Book: Improve type checking and lint passes chapters #10653

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
- [Development](development/README.md)
- [Basics](development/basics.md)
- [Adding Lints](development/adding_lints.md)
- [Lint Passes](development/lint_passes.md)
- [Type Checking](development/type_checking.md)
- [Common Tools](development/common_tools_writing_lints.md)
- [Infrastructure](development/infrastructure/README.md)
Expand Down
22 changes: 22 additions & 0 deletions book/src/development/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,24 @@ If this is your first time contributing to Clippy, you should first read the
[Basics docs](basics.md). This will explain the basics on how to get the source
code and how to compile and test the code.

## Additional Readings for Beginners

If a dear reader of this documentation has never taken a class on compilers
and interpreters, it might be confusing as to why AST level deals with only
the language's syntax. And some readers might not even understand what lexing,
parsing, and AST mean.

This documentation serves by no means as a crash course on compilers or language design.
And for details specifically related to Rust, the [Rustc Development Guide][rustc_dev_guide]
is a far better choice to peruse.

The [Syntax and AST][ast] chapter and the [High-Level IR][hir] chapter are
great introduction to the concepts mentioned in this chapter.

Some readers might also find the [introductory chapter][map_of_territory] of
Robert Nystrom's _Crafting Interpreters_ a helpful overview of compiled and
interpreted languages before jumping back to the Rustc guide.

## Writing code

If you have done the basic setup, it's time to start hacking.
Expand All @@ -37,6 +55,10 @@ book](../lints.md).
> - Triage procedure
> - Bors and Homu
[ast]: https://rustc-dev-guide.rust-lang.org/syntax-intro.html
[hir]: https://rustc-dev-guide.rust-lang.org/hir.html
[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
[map_of_territory]: https://craftinginterpreters.com/a-map-of-the-territory.html
[clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md
[rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees
[rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories
Expand Down
24 changes: 1 addition & 23 deletions book/src/development/lint_passes.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Lint passes

Before working on the logic of a new lint, there is an important decision
that every Clippy developers must make: to use
that every Clippy developer must make: to use
[`EarlyLintPass`][early_lint_pass] or [`LateLintPass`][late_lint_pass].

In short, the `LateLintPass` has access to type and symbol information while the
Expand Down Expand Up @@ -107,30 +107,8 @@ that use `LateLintPass`:
$ cargo dev new_lint --name=<your_new_lint> --pass=late --category=<your_category_choice>
```

## Additional Readings for Beginners

If a dear reader of this documentation has never taken a class on compilers
and interpreters, it might be confusing as to why AST level deals with only
the language's syntax. And some readers might not even understand what lexing,
parsing, and AST mean.

This documentation serves by no means as a crash course on compilers or language design.
And for details specifically related to Rust, the [Rustc Development Guide][rustc_dev_guide]
is a far better choice to peruse.

The [Syntax and AST][ast] chapter and the [High-Level IR][hir] chapter are
great introduction to the concepts mentioned in this chapter.

Some readers might also find the [introductory chapter][map_of_territory] of
Robert Nystrom's _Crafting Interpreters_ a helpful overview of compiled and
interpreted languages before jumping back to the Rustc guide.

[ast]: https://rustc-dev-guide.rust-lang.org/syntax-intro.html
[early_context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.EarlyContext.html
[early_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html
[hir]: https://rustc-dev-guide.rust-lang.org/hir.html
[late_context]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/context/struct.LateContext.html
[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
[lexing_and_parsing]: https://rustc-dev-guide.rust-lang.org/overview.html#lexing-and-parsing
[rustc_dev_guide]: https://rustc-dev-guide.rust-lang.org/
[map_of_territory]: https://craftinginterpreters.com/a-map-of-the-territory.html
25 changes: 16 additions & 9 deletions book/src/development/type_checking.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ 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!");
Expand All @@ -70,18 +70,18 @@ pub fn is_char(self) -> bool {
}
```

Indeed, we just discovered `Ty`'s [`kind` method][kind], which provides us
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.
enum of over 25 variants, including items such as `Bool`, `Int`, `Ref`, etc.

### `kind` Usage

The `TyKind` of `Ty` can be returned by calling [`Ty.kind` method][kind].
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
Expand All @@ -107,15 +107,21 @@ impl LateLintPass<'_> for MyStructLint {
We've been talking about [`ty::Ty`][middle_ty] this whole time without addressing [`hir::Ty`][hir_ty], but the latter
is also important to understand.

`hir::Ty` would represent *what* an user wrote, while `ty::Ty` would understand the meaning of it (because it has more
information).
`hir::Ty` would represent *what* the user wrote, while `ty::Ty` is how the compiler sees the type and has more
information. Example:

**Example: `fn foo(x: u32) -> u32 { x }`**
```rust
fn foo(x: u32) -> u32 { x }
```

Here the HIR sees the types without "thinking" about them, it knows that the function takes an `u32` and returns
an `u32`. But at the `ty::Ty` level the compiler understands that they're the same type, in-depth lifetimes, etc...
an `u32`. As far as `hir::Ty` is concerned those might be different types. But at the `ty::Ty` level the compiler
understands that they're the same type, in-depth lifetimes, etc...

To get from a `hir::Ty` to a `ty::Ty`, you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function outside of bodies or
outside of bodies the [`TypeckResults::node_type()`][node_type] method.

you can use the [`hir_ty_to_ty`][hir_ty_to_ty] function to convert from a `hir::Ty` to a `ty::Ty`
> **Warning**: Don't use `hir_ty_to_ty` inside of bodies, because this can cause ICEs.
## Useful Links

Expand All @@ -130,6 +136,7 @@ in this chapter:
[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
[node_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TypeckResults.html#method.node_type
[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
Expand Down