Skip to content

Commit 8142a31

Browse files
committed
Auto merge of rust-lang#115790 - flip1995:clippyup, r=Manishearth
Update Clippy r? `@Manishearth`
2 parents eb2446a + 780cbf3 commit 8142a31

File tree

175 files changed

+4685
-1638
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

175 files changed

+4685
-1638
lines changed

Cargo.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ dependencies = [
531531
"tester",
532532
"tokio",
533533
"toml 0.7.5",
534-
"ui_test 0.18.1",
534+
"ui_test 0.20.0",
535535
"walkdir",
536536
]
537537

@@ -5596,9 +5596,9 @@ dependencies = [
55965596

55975597
[[package]]
55985598
name = "ui_test"
5599-
version = "0.18.1"
5599+
version = "0.20.0"
56005600
source = "registry+https://github.com/rust-lang/crates.io-index"
5601-
checksum = "640159421816683e558867ffc0e60ed3a3ed97ec6ccb22c03adb41bf87c5cfa4"
5601+
checksum = "bfd8fb9b15c8332cf51bfc2dc4830063b2446a9c9d732421b56f2478024a3971"
56025602
dependencies = [
56035603
"annotate-snippets",
56045604
"anyhow",

src/tools/clippy/.github/driver.sh

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ unset CARGO_MANIFEST_DIR
3030
# Run a lint and make sure it produces the expected output. It's also expected to exit with code 1
3131
# FIXME: How to match the clippy invocation in compile-test.rs?
3232
./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
33-
sed -e "s,tests/ui,\$DIR," -e "/= help/d" double_neg.stderr >normalized.stderr
33+
sed -e "s,tests/ui,\$DIR," -e "/= help: for/d" double_neg.stderr > normalized.stderr
3434
diff -u normalized.stderr tests/ui/double_neg.stderr
3535

3636
# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same

src/tools/clippy/.github/workflows/clippy_bors.yml

+16-17
Original file line numberDiff line numberDiff line change
@@ -52,24 +52,14 @@ jobs:
5252
needs: changelog
5353
strategy:
5454
matrix:
55-
os: [ubuntu-latest, windows-latest, macos-latest]
56-
host: [x86_64-unknown-linux-gnu, i686-unknown-linux-gnu, x86_64-apple-darwin, x86_64-pc-windows-msvc]
57-
exclude:
55+
include:
5856
- os: ubuntu-latest
59-
host: x86_64-apple-darwin
60-
- os: ubuntu-latest
61-
host: x86_64-pc-windows-msvc
62-
- os: macos-latest
63-
host: x86_64-unknown-linux-gnu
64-
- os: macos-latest
65-
host: i686-unknown-linux-gnu
66-
- os: macos-latest
67-
host: x86_64-pc-windows-msvc
68-
- os: windows-latest
6957
host: x86_64-unknown-linux-gnu
70-
- os: windows-latest
58+
- os: ubuntu-latest
7159
host: i686-unknown-linux-gnu
7260
- os: windows-latest
61+
host: x86_64-pc-windows-msvc
62+
- os: macos-latest
7363
host: x86_64-apple-darwin
7464

7565
runs-on: ${{ matrix.os }}
@@ -84,8 +74,17 @@ jobs:
8474
- name: Checkout
8575
uses: actions/checkout@v3
8676

77+
- name: Install i686 dependencies
78+
if: matrix.host == 'i686-unknown-linux-gnu'
79+
run: |
80+
sudo dpkg --add-architecture i386
81+
sudo apt-get update
82+
sudo apt-get install gcc-multilib zlib1g-dev:i386
83+
8784
- name: Install toolchain
88-
run: rustup show active-toolchain
85+
run: |
86+
rustup set default-host ${{ matrix.host }}
87+
rustup show active-toolchain
8988
9089
# Run
9190
- name: Set LD_LIBRARY_PATH (Linux)
@@ -109,11 +108,11 @@ jobs:
109108
run: cargo build --tests --features deny-warnings,internal
110109

111110
- name: Test
112-
if: runner.os == 'Linux'
111+
if: matrix.host == 'x86_64-unknown-linux-gnu'
113112
run: cargo test --features deny-warnings,internal
114113

115114
- name: Test
116-
if: runner.os != 'Linux'
115+
if: matrix.host != 'x86_64-unknown-linux-gnu'
117116
run: cargo test --features deny-warnings,internal -- --skip dogfood
118117

119118
- name: Test clippy_lints

src/tools/clippy/CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -5031,6 +5031,7 @@ Released 2018-09-13
50315031
[`iter_nth_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_nth_zero
50325032
[`iter_on_empty_collections`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_empty_collections
50335033
[`iter_on_single_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_on_single_items
5034+
[`iter_out_of_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_out_of_bounds
50345035
[`iter_overeager_cloned`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_overeager_cloned
50355036
[`iter_skip_next`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_next
50365037
[`iter_skip_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#iter_skip_zero
@@ -5131,6 +5132,7 @@ Released 2018-09-13
51315132
[`misnamed_getters`]: https://rust-lang.github.io/rust-clippy/master/index.html#misnamed_getters
51325133
[`misrefactored_assign_op`]: https://rust-lang.github.io/rust-clippy/master/index.html#misrefactored_assign_op
51335134
[`missing_assert_message`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_assert_message
5135+
[`missing_asserts_for_indexing`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_asserts_for_indexing
51345136
[`missing_const_for_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_const_for_fn
51355137
[`missing_docs_in_private_items`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_docs_in_private_items
51365138
[`missing_enforced_import_renames`]: https://rust-lang.github.io/rust-clippy/master/index.html#missing_enforced_import_renames
@@ -5204,6 +5206,8 @@ Released 2018-09-13
52045206
[`no_effect_underscore_binding`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_effect_underscore_binding
52055207
[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
52065208
[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
5209+
[`non_canonical_clone_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_canonical_clone_impl
5210+
[`non_canonical_partial_ord_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_canonical_partial_ord_impl
52075211
[`non_minimal_cfg`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_minimal_cfg
52085212
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
52095213
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
@@ -5570,4 +5574,5 @@ Released 2018-09-13
55705574
[`allow-one-hash-in-raw-strings`]: https://doc.rust-lang.org/clippy/lint_configuration.html#allow-one-hash-in-raw-strings
55715575
[`absolute-paths-max-segments`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-max-segments
55725576
[`absolute-paths-allowed-crates`]: https://doc.rust-lang.org/clippy/lint_configuration.html#absolute-paths-allowed-crates
5577+
[`enforce-iter-loop-reborrow`]: https://doc.rust-lang.org/clippy/lint_configuration.html#enforce-iter-loop-reborrow
55735578
<!-- end autogenerated links to configuration documentation -->

src/tools/clippy/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ tempfile = { version = "3.2", optional = true }
2727
termize = "0.1"
2828

2929
[dev-dependencies]
30-
ui_test = "0.18.1"
30+
ui_test = "0.20"
3131
tester = "0.9"
3232
regex = "1.5"
3333
toml = "0.7.3"

src/tools/clippy/book/src/SUMMARY.md

+3
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,11 @@
1414
- [Basics](development/basics.md)
1515
- [Adding Lints](development/adding_lints.md)
1616
- [Defining Lints](development/defining_lints.md)
17+
- [Writing tests](development/writing_tests.md)
1718
- [Lint Passes](development/lint_passes.md)
19+
- [Emitting lints](development/emitting_lints.md)
1820
- [Type Checking](development/type_checking.md)
21+
- [Trait Checking](development/trait_checking.md)
1922
- [Method Checking](development/method_checking.md)
2023
- [Macro Expansions](development/macro_expansions.md)
2124
- [Common Tools](development/common_tools_writing_lints.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# Emitting a lint
2+
3+
Once we have [defined a lint](defining_lints.md), written [UI
4+
tests](writing_tests.md) and chosen [the lint pass](lint_passes.md) for the lint,
5+
we can begin the implementation of the lint logic so that we can emit it and
6+
gradually work towards a lint that behaves as expected.
7+
8+
Note that we will not go into concrete implementation of a lint logic in this
9+
chapter. We will go into details in later chapters as well as in two examples of
10+
real Clippy lints.
11+
12+
To emit a lint, we must implement a pass (see [Lint Passes](lint_passes.md)) for
13+
the lint that we have declared. In this example we'll implement a "late" lint,
14+
so take a look at the [LateLintPass][late_lint_pass] documentation, which
15+
provides an abundance of methods that we can implement for our lint.
16+
17+
```rust
18+
pub trait LateLintPass<'tcx>: LintPass {
19+
// Trait methods
20+
}
21+
```
22+
23+
By far the most common method used for Clippy lints is [`check_expr`
24+
method][late_check_expr], this is because Rust is an expression language and,
25+
more often than not, the lint we want to work on must examine expressions.
26+
27+
> _Note:_ If you don't fully understand what expressions are in Rust, take a
28+
> look at the official documentation on [expressions][rust_expressions]
29+
30+
Other common ones include the [`check_fn` method][late_check_fn] and the
31+
[`check_item` method][late_check_item].
32+
33+
### Emitting a lint
34+
35+
Inside the trait method that we implement, we can write down the lint logic and
36+
emit the lint with suggestions.
37+
38+
Clippy's [diagnostics] provides quite a few diagnostic functions that we can use
39+
to emit lints. Take a look at the documentation to pick one that suits your
40+
lint's needs the best. Some common ones you will encounter in the Clippy
41+
repository includes:
42+
43+
- [`span_lint`]: Emits a lint without providing any other information
44+
- [`span_lint_and_note`]: Emits a lint and adds a note
45+
- [`span_lint_and_help`]: Emits a lint and provides a helpful message
46+
- [`span_lint_and_sugg`]: Emits a lint and provides a suggestion to fix the code
47+
- [`span_lint_and_then`]: Like `span_lint`, but allows for a lot of output
48+
customization.
49+
50+
```rust
51+
impl<'tcx> LateLintPass<'tcx> for LintName {
52+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
53+
// Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint
54+
if some_lint_expr_logic(expr) {
55+
span_lint_and_help(
56+
cx, // < The context
57+
LINT_NAME, // < The name of the lint in ALL CAPS
58+
expr.span, // < The span to lint
59+
"message on why the lint is emitted",
60+
None, // < An optional help span (to highlight something in the lint)
61+
"message that provides a helpful suggestion",
62+
);
63+
}
64+
}
65+
}
66+
```
67+
68+
> Note: The message should be matter of fact and avoid capitalization and
69+
> punctuation. If multiple sentences are needed, the messages should probably be
70+
> split up into an error + a help / note / suggestion message.
71+
72+
## Suggestions: Automatic fixes
73+
74+
Some lints know what to change in order to fix the code. For example, the lint
75+
[`range_plus_one`][range_plus_one] warns for ranges where the user wrote `x..y +
76+
1` instead of using an [inclusive range][inclusive_range] (`x..=y`). The fix to
77+
this code would be changing the `x..y + 1` expression to `x..=y`. **This is
78+
where suggestions come in**.
79+
80+
A suggestion is a change that the lint provides to fix the issue it is linting.
81+
The output looks something like this (from the example earlier):
82+
83+
```text
84+
error: an inclusive range would be more readable
85+
--> $DIR/range_plus_minus_one.rs:37:14
86+
|
87+
LL | for _ in 1..1 + 1 {}
88+
| ^^^^^^^^ help: use: `1..=1`
89+
```
90+
91+
**Not all suggestions are always right**, some of them require human
92+
supervision, that's why we have [Applicability][applicability].
93+
94+
Applicability indicates confidence in the correctness of the suggestion, some
95+
are always right (`Applicability::MachineApplicable`), but we use
96+
`Applicability::MaybeIncorrect` and others when talking about a suggestion that
97+
may be incorrect.
98+
99+
### Example
100+
101+
The same lint `LINT_NAME` but that emits a suggestion would look something like this:
102+
103+
```rust
104+
impl<'tcx> LateLintPass<'tcx> for LintName {
105+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
106+
// Imagine that `some_lint_expr_logic` checks for requirements for emitting the lint
107+
if some_lint_expr_logic(expr) {
108+
span_lint_and_sugg( // < Note this change
109+
cx,
110+
LINT_NAME,
111+
span,
112+
"message on why the lint is emitted",
113+
"use",
114+
format!("foo + {} * bar", snippet(cx, expr.span, "<default>")), // < Suggestion
115+
Applicability::MachineApplicable,
116+
);
117+
}
118+
}
119+
}
120+
```
121+
122+
Suggestions generally use the [`format!`][format_macro] macro to interpolate the
123+
old values with the new ones. To get code snippets, use one of the `snippet*`
124+
functions from `clippy_utils::source`.
125+
126+
## How to choose between notes, help messages and suggestions
127+
128+
Notes are presented separately from the main lint message, they provide useful
129+
information that the user needs to understand why the lint was activated. They
130+
are the most helpful when attached to a span.
131+
132+
Examples:
133+
134+
### Notes
135+
136+
```text
137+
error: calls to `std::mem::forget` with a reference instead of an owned value. Forgetting a reference does nothing.
138+
--> $DIR/drop_forget_ref.rs:10:5
139+
|
140+
10 | forget(&SomeStruct);
141+
| ^^^^^^^^^^^^^^^^^^^
142+
|
143+
= note: `-D clippy::forget-ref` implied by `-D warnings`
144+
note: argument has type &SomeStruct
145+
--> $DIR/drop_forget_ref.rs:10:12
146+
|
147+
10 | forget(&SomeStruct);
148+
| ^^^^^^^^^^^
149+
```
150+
151+
### Help Messages
152+
153+
Help messages are specifically to help the user. These are used in situation
154+
where you can't provide a specific machine applicable suggestion. They can also
155+
be attached to a span.
156+
157+
Example:
158+
159+
```text
160+
error: constant division of 0.0 with 0.0 will always result in NaN
161+
--> $DIR/zero_div_zero.rs:6:25
162+
|
163+
6 | let other_f64_nan = 0.0f64 / 0.0;
164+
| ^^^^^^^^^^^^
165+
|
166+
= help: consider using `f64::NAN` if you would like a constant representing NaN
167+
```
168+
169+
### Suggestions
170+
171+
Suggestions are the most helpful, they are changes to the source code to fix the
172+
error. The magic in suggestions is that tools like `rustfix` can detect them and
173+
automatically fix your code.
174+
175+
Example:
176+
177+
```text
178+
error: This `.fold` can be more succinctly expressed as `.any`
179+
--> $DIR/methods.rs:390:13
180+
|
181+
390 | let _ = (0..3).fold(false, |acc, x| acc || x > 2);
182+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.any(|x| x > 2)`
183+
|
184+
```
185+
186+
### Snippets
187+
188+
Snippets are pieces of the source code (as a string), they are extracted
189+
generally using the [`snippet`][snippet_fn] function.
190+
191+
For example, if you want to know how an item looks (and you know the item's
192+
span), you could use `snippet(cx, span, "..")`.
193+
194+
## Final: Run UI Tests to Emit the Lint
195+
196+
Now, if we run our [UI test](writing_tests.md), we should see that Clippy now
197+
produces output that contains the lint message we designed.
198+
199+
The next step is to implement the logic properly, which is a detail that we will
200+
cover in the next chapters.
201+
202+
[diagnostics]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/index.html
203+
[late_check_expr]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_expr
204+
[late_check_fn]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_fn
205+
[late_check_item]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html#method.check_item
206+
[late_lint_pass]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.LateLintPass.html
207+
[rust_expressions]: https://doc.rust-lang.org/reference/expressions.html
208+
[`span_lint`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint.html
209+
[`span_lint_and_note`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_note.html
210+
[`span_lint_and_help`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_help.html
211+
[`span_lint_and_sugg`]: https://doc.rust-lang.org/nightly/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_sugg.html
212+
[`span_lint_and_then`]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/diagnostics/fn.span_lint_and_then.html
213+
[range_plus_one]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one
214+
[inclusive_range]: https://doc.rust-lang.org/std/ops/struct.RangeInclusive.html
215+
[applicability]: https://doc.rust-lang.org/beta/nightly-rustc/rustc_errors/enum.Applicability.html
216+
[snippet_fn]: https://doc.rust-lang.org/beta/nightly-rustc/clippy_utils/source/fn.snippet.html
217+
[format_macro]: https://doc.rust-lang.org/std/macro.format.html

0 commit comments

Comments
 (0)