Skip to content

Commit 80abb94

Browse files
authored
liaison: 2026-05-27 expert session with t-clippy (#677)
1 parent 5cc0933 commit 80abb94

1 file changed

Lines changed: 199 additions & 0 deletions

File tree

  • subcommittee/liaison/meetings/2026-05-27-clippy-expert-session
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
# Safety-Critical Rust Consortium Meeting on 2026-05-27 @ 10am EDT / 4pm CEST
2+
3+
Expert session with Jason Newcomb of the Rust Project Clippy Team (t-clippy)
4+
5+
| Search Key | Description |
6+
| :---- | :---- |
7+
| \[todo\] | Action Item |
8+
| \[decision\] | Something decided on |
9+
| \[important\] | Key information |
10+
11+
## Agenda
12+
13+
1. Introduction to t-clippy
14+
2. Practical guide to writing Clippy lints
15+
16+
## Check-in area
17+
18+
**Please add your name, and an emoji that describes your day.**
19+
20+
* David Svoboda (-:
21+
* Jason Newcomb
22+
* Michael Henn 🥵
23+
* Manuel Hatzl ☀️
24+
* Samuel Wright 🌞
25+
* Arshad Mahmood 🌅
26+
* Max Jacinto 🍀
27+
* Pete LeVasseur 🦀🦺
28+
* Mira Baumann 🧵
29+
* Raiki Tamura🏫
30+
* Achim Kriso 🦆
31+
* Mikhail Antoshkin 💤
32+
* William Barsse
33+
* Marcos Borges 😎
34+
* Christof Petig 🥵
35+
36+
**Notetaker:**
37+
38+
* Pete LeVasseur
39+
40+
## Housekeeping section
41+
42+
*
43+
44+
## Tasks
45+
46+
*
47+
48+
## Meeting Minutes
49+
50+
## Introduction to t-clippy
51+
52+
Clippy Book / Getting Started Guide
53+
54+
* [https://doc.rust-lang.org/nightly/clippy/development/infrastructure/book.html](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/book.html)
55+
56+
Who has worked on/with Clippy?
57+
58+
* Pete LeVasseur
59+
* Arshad Mahmood
60+
* Achim Kriso
61+
62+
Who has worked on/with static analysis tools in the past?
63+
64+
* David Svoboda
65+
66+
Differing levels of where you can “hook into”
67+
68+
* Syntax/AST
69+
* HIR
70+
* MIR
71+
72+
Can we have the lints be put into their own Safety-Critical Rust grouping (to Jason Newcomb)?
73+
74+
* Jason will bring this forward to the team and discuss the idea
75+
* Might or might not be a need for this depending on (1) how many lints we are writing (2) how
76+
77+
Can we have lints that overlap between different groups?
78+
79+
* Technically possible today
80+
* Prefer to not do this
81+
* Jason would need to bring this back to the team to discuss the usecase of safety-critical to be able to “turn on all the things”
82+
83+
Starting point
84+
85+
* `cargo dev new_lint -h` for reading how to create a new lint
86+
* Also read: [https://doc.rust-lang.org/nightly/clippy/development/infrastructure/book.html](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/book.html)
87+
* Basic scaffolding will be set up
88+
* “Lint pass” to hook into compiler’s infrastructure
89+
* Could be any number of lints in a single lint pass
90+
* Lint pass runs as visitor over entire HIR tree
91+
* Can then define `check_expr` on the `LateLintPass` which will run over every expression node in the HIR tree
92+
* Can then define `check_body` as well as an alternative type of item to check
93+
* Many, many hooks are available to you in here to hook into the visitor
94+
95+
In `check_expr`:
96+
97+
* Tend to first do some sort of filtering to find the type of expression that you’d like to lint on
98+
* `match e.kind { /* .. */ }`
99+
* Can then filter onto e.g. `ExprKind::Path`
100+
* Can allow for destructuring and further filtering
101+
* Entails reading a lot of compiler documentation to understand how to check over HIR
102+
* [https://doc.rust-lang.org/nightly/nightly-rustc/](https://doc.rust-lang.org/nightly/nightly-rustc/)
103+
* [https://rustc-dev-guide.rust-lang.org/](https://rustc-dev-guide.rust-lang.org/)
104+
* [https://github.com/rust-lang/rust-clippy/tree/master/book/src/development](https://github.com/rust-lang/rust-clippy/tree/master/book/src/development)
105+
* Some things are documented, some things are not
106+
* May, at times, need to look at compiler source code
107+
* Can further filter, e.g.
108+
* `match p { QPath::Resolved(/* .. */) => { /* .. */ }, /* .. */ }`
109+
* Many, many hooks are available to you in here
110+
111+
The tests and how to work with them
112+
113+
* Ends up being named the same as the lint that you named
114+
* All lints run on all files (dogfooding)
115+
* If a new lint triggers on other files, you can tell them to ignore the new lint
116+
* When writing test, then default enabled things run at the same time
117+
* Could cause it to take some time to run at first
118+
* Normally then handle this with a targeted `#![allow(clippy::other_failing_lint_we_dont_care_about)]`
119+
* There are `your_lint_here.stderr` files which contain the expected output of the lint that this is checked against
120+
121+
The mindset
122+
123+
* Write a test which is “normal” and represents where the lint should fire
124+
* Write the the lint logic
125+
* Go run the lints
126+
* Note that it may fail or not catch what we want
127+
* Once it does, run the `bless` command and go back and write another test, then flesh out the lint more in a loop
128+
129+
Question: Is there some kind of workflow / secret that will not be on the documentation?
130+
131+
* No, not really
132+
* All of what Jason is walking us through is available in the documentation
133+
* Some of the things “not in” the Clippy documentation could be where as a lint implementor you have to get into how the compiler works, ASTs, HIR, MIR
134+
135+
Question: How about a more complex lint? Like constant propagation?
136+
137+
* Please hang tight, we’ll come back to this
138+
139+
`LateLintPass` details for HIR
140+
141+
* Doesn’t contain type information
142+
* Second parameter of `LateContext` will give useful information
143+
* `cx.typeck_results()` will contain all the type checking information
144+
* Can work with this further, e.g. `typeck.expr_ty(e)`
145+
* There is a helper function to use for checking on trait implementation
146+
* `implements_trait!()`
147+
* Also have access to e.g. `cx.tcx.lang_items().eq_trait()` for getting the trait’s definition ID
148+
* Depending on if the trait has generics, there’s now an assert which forces passing this information that’s relevant in
149+
* Can resolve method calls, e.g. `ExprKind::MethodCall(/* .. */) => { def_id = typeck.type_dependent_def_id(e.hir_id) }`
150+
* This information must be obtained like above
151+
* Other useful things like diagnostic items, e.g. `cx.tcs.is_diagnostic_item(name, did)`
152+
* You’ll need to check the compiler documentation for this
153+
* Jump to definition will take you to compiler source so you can get that info that’s decorated on the item: `rustc_diagnostic_item`
154+
* Helpful at times when filtering to “do the opposite of what the check is for”
155+
* When referring to typechecked item, goes back to the trait, not the implementation of the trait
156+
* If “is this String’s implementation of something?” have to check type and Definition ID (def\_id)
157+
158+
`LateLintPass` details for MIR
159+
160+
* `check_fn()` or `check_body()`
161+
* `check_fn()` may also handle closures
162+
* First need to write a check for if MIR can be obtained
163+
* If something can never be satisfied, then the MIR body never exists
164+
* Would crash if trying to obtain
165+
* Work on optimized MIR
166+
* Perform whole MIR lint check on the body
167+
* For data flow analysis there’s fixed point analysis framework that allows to go MIR block by MIR block using the `Analysis` trait ([rustc\_mir\_dataflow](https://doc.rust-lang.org/beta/nightly-rustc/rustc_mir_dataflow/))
168+
* Propagate until you run out of checks/changes to perform
169+
* Not a lot specific to doing const propagation
170+
* Likely need to write your own code to handle this
171+
172+
Because lints are run on macro-expanded code
173+
174+
* You have to do some things to figure out if that’s the case
175+
* On each node you have the span
176+
* `e.span.ctxt()` \=\> syntax context
177+
* Unique syntax context for each
178+
* macro expansion and
179+
* AST \=\> HIR lowering
180+
* Syntax context allows for telling when this expansion or lowering has occurred
181+
* `e.span.ctxt().outer_expn_data()`
182+
* Would end up with two different macro expansion context
183+
* When writing lints you may need to keep track of this; these can show up anywhere
184+
* Any given `x` and `y` might originate from a macro expansion
185+
* For style lints this matters and you have to compare context a lot along the way
186+
* `e.span.ctxt() == p.span.ctxt()`
187+
* Checking if the context of the parent thing is the same as the expression under investigation
188+
189+
Ways to solicit help / support:
190+
191+
* If writing a lint and stuck \=\> open a draft PR
192+
* If stuck, can open a topic on the Rust Zulip’s clippy channel
193+
194+
## Material
195+
196+
Any material to read before the meeting should be included here.
197+
198+
*
199+

0 commit comments

Comments
 (0)