Skip to content

Commit 4a3a249

Browse files
committed
Merge remote-tracking branch 'upstream/master' into sync-from-rust
2 parents 8a18963 + e298c83 commit 4a3a249

Some content is hidden

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

69 files changed

+1215
-276
lines changed

.github/driver.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ unset CARGO_MANIFEST_DIR
2424
# FIXME: How to match the clippy invocation in compile-test.rs?
2525
./target/debug/clippy-driver -Dwarnings -Aunused -Zui-testing --emit metadata --crate-type bin tests/ui/double_neg.rs 2>double_neg.stderr && exit 1
2626
sed -e "s,tests/ui,\$DIR," -e "/= help/d" double_neg.stderr >normalized.stderr
27-
diff normalized.stderr tests/ui/double_neg.stderr
27+
diff -u normalized.stderr tests/ui/double_neg.stderr
2828

2929
# make sure "clippy-driver --rustc --arg" and "rustc --arg" behave the same
3030
SYSROOT=$(rustc --print sysroot)
31-
diff <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
31+
diff -u <(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver --rustc --version --verbose) <(rustc --version --verbose)
3232

3333
echo "fn main() {}" >target/driver_test.rs
3434
# we can't run 2 rustcs on the same file at the same time
3535
CLIPPY=$(LD_LIBRARY_PATH=${SYSROOT}/lib ./target/debug/clippy-driver ./target/driver_test.rs --rustc)
3636
RUSTC=$(rustc ./target/driver_test.rs)
37-
diff <($CLIPPY) <($RUSTC)
37+
diff -u <($CLIPPY) <($RUSTC)
3838

