Skip to content

Commit 7a19419

Browse files
committed
Update Clippy
1 parent 70ce94f commit 7a19419

File tree

483 files changed

+7313
-7108
lines changed

Some content is hidden

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

483 files changed

+7313
-7108
lines changed

.travis.yml

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,15 +18,6 @@ env:
1818
global:
1919
- RUST_BACKTRACE=1
2020

21-
before_install:
22-
- |
23-
# work-around for issue https://github.com/travis-ci/travis-ci/issues/6307
24-
# might not be necessary in the future
25-
if [ "$TRAVIS_OS_NAME" == "osx" ]; then
26-
command curl -sSL https://rvm.io/mpapis.asc | gpg --import -
27-
rvm get stable
28-
fi
29-
3021
install:
3122
- |
3223
if [ -z ${INTEGRATION} ]; then
@@ -46,6 +37,7 @@ install:
4637
# if: fork = false
4738
# but this is currently buggy travis-ci/travis-ci#9118
4839
matrix:
40+
fast_finish: true
4941
include:
5042
- os: osx # run base tests on both platforms
5143
env: BASE_TESTS=true

CONTRIBUTING.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,10 @@ All contributors are expected to follow the [Rust Code of Conduct](http://www.ru
1919
* [Running test suite](#running-test-suite)
2020
* [Running rustfmt](#running-rustfmt)
2121
* [Testing manually](#testing-manually)
22-
* [Linting Clippy with your local changes](#linting-clippy-with-your-local-changes)
2322
* [How Clippy works](#how-clippy-works)
2423
* [Fixing nightly build failures](#fixing-build-failures-caused-by-rust)
2524
* [Issue and PR Triage](#issue-and-pr-triage)
25+
* [Bors and Homu](#bors-and-homu)
2626
* [Contributions](#contributions)
2727

2828
## Getting started
@@ -156,7 +156,7 @@ to style guidelines. The code has to be formatted by `rustfmt` before a PR will
156156

157157
It can be installed via `rustup`:
158158
```bash
159-
rustup component add rustfmt-preview
159+
rustup component add rustfmt
160160
```
161161

162162
Use `cargo fmt --all` to format the whole codebase.
@@ -220,7 +220,7 @@ That's why the `else_if_without_else` example uses the `register_early_lint_pass
220220

221221
### Fixing build failures caused by Rust
222222

223-
Clippy will sometimes break because it still depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals.
223+
Clippy will sometimes fail to build from source because building it depends on unstable internal Rust features. Most of the times we have to adapt to the changes and only very rarely there's an actual bug in Rust. Fixing build failures caused by Rust updates, can be a good way to learn about Rust internals.
224224

225225
In order to find out why Clippy does not work properly with a new Rust commit, you can use the [rust-toolstate commit history][toolstate_commit_history].
226226
You will then have to look for the last commit that contains `test-pass -> build-fail` or `test-pass` -> `test-fail` for the `clippy-driver` component. [Here][toolstate_commit] is an example.
@@ -257,6 +257,17 @@ Our highest priority is fixing [crashes][l-crash] and [bugs][l-bug]. We don't
257257
want Clippy to crash on your code and we want it to be as reliable as the
258258
suggestions from Rust compiler errors.
259259

260+
## Bors and Homu
261+
262+
We use a bot powered by [Homu][homu] to help automate testing and landing of pull
263+
requests in Clippy. The bot's username is @bors.
264+
265+
You can find the Clippy bors queue [here][homu_queue].
266+
267+
If you have @bors permissions, you can find an overview of the available
268+
commands [here][homu_instructions].
269+
270+
260271
## Contributions
261272

262273
Contributions to Clippy should be made in the form of GitHub pull requests. Each pull request will
@@ -288,3 +299,6 @@ or the [MIT](http://opensource.org/licenses/MIT) license.
288299
[triage]: https://forge.rust-lang.org/triage-procedure.html
289300
[l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A
290301
[l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A
302+
[homu]: https://github.com/servo/homu
303+
[homu_instructions]: https://buildbot2.rust-lang.org/homu/
304+
[homu_queue]: https://buildbot2.rust-lang.org/homu/queue/clippy

README.md

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -106,8 +106,8 @@ script:
106106
# etc.
107107
```
108108

109-
It might happen that clippy is not available for a certain nightly release.
110-
In this case you can try to conditionally install clippy from the git repo.
109+
It might happen that Clippy is not available for a certain nightly release.
110+
In this case you can try to conditionally install Clippy from the git repo.
111111

112112
```yaml
113113
language: rust
@@ -149,21 +149,7 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints:
149149

150150
Note: `deny` produces errors instead of warnings.
151151

152-
Note: To use the new `clippy::lint_name` syntax, a recent compiler has to be used
153-
currently. If you want to compile your code with the stable toolchain you can use a `cfg_attr` to
154-
activate the `tool_lints` feature:
155-
```rust
156-
#![cfg_attr(feature = "cargo-clippy", allow(clippy::lint_name))]
157-
```
158-
159-
For this to work you have to use Clippy on the nightly toolchain: `cargo +nightly clippy`. If you
160-
want to use Clippy with the stable toolchain, you can stick to the old unscoped method to
161-
enable/disable Clippy lints until `tool_lints` are stable:
162-
```rust
163-
#![cfg_attr(feature = "cargo-clippy", allow(clippy_lint))]
164-
```
165-
166-
If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to clippy during the run: `cargo clippy -- -A lint_name` will run clippy with `lint_name` disabled and `cargo clippy -- -W lint_name` will run it with that enabled. On newer compilers you may need to use `clippy::lint_name` instead.
152+
If you do not want to include your lint levels in your code, you can globally enable/disable lints by passing extra flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic`
167153

168154
## License
169155

ci/base-tests.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,29 @@ fi
2020
# build clippy in debug mode and run tests
2121
cargo build --features debugging
2222
cargo test --features debugging
23+
# for faster build, share target dir between subcrates
24+
export CARGO_TARGET_DIR=`pwd`/target/
2325
cd clippy_lints && cargo test && cd ..
2426
cd rustc_tools_util && cargo test && cd ..
2527
cd clippy_dev && cargo test && cd ..
2628

2729
# Perform various checks for lint registration
2830
./util/dev update_lints --check
2931
cargo +nightly fmt --all -- --check
32+
33+
34+
#avoid loop spam
35+
set +x
36+
# make sure tests are formatted
37+
38+
# some lints are sensitive to formatting, exclude some files
39+
needs_formatting=false
40+
for file in `find tests -not -path "tests/ui/methods.rs" -not -path "tests/ui/format.rs" -not -path "tests/ui/formatting.rs" -not -path "tests/ui/empty_line_after_outer_attribute.rs" -not -path "tests/ui/double_parens.rs" -not -path "tests/ui/doc.rs" -not -path "tests/ui/unused_unit.rs" | grep "\.rs$"` ; do
41+
rustfmt ${file} --check || echo "${file} needs reformatting!" ; needs_formatting=true
42+
done
43+
44+
if [ "${needs_reformatting}" = true ] ; then
45+
echo "Tests need reformatting!"
46+
exit 2
47+
fi
48+
set -x

clippy_lints/src/attrs.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ fn check_clippy_lint_names(cx: &LateContext<'_, '_>, items: &[NestedMetaItem]) {
332332
&format!("unknown clippy lint: clippy::{}", name),
333333
|db| {
334334
if name.as_str().chars().any(|c| c.is_uppercase()) {
335-
let name_lower = name.as_str().to_lowercase().to_string();
335+
let name_lower = name.as_str().to_lowercase();
336336
match lint_store.check_lint_name(
337337
&name_lower,
338338
Some(tool_name.as_str())

clippy_lints/src/doc.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ fn check_doc<'a, Events: Iterator<Item = (usize, pulldown_cmark::Event<'a>)>>(
238238
}
239239

240240
fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) {
241-
for word in text.split_whitespace() {
241+
for word in text.split(|c: char| c.is_whitespace() || c == '\'') {
242242
// Trim punctuation as in `some comment (see foo::bar).`
243243
// ^^
244244
// Or even as in `_foo bar_` which is emphasized.

clippy_lints/src/excessive_precision.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,9 @@ impl ExcessivePrecision {
109109
}
110110
}
111111

112-
#[allow(clippy::doc_markdown)]
113112
/// Should we exclude the float because it has a `.0` or `.` suffix
114-
/// Ex 1_000_000_000.0
115-
/// Ex 1_000_000_000.
113+
/// Ex `1_000_000_000.0`
114+
/// Ex `1_000_000_000.`
116115
fn dot_zero_exclusion(s: &str) -> bool {
117116
if let Some(after_dec) = s.split('.').nth(1) {
118117
let mut decpart = after_dec.chars().take_while(|c| *c != 'e' || *c != 'E');

clippy_lints/src/methods/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1358,7 +1358,10 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr, arg: &hir::Exp
13581358
_ => {},
13591359
}
13601360

1361-
let deref_count = cx.tables.expr_adjustments(arg).iter()
1361+
let deref_count = cx
1362+
.tables
1363+
.expr_adjustments(arg)
1364+
.iter()
13621365
.filter(|adj| {
13631366
if let ty::adjustment::Adjust::Deref(_) = adj.kind {
13641367
true

clippy_lints/src/no_effect.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
5757
}
5858
match expr.node {
5959
ExprKind::Lit(..) | ExprKind::Closure(.., _) => true,
60-
ExprKind::Path(..) => !has_drop(cx, expr),
60+
ExprKind::Path(..) => !has_drop(cx, cx.tables.expr_ty(expr)),
6161
ExprKind::Index(ref a, ref b) | ExprKind::Binary(_, ref a, ref b) => {
6262
has_no_effect(cx, a) && has_no_effect(cx, b)
6363
},
@@ -70,7 +70,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
7070
| ExprKind::AddrOf(_, ref inner)
7171
| ExprKind::Box(ref inner) => has_no_effect(cx, inner),
7272
ExprKind::Struct(_, ref fields, ref base) => {
73-
!has_drop(cx, expr)
73+
!has_drop(cx, cx.tables.expr_ty(expr))
7474
&& fields.iter().all(|field| has_no_effect(cx, &field.expr))
7575
&& match *base {
7676
Some(ref base) => has_no_effect(cx, base),
@@ -82,7 +82,7 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool {
8282
let def = cx.tables.qpath_def(qpath, callee.hir_id);
8383
match def {
8484
Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..) => {
85-
!has_drop(cx, expr) && args.iter().all(|arg| has_no_effect(cx, arg))
85+
!has_drop(cx, cx.tables.expr_ty(expr)) && args.iter().all(|arg| has_no_effect(cx, arg))
8686
},
8787
_ => false,
8888
}
@@ -161,7 +161,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<Vec
161161
| ExprKind::AddrOf(_, ref inner)
162162
| ExprKind::Box(ref inner) => reduce_expression(cx, inner).or_else(|| Some(vec![inner])),
163163
ExprKind::Struct(_, ref fields, ref base) => {
164-
if has_drop(cx, expr) {
164+
if has_drop(cx, cx.tables.expr_ty(expr)) {
165165
None
166166
} else {
167167
Some(fields.iter().map(|f| &f.expr).chain(base).map(Deref::deref).collect())
@@ -172,7 +172,7 @@ fn reduce_expression<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr) -> Option<Vec
172172
let def = cx.tables.qpath_def(qpath, callee.hir_id);
173173
match def {
174174
Def::Struct(..) | Def::Variant(..) | Def::StructCtor(..) | Def::VariantCtor(..)
175-
if !has_drop(cx, expr) =>
175+
if !has_drop(cx, cx.tables.expr_ty(expr)) =>
176176
{
177177
Some(args.iter().collect())
178178
},

clippy_lints/src/redundant_clone.rs

Lines changed: 84 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use crate::rustc::hir::{def_id, Body, FnDecl};
1212
use crate::rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
1313
use crate::rustc::mir::{
1414
self, traversal,
15-
visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor},
15+
visit::{MutatingUseContext, PlaceContext, Visitor},
1616
TerminatorKind,
1717
};
1818
use crate::rustc::ty;
@@ -23,10 +23,11 @@ use crate::syntax::{
2323
source_map::{BytePos, Span},
2424
};
2525
use crate::utils::{
26-
in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node, span_lint_node_and_then,
27-
walk_ptrs_ty_depth,
26+
has_drop, in_macro, is_copy, match_def_path, match_type, paths, snippet_opt, span_lint_node,
27+
span_lint_node_and_then, walk_ptrs_ty_depth,
2828
};
2929
use if_chain::if_chain;
30+
use matches::matches;
3031
use std::convert::TryFrom;
3132

3233
macro_rules! unwrap_or_continue {
@@ -126,7 +127,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
126127
// _1 in MIR `{ _2 = &_1; clone(move _2); }` or `{ _2 = _1; to_path_buf(_2); } (from_deref)
127128
// In case of `from_deref`, `arg` is already a reference since it is `deref`ed in the previous
128129
// block.
129-
let cloned = unwrap_or_continue!(find_stmt_assigns_to(arg, from_borrow, bbdata.statements.iter().rev()));
130+
let (cloned, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(
131+
cx,
132+
mir,
133+
arg,
134+
from_borrow,
135+
bbdata.statements.iter()
136+
));
137+
138+
if from_borrow && cannot_move_out {
139+
continue;
140+
}
130141

131142
// _1 in MIR `{ _2 = &_1; _3 = deref(move _2); } -> { _4 = _3; to_path_buf(move _4); }`
132143
let referent = if from_deref {
@@ -150,7 +161,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone {
150161
}
151162
};
152163

153-
unwrap_or_continue!(find_stmt_assigns_to(pred_arg, true, mir[ps[0]].statements.iter().rev()))
164+
let (local, cannot_move_out) = unwrap_or_continue!(find_stmt_assigns_to(
165+
cx,
166+
mir,
167+
pred_arg,
168+
true,
169+
mir[ps[0]].statements.iter()
170+
));
171+
if cannot_move_out {
172+
continue;
173+
}
174+
local
154175
} else {
155176
cloned
156177
};
@@ -227,27 +248,69 @@ fn is_call_with_ref_arg<'tcx>(
227248
}
228249
}
229250

230-
/// Finds the first `to = (&)from`, and returns `Some(from)`.
251+
type CannotMoveOut = bool;
252+
253+
/// Finds the first `to = (&)from`, and returns
254+
/// ``Some((from, [`true` if `from` cannot be moved out]))``.
231255
fn find_stmt_assigns_to<'a, 'tcx: 'a>(
256+
cx: &LateContext<'_, 'tcx>,
257+
mir: &mir::Mir<'tcx>,
232258
to: mir::Local,
233259
by_ref: bool,
234-
mut stmts: impl Iterator<Item = &'a mir::Statement<'tcx>>,
235-
) -> Option<mir::Local> {
236-
stmts.find_map(|stmt| {
237-
if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind {
238-
if *local == to {
239-
if by_ref {
240-
if let mir::Rvalue::Ref(_, _, mir::Place::Local(r)) = **v {
241-
return Some(r);
242-
}
243-
} else if let mir::Rvalue::Use(mir::Operand::Copy(mir::Place::Local(r))) = **v {
244-
return Some(r);
260+
stmts: impl DoubleEndedIterator<Item = &'a mir::Statement<'tcx>>,
261+
) -> Option<(mir::Local, CannotMoveOut)> {
262+
stmts
263+
.rev()
264+
.find_map(|stmt| {
265+
if let mir::StatementKind::Assign(mir::Place::Local(local), v) = &stmt.kind {
266+
if *local == to {
267+
return Some(v);
245268
}
246269
}
247-
}
248270

249-
None
250-
})
271+
None
272+
})
273+
.and_then(|v| {
274+
if by_ref {
275+
if let mir::Rvalue::Ref(_, _, ref place) = **v {
276+
return base_local_and_movability(cx, mir, place);
277+
}
278+
} else if let mir::Rvalue::Use(mir::Operand::Copy(ref place)) = **v {
279+
return base_local_and_movability(cx, mir, place);
280+
}
281+
None
282+
})
283+
}
284+
285+
/// Extracts and returns the undermost base `Local` of given `place`. Returns `place` itself
286+
/// if it is already a `Local`.
287+
///
288+
/// Also reports whether given `place` cannot be moved out.
289+
fn base_local_and_movability<'tcx>(
290+
cx: &LateContext<'_, 'tcx>,
291+
mir: &mir::Mir<'tcx>,
292+
mut place: &mir::Place<'tcx>,
293+
) -> Option<(mir::Local, CannotMoveOut)> {
294+
use rustc::mir::Place::*;
295+
296+
// Dereference. You cannot move things out from a borrowed value.
297+
let mut deref = false;
298+
// Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509.
299+
let mut field = false;
300+
301+
loop {
302+
match place {
303+
Local(local) => return Some((*local, deref || field)),
304+
Projection(proj) => {
305+
place = &proj.base;
306+
deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref);
307+
if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) {
308+
field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).to_ty(cx.tcx));
309+
}
310+
},
311+
_ => return None,
312+
}
313+
}
251314
}
252315

253316
struct LocalUseVisitor {
@@ -279,9 +342,7 @@ impl<'tcx> mir::visit::Visitor<'tcx> for LocalUseVisitor {
279342

280343
fn visit_local(&mut self, local: &mir::Local, ctx: PlaceContext<'tcx>, _: mir::Location) {
281344
match ctx {
282-
PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(NonUseContext::StorageDead) => {
283-
return;
284-
},
345+
PlaceContext::MutatingUse(MutatingUseContext::Drop) | PlaceContext::NonUse(_) => return,
285346
_ => {},
286347
}
287348

0 commit comments

Comments
 (0)