3939
# TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,7 @@ Released 2018-09-13
16651665
[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
16661666
[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
16671667
[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
1668+
[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
16681669
[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
16691670
[`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir
16701671
[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
@@ -1802,6 +1803,7 @@ Released 2018-09-13
18021803
[`manual_unwrap_or`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_unwrap_or
18031804
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names
18041805
[`map_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
1806+
[`map_collect_result_unit`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_collect_result_unit
18051807
[`map_entry`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_entry
18061808
[`map_err_ignore`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_err_ignore
18071809
[`map_flatten`]: https://rust-lang.github.io/rust-clippy/master/index.html#map_flatten

CONTRIBUTING.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,10 @@ To figure out how this syntax structure is encoded in the AST, it is recommended
6363
Usually the lint will end up to be a nested series of matches and ifs, [like so][deep-nesting].
6464
But we can make it nest-less by using [if_chain] macro, [like this][nest-less].
6565

66-
[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an E-easy issue first.
67-
They are mostly classified as [`E-medium`], since they might be somewhat involved code wise,
68-
but not difficult per-se.
66+
[`E-medium`] issues are generally pretty easy too, though it's recommended you work on an [`good first issue`]
67+
first. Sometimes they are only somewhat involved code wise, but not difficult per-se.
68+
Note that [`E-medium`] issues may require some knowledge of Clippy internals or some
69+
debugging to find the actual problem behind the issue.
6970

7071
[`T-middle`] issues can be more involved and require verifying types. The [`ty`] module contains a
7172
lot of methods that are useful, though one of the most useful would be `expr_ty` (gives the type of

clippy_dev/src/ra_setup.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::path::PathBuf;
1111
// code. See https://github.com/rust-analyzer/rust-analyzer/issues/3517 and https://github.com/rust-lang/rust-clippy/issues/5514 for details
1212

1313
pub fn run(rustc_path: Option<&str>) {
14-
// we can unwrap here because the arg is required here
14+
// we can unwrap here because the arg is required by clap
1515
let rustc_path = PathBuf::from(rustc_path.unwrap());
1616
assert!(rustc_path.is_dir(), "path is not a directory");
1717
let rustc_source_basedir = rustc_path.join("compiler");
@@ -49,6 +49,15 @@ fn inject_deps_into_manifest(
4949
cargo_toml: &str,
5050
lib_rs: &str,
5151
) -> std::io::Result<()> {
52+
// do not inject deps if we have aleady done so
53+
if cargo_toml.contains("[target.'cfg(NOT_A_PLATFORM)'.dependencies]") {
54+
eprintln!(
55+
"cargo dev ra-setup: warning: deps already found inside {}, doing nothing.",
56+
manifest_path
57+
);
58+
return Ok(());
59+
}
60+
5261
let extern_crates = lib_rs
5362
.lines()
5463
// get the deps

clippy_lints/src/arithmetic.rs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,28 @@ impl<'tcx> LateLintPass<'tcx> for Arithmetic {
8888

8989
let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
9090
if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
91-
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
92-
self.expr_span = Some(expr.span);
93-
} else if l_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
91+
match op.node {
92+
hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
93+
hir::ExprKind::Lit(_lit) => (),
94+
hir::ExprKind::Unary(hir::UnOp::UnNeg, expr) => {
95+
if let hir::ExprKind::Lit(lit) = &expr.kind {
96+
if let rustc_ast::ast::LitKind::Int(1, _) = lit.node {
97+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
98+
self.expr_span = Some(expr.span);
99+
}
100+
}
101+
},
102+
_ => {
103+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
104+
self.expr_span = Some(expr.span);
105+
},
106+
},
107+
_ => {
108+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
109+
self.expr_span = Some(expr.span);
110+
},
111+
}
112+
} else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
94113
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
95114
self.expr_span = Some(expr.span);
96115
}

clippy_lints/src/future_not_send.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,13 +92,8 @@ impl<'tcx> LateLintPass<'tcx> for FutureNotSend {
9292
|db| {
9393
cx.tcx.infer_ctxt().enter(|infcx| {
9494
for FulfillmentError { obligation, .. } in send_errors {
95-
infcx.maybe_note_obligation_cause_for_async_await(
96-
db,
97-
&obligation,
98-
);
99-
if let Trait(trait_pred, _) =
100-
obligation.predicate.skip_binders()
101-
{
95+
infcx.maybe_note_obligation_cause_for_async_await(db, &obligation);
96+
if let Trait(trait_pred, _) = obligation.predicate.skip_binders() {
10297
db.note(&format!(
10398
"`{}` doesn't implement `{}`",
10499
trait_pred.self_ty(),

clippy_lints/src/items_after_statements.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
33
use crate::utils::span_lint;
44
use rustc_ast::ast::{Block, ItemKind, StmtKind};
5-
use rustc_lint::{EarlyContext, EarlyLintPass};
5+
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
6+
use rustc_middle::lint::in_external_macro;
67
use rustc_session::{declare_lint_pass, declare_tool_lint};
78

89
declare_clippy_lint! {
@@ -53,7 +54,7 @@ declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]);
5354

5455
impl EarlyLintPass for ItemsAfterStatements {
5556
fn check_block(&mut self, cx: &EarlyContext<'_>, item: &Block) {
56-
if item.span.from_expansion() {
57+
if in_external_macro(cx.sess(), item.span) {
5758
return;
5859
}
5960

@@ -67,7 +68,7 @@ impl EarlyLintPass for ItemsAfterStatements {
6768
// lint on all further items
6869
for stmt in stmts {
6970
if let StmtKind::Item(ref it) = *stmt {
70-
if it.span.from_expansion() {
71+
if in_external_macro(cx.sess(), it.span) {
7172
return;
7273
}
7374
if let ItemKind::MacroDef(..) = it.kind {

clippy_lints/src/len_zero.rs

Lines changed: 76 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,44 @@ declare_clippy_lint! {
6868
"traits or impls with a public `len` method but no corresponding `is_empty` method"
6969
}
7070

71-
declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY]);
71+
declare_clippy_lint! {
72+
/// **What it does:** Checks for comparing to an empty slice such as "" or [],`
73+
/// and suggests using `.is_empty()` where applicable.
74+
///
75+
/// **Why is this bad?** Some structures can answer `.is_empty()` much faster
76+
/// than checking for equality. So it is good to get into the habit of using
77+
/// `.is_empty()`, and having it is cheap.
78+
/// Besides, it makes the intent clearer than a manual comparison in some contexts.
79+
///
80+
/// **Known problems:** None.
81+
///
82+
/// **Example:**
83+
///
84+
/// ```ignore
85+
/// if s == "" {
86+
/// ..
87+
/// }
88+
///
89+
/// if arr == [] {
90+
/// ..
91+
/// }
92+
/// ```
93+
/// Use instead:
94+
/// ```ignore
95+
/// if s.is_empty() {
96+
/// ..
97+
/// }
98+
///
99+
/// if arr.is_empty() {
100+
/// ..
101+
/// }
102+
/// ```
103+
pub COMPARISON_TO_EMPTY,
104+
style,
105+
"checking `x == \"\"` or `x == []` (or similar) when `.is_empty()` could be used instead"
106+
}
107+
108+
declare_lint_pass!(LenZero => [LEN_ZERO, LEN_WITHOUT_IS_EMPTY, COMPARISON_TO_EMPTY]);
72109

73110
impl<'tcx> LateLintPass<'tcx> for LenZero {
74111
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
@@ -221,6 +258,8 @@ fn check_cmp(cx: &LateContext<'_>, span: Span, method: &Expr<'_>, lit: &Expr<'_>
221258
}
222259

223260
check_len(cx, span, method_path.ident.name, args, &lit.node, op, compare_to)
261+
} else {
262+
check_empty_expr(cx, span, method, lit, op)
224263
}
225264
}
226265

@@ -258,6 +297,42 @@ fn check_len(
258297
}
259298
}
260299

300+
fn check_empty_expr(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str) {
301+
if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
302+
let mut applicability = Applicability::MachineApplicable;
303+
span_lint_and_sugg(
304+
cx,
305+
COMPARISON_TO_EMPTY,
306+
span,
307+
"comparison to empty slice",
308+
&format!("using `{}is_empty` is clearer and more explicit", op),
309+
format!(
310+
"{}{}.is_empty()",
311+
op,
312+
snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
313+
),
314+
applicability,
315+
);
316+
}
317+
}
318+
319+
fn is_empty_string(expr: &Expr<'_>) -> bool {
320+
if let ExprKind::Lit(ref lit) = expr.kind {
321+
if let LitKind::Str(lit, _) = lit.node {
322+
let lit = lit.as_str();
323+
return lit == "";
324+
}
325+
}
326+
false
327+
}
328+
329+
fn is_empty_array(expr: &Expr<'_>) -> bool {
330+
if let ExprKind::Array(ref arr) = expr.kind {
331+
return arr.is_empty();
332+
}
333+
false
334+
}
335+
261336
/// Checks if this type has an `is_empty` method.
262337
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
263338
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`.

clippy_lints/src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
615615
&large_const_arrays::LARGE_CONST_ARRAYS,
616616
&large_enum_variant::LARGE_ENUM_VARIANT,
617617
&large_stack_arrays::LARGE_STACK_ARRAYS,
618+
&len_zero::COMPARISON_TO_EMPTY,
618619
&len_zero::LEN_WITHOUT_IS_EMPTY,
619620
&len_zero::LEN_ZERO,
620621
&let_if_seq::USELESS_LET_IF_SEQ,
@@ -702,6 +703,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
702703
&methods::ITER_NTH_ZERO,
703704
&methods::ITER_SKIP_NEXT,
704705
&methods::MANUAL_SATURATING_ARITHMETIC,
706+
&methods::MAP_COLLECT_RESULT_UNIT,
705707
&methods::MAP_FLATTEN,
706708
&methods::MAP_UNWRAP_OR,
707709
&methods::NEW_RET_NO_SELF,
@@ -1366,6 +1368,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
13661368
LintId::of(&int_plus_one::INT_PLUS_ONE),
13671369
LintId::of(&large_const_arrays::LARGE_CONST_ARRAYS),
13681370
LintId::of(&large_enum_variant::LARGE_ENUM_VARIANT),
1371+
LintId::of(&len_zero::COMPARISON_TO_EMPTY),
13691372
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
13701373
LintId::of(&len_zero::LEN_ZERO),
13711374
LintId::of(&let_underscore::LET_UNDERSCORE_LOCK),
@@ -1427,6 +1430,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
14271430
LintId::of(&methods::ITER_NTH_ZERO),
14281431
LintId::of(&methods::ITER_SKIP_NEXT),
14291432
LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
1433+
LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
14301434
LintId::of(&methods::NEW_RET_NO_SELF),
14311435
LintId::of(&methods::OK_EXPECT),
14321436
LintId::of(&methods::OPTION_AS_REF_DEREF),
@@ -1592,6 +1596,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
15921596
LintId::of(&functions::RESULT_UNIT_ERR),
15931597
LintId::of(&if_let_some_result::IF_LET_SOME_RESULT),
15941598
LintId::of(&inherent_to_string::INHERENT_TO_STRING),
1599+
LintId::of(&len_zero::COMPARISON_TO_EMPTY),
15951600
LintId::of(&len_zero::LEN_WITHOUT_IS_EMPTY),
15961601
LintId::of(&len_zero::LEN_ZERO),
15971602
LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING),
@@ -1621,6 +1626,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16211626
LintId::of(&methods::ITER_NTH_ZERO),
16221627
LintId::of(&methods::ITER_SKIP_NEXT),
16231628
LintId::of(&methods::MANUAL_SATURATING_ARITHMETIC),
1629+
LintId::of(&methods::MAP_COLLECT_RESULT_UNIT),
16241630
LintId::of(&methods::NEW_RET_NO_SELF),
16251631
LintId::of(&methods::OK_EXPECT),
16261632
LintId::of(&methods::OPTION_MAP_OR_NONE),

0 commit comments

Comments
 (0)