Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
107 commits
Select commit Hold shift + click to select a range
32e2021
Lint items after statements in macro expansions
achris Oct 15, 2020
de5a6d3
Initial implementation of comparison_to_empty
Urcra Oct 25, 2020
7f7faa1
Move implementation into len_zero.rs
Urcra Oct 25, 2020
4417af8
Revert changes to Cargo.toml file
Urcra Oct 25, 2020
deecfb5
Add description to lint
Urcra Oct 26, 2020
4cf5b5f
Run update lints
Urcra Oct 26, 2020
4532dd9
run cargo fmt
Urcra Oct 26, 2020
45aa3ef
Remove unnecesary format
Urcra Oct 26, 2020
f0cf3bd
Add lint for replacing `.map().collect()` with `.try_for_each()`
HMPerson1 Oct 26, 2020
bab3386
No lint in external macro for `toplevel_ref_arg`
ThibsG Oct 24, 2020
2911d9c
Use better placeholders for some methods lint messages
ThibsG Oct 18, 2020
3fec6f5
Improve some suggestions for `filter_map_next`, `filter_next` and `ma…
ThibsG Oct 19, 2020
2a3ae11
Move fixable `map_unwrap_or` cases to rustfixed test
ThibsG Oct 23, 2020
e2d86b5
Move fixable `filter_next` and `filter_map_next` cases to rustfixed t…
ThibsG Oct 23, 2020
c0dd1f9
Fix tests for `map_unwrap_or*`
ThibsG Oct 26, 2020
213dbf7
clippy_lint: Add 'ref_option_ref'
dvermd Oct 12, 2020
d1baa25
clippy_lint: Add 'ref_option_ref' refactor code
dvermd Oct 13, 2020
469b2fc
clippy_lint: Add 'ref_option_ref' move to check_ty and add type alias…
dvermd Oct 13, 2020
c1f3bab
clippy_lint: Add 'ref_option_ref' remove unused import
dvermd Oct 13, 2020
bdd76a9
clippy_lint: Allow 'ref_option_ref' for 'option_if_let_else'
dvermd Oct 13, 2020
b41b38c
clippy_lint: Refactor 'ref_option_ref'
dvermd Oct 13, 2020
2270ff4
clippy_lint: Add test cases
dvermd Oct 15, 2020
8e26004
Update clippy_lints/src/ref_option_ref.rs doctest
dvermd Oct 19, 2020
1566db7
Update clippy_lints/src/ref_option_ref.rs
dvermd Oct 19, 2020
7fd74c6
clippy_lint: Add Known Problems message
dvermd Oct 19, 2020
db40a07
Update clippy_lints/src/ref_option_ref.rs
dvermd Oct 19, 2020
ffddb66
clippy_lint: run after changing category to pendantic
dvermd Oct 20, 2020
8337c46
Change Applicability to MaybeIncorrect
dvermd Oct 26, 2020
6212950
Explain why 'run-rustfix' is not defined
dvermd Oct 26, 2020
e568a32
fix the error-causing suggestion of 'borrowed_box'
rail-rain Oct 20, 2020
111b902
add manual_ok_or lint
tnielens Oct 27, 2020
8bd1e23
Replace `E-easy` with `good first issue` in `CONTRIBUTING.md`
giraffate Oct 27, 2020
4c58860
Fix suggestion to add unneeded space in `unused_unit`
giraffate Oct 27, 2020
0d6eed1
use diff -u in driver.sh test
matthiaskrgr Oct 28, 2020
4f1240f
Auto merge of #6263 - matthiaskrgr:diff_u, r=ebroto
bors Oct 28, 2020
abd64d7
add a couple of ICE testcases
matthiaskrgr Oct 28, 2020
5041911
Merge commit '645ef505da378b6f810b1567806d1bcc2856395f' into clippyup
ebroto Oct 28, 2020
7f3462a
cargo dev ra-setup: don't inject deps multiple times if we have alrea…
matthiaskrgr Oct 29, 2020
6d5cd6e
Auto merge of #6264 - matthiaskrgr:ra_setup_no_twice, r=llogiq
bors Oct 29, 2020
e97602e
Update existing arithmetic lint and add new tests related to it.
henil Oct 26, 2020
e8de57c
Auto merge of #6212 - ThibsG:MacroTopLevelRefArg, r=flip1995
bors Oct 29, 2020
e3de544
Remove empty lines in doc comment
Urcra Oct 29, 2020
ee9da9a
Auto merge of #6176 - achris:issues/578, r=phansch
bors Oct 29, 2020
e1a2845
Auto merge of #6226 - Urcra:master, r=flip1995
bors Oct 29, 2020
38ec920
Update CONTRIBUTING.md to describe `E-medium` in detail
giraffate Oct 29, 2020
c57d8ae
Auto merge of #6227 - HMPerson1:collect_map, r=phansch
bors Oct 29, 2020
e01d487
Auto merge of #6248 - giraffate:replace_e_easy_with_good_first_issue,…
bors Oct 29, 2020
230d9cb
Update clippy_lints/src/ref_option_ref.rs
dvermd Oct 29, 2020
7b065db
clippy: update reference file to match suggested change
dvermd Oct 29, 2020
d780f61
add manual_ok_or / pr remarks
tnielens Oct 29, 2020
74d8fbb
Auto merge of #6200 - rail-rain:borrowed_box_invalid_sugg, r=phansch
bors Oct 30, 2020
fa79cc4
TypeVisitor: use `ControlFlow` in clippy
LeSeulArtichaut Oct 21, 2020
4a06145
Use `ControlFlow::is{break,continue}`
LeSeulArtichaut Oct 22, 2020
1c8c3d1
Remove implicit `Continue` type
LeSeulArtichaut Oct 25, 2020
fa0a78b
removed lint for division/modulo for literal `0`
henil Oct 30, 2020
0be6544
Auto merge of #6229 - henil:improve-integer-division-lint, r=phansch
bors Oct 30, 2020
9f402c9
Clarify allow/warn/deny. Remove enable/disable.
ClashTheBunny Oct 30, 2020
7387b87
Auto merge of #6197 - ThibsG:ImproveFilterNext, r=ebroto
bors Oct 30, 2020
084b203
Auto merge of #6260 - matthiaskrgr:ices, r=ebroto
bors Oct 30, 2020
2350ee7
single_char_push_str lint using insert_str() on single-char literals …
matthiaskrgr Sep 13, 2020
c6412ae
handle macros returning Strings in single_char_push_str and single_ch…
matthiaskrgr Sep 14, 2020
c1eb8ce
get_hint_if_single_char_arg: fix bug where multi-char letters are not…
matthiaskrgr Sep 24, 2020
d958269
Rename single_char_push_str to single_char_add_str
ebroto Oct 7, 2020
f8ac1f9
Address suggestions in PR review
ebroto Oct 30, 2020
4bbc771
Update Clippy path to `Lint`
Aaron1011 Oct 31, 2020
9d73371
Merge remote-tracking branch 'upstream/master' into rustup
ebroto Oct 31, 2020
2eb248d
Fix formatting
ebroto Oct 31, 2020
a6b3a40
Auto merge of #6277 - ebroto:rustup, r=ebroto
bors Oct 31, 2020
edfa13d
Fix typo in adding_lints.md
dp304 Oct 31, 2020
e298c83
Auto merge of #6276 - dp304:patch-1, r=llogiq
bors Oct 31, 2020
7b203f3
Implement field_reassign_with_default
Oct 31, 2019
8a18963
Auto merge of #75534 - Aaron1011:feature/new-future-breakage, r=pnkfelix
bors Nov 1, 2020
4a3a249
Merge remote-tracking branch 'upstream/master' into sync-from-rust
giraffate Nov 2, 2020
5f97326
Provide diagnostic suggestion in ExprUseVisitor Delegate
null-sleep Nov 1, 2020
c45255b
Auto merge of #6282 - giraffate:sync-from-rust, r=ebroto
bors Nov 2, 2020
22cc77a
Use const rustc sym where possible
camsteffen Nov 2, 2020
b2332a7
Change lint to use const sym
camsteffen Nov 2, 2020
3ee9c2e
Auto merge of #6037 - matthiaskrgr:single_char_insert, r=flip1995
bors Nov 3, 2020
315bab0
Add `from_iter_instead_of_collect` lint implementation
pitiK3U Sep 10, 2020
9d6eedf
Run `cargo dev update_lints`
pitiK3U Sep 10, 2020
1b117f4
Add tests for `from_iter_instead_of_collect`
pitiK3U Sep 10, 2020
8a5d78b
Fix `from_iter_instead_of_collect` lint crashing on exprs without pat…
pitiK3U Sep 11, 2020
a856706
Update: stderr message format
pitiK3U Oct 1, 2020
8906040
Improvements from PR feedback
pitiK3U Oct 1, 2020
0ab96ba
Allow lint
pitiK3U Oct 1, 2020
e320dd3
Improve: error message
pitiK3U Oct 1, 2020
854f2ce
Run `cargo dev fmt`
pitiK3U Oct 1, 2020
abdb7ae
Remove backticks
pitiK3U Oct 1, 2020
f359fb8
Improve error message
pitiK3U Oct 1, 2020
52d1ea3
Fix: Don't show lint for types that doesn't implement Iterator
pitiK3U Oct 12, 2020
ddf23d6
Fix: Use `.collect()` instead of `::fromIterator()`
pitiK3U Oct 24, 2020
a2bf404
Auto merge of #6101 - pitiK3U:from_iter_instead_of_collect, r=flip1995
bors Nov 3, 2020
2fe87a8
Auto merge of #6165 - dvermd:ref_option_ref, r=flip1995
bors Nov 3, 2020
225ce5f
Auto merge of #6233 - montrivo:manual_ok_or, r=flip1995
bors Nov 3, 2020
cf2043d
Update wording to avoid code having "lint" metaphor
ClashTheBunny Nov 3, 2020
3a34bc0
Auto merge of #6270 - ClashTheBunny:clarify_allow_deny_enable_disable…
bors Nov 4, 2020
c2cf40c
Auto merge of #6284 - camsteffen:rustc-sym, r=flip1995
bors Nov 4, 2020
6fdbde5
Split the "raw integer bytes" part out of `Scalar`
oli-obk Sep 26, 2020
83edb2f
s/Scalar::Raw/Scalar::Int
oli-obk Nov 1, 2020
834ad5c
Merge remote-tracking branch 'upstream/master' into rustup
ebroto Nov 4, 2020
f5166e8
Run cargo dev fmt
ebroto Nov 4, 2020
62c0d29
Auto merge of #6292 - ebroto:rustup, r=ebroto
bors Nov 4, 2020
5b52474
Auto merge of #5911 - hegza:issue-568, r=ebroto
bors Nov 4, 2020
0d2f1ae
Auto merge of #6247 - giraffate:fix_suggestion_to_add_space_in_unused…
bors Nov 4, 2020
0c1531a
Auto merge of #78662 - sexxi-goose:add_expr_id_to_delegate, r=nikomat…
bors Nov 4, 2020
b20d4c1
Auto merge of #6296 - flip1995:rustup, r=flip1995
bors Nov 5, 2020
46c714f
Merge commit 'b20d4c155d2fe3a8391f86dcf9a8c49e17188703' into clippyup
flip1995 Nov 5, 2020
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
Prev Previous commit
Next Next commit
Initial implementation of comparison_to_empty
  • Loading branch information
Urcra committed Oct 25, 2020
commit de5a6d3420d9f2f2c4c995e325412e862a9dc583
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1664,6 +1664,7 @@ Released 2018-09-13
[`cognitive_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#cognitive_complexity
[`collapsible_if`]: https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_if
[`comparison_chain`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain
[`comparison_to_empty`]: https://rust-lang.github.io/rust-clippy/master/index.html#comparison_to_empty
[`copy_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#copy_iterator
[`create_dir`]: https://rust-lang.github.io/rust-clippy/master/index.html#create_dir
[`crosspointer_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#crosspointer_transmute
Expand Down
7 changes: 7 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@ path = "src/main.rs"
name = "clippy-driver"
path = "src/driver.rs"

[target.'cfg(NOT_A_PLATFORM)'.dependencies]
rustc_data_structures = { path = "/home/urcra/rust/compiler/rustc_data_structures" }
rustc_driver = { path = "/home/urcra/rust/compiler/rustc_driver" }
rustc_errors = { path = "/home/urcra/rust/compiler/rustc_errors" }
rustc_interface = { path = "/home/urcra/rust/compiler/rustc_interface" }
rustc_middle = { path = "/home/urcra/rust/compiler/rustc_middle" }

[dependencies]
# begin automatic update
clippy_lints = { version = "0.0.212", path = "clippy_lints" }
Expand Down
22 changes: 22 additions & 0 deletions clippy_lints/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,28 @@ license = "MIT OR Apache-2.0"
keywords = ["clippy", "lint", "plugin"]
edition = "2018"

[target.'cfg(NOT_A_PLATFORM)'.dependencies]
rustc_ast = { path = "/home/urcra/rust/compiler/rustc_ast" }
rustc_ast_pretty = { path = "/home/urcra/rust/compiler/rustc_ast_pretty" }
rustc_attr = { path = "/home/urcra/rust/compiler/rustc_attr" }
rustc_data_structures = { path = "/home/urcra/rust/compiler/rustc_data_structures" }
rustc_errors = { path = "/home/urcra/rust/compiler/rustc_errors" }
rustc_hir = { path = "/home/urcra/rust/compiler/rustc_hir" }
rustc_hir_pretty = { path = "/home/urcra/rust/compiler/rustc_hir_pretty" }
rustc_index = { path = "/home/urcra/rust/compiler/rustc_index" }
rustc_infer = { path = "/home/urcra/rust/compiler/rustc_infer" }
rustc_lexer = { path = "/home/urcra/rust/compiler/rustc_lexer" }
rustc_lint = { path = "/home/urcra/rust/compiler/rustc_lint" }
rustc_middle = { path = "/home/urcra/rust/compiler/rustc_middle" }
rustc_mir = { path = "/home/urcra/rust/compiler/rustc_mir" }
rustc_parse = { path = "/home/urcra/rust/compiler/rustc_parse" }
rustc_parse_format = { path = "/home/urcra/rust/compiler/rustc_parse_format" }
rustc_session = { path = "/home/urcra/rust/compiler/rustc_session" }
rustc_span = { path = "/home/urcra/rust/compiler/rustc_span" }
rustc_target = { path = "/home/urcra/rust/compiler/rustc_target" }
rustc_trait_selection = { path = "/home/urcra/rust/compiler/rustc_trait_selection" }
rustc_typeck = { path = "/home/urcra/rust/compiler/rustc_typeck" }

[dependencies]
cargo_metadata = "0.12"
if_chain = "1.0.0"
Expand Down
155 changes: 155 additions & 0 deletions clippy_lints/src/comparison_to_empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
use crate::utils::{snippet_with_applicability, span_lint_and_sugg};
use rustc_ast::ast::LitKind;
use rustc_errors::Applicability;
use rustc_hir::def_id::DefId;
use rustc_hir::{BinOpKind, Expr, ExprKind, ItemKind, TraitItemRef};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{Span, Spanned};

declare_clippy_lint! {
/// **What it does:**
///
/// **Why is this bad?**
///
/// **Known problems:** None.
///
/// **Example:**
///
/// ```rust
/// // example code where clippy issues a warning
/// ```
/// Use instead:
/// ```rust
/// // example code which does not raise clippy warning
/// ```
pub COMPARISON_TO_EMPTY,
style,
"default lint description"
}

declare_lint_pass!(ComparisonToEmpty => [COMPARISON_TO_EMPTY]);

impl LateLintPass<'_> for ComparisonToEmpty {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if expr.span.from_expansion() {
return;
}

if let ExprKind::Binary(Spanned { node: cmp, .. }, ref left, ref right) = expr.kind {
match cmp {
BinOpKind::Eq => {
check_cmp(cx, expr.span, left, right, "", 0); // len == 0
check_cmp(cx, expr.span, right, left, "", 0); // 0 == len
},
BinOpKind::Ne => {
check_cmp(cx, expr.span, left, right, "!", 0); // len != 0
check_cmp(cx, expr.span, right, left, "!", 0); // 0 != len
},
BinOpKind::Gt => {
check_cmp(cx, expr.span, left, right, "!", 0); // len > 0
check_cmp(cx, expr.span, right, left, "", 1); // 1 > len
},
BinOpKind::Lt => {
check_cmp(cx, expr.span, left, right, "", 1); // len < 1
check_cmp(cx, expr.span, right, left, "!", 0); // 0 < len
},
BinOpKind::Ge => check_cmp(cx, expr.span, left, right, "!", 1), // len >= 1
BinOpKind::Le => check_cmp(cx, expr.span, right, left, "!", 1), // 1 <= len
_ => (),
}
}
}

}


fn check_cmp(cx: &LateContext<'_>, span: Span, lit1: &Expr<'_>, lit2: &Expr<'_>, op: &str, compare_to: u32) {
check_empty_expr(cx, span, lit1, lit2, op)
}

fn check_empty_expr(
cx: &LateContext<'_>,
span: Span,
lit1: &Expr<'_>,
lit2: &Expr<'_>,
op: &str
) {
if (is_empty_array(lit2) || is_empty_string(lit2)) && has_is_empty(cx, lit1) {
let mut applicability = Applicability::MachineApplicable;
span_lint_and_sugg(
cx,
COMPARISON_TO_EMPTY,
span,
&format!("comparison to empty slice"),
&format!("using `{}is_empty` is clearer and more explicit", op),
format!(
"{}{}.is_empty()",
op,
snippet_with_applicability(cx, lit1.span, "_", &mut applicability)
),
applicability,
);
}
}

fn is_empty_string(expr: &Expr<'_>) -> bool {
if let ExprKind::Lit(ref lit) = expr.kind {
if let LitKind::Str(lit, _) = lit.node {
let lit = lit.as_str();
return lit == "";
}
}
false
}

fn is_empty_array(expr: &Expr<'_>) -> bool {
if let ExprKind::Array(ref arr) = expr.kind {
return arr.is_empty();
}
false
}


/// Checks if this type has an `is_empty` method.
fn has_is_empty(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
/// Gets an `AssocItem` and return true if it matches `is_empty(self)`.
fn is_is_empty(cx: &LateContext<'_>, item: &ty::AssocItem) -> bool {
if let ty::AssocKind::Fn = item.kind {
if item.ident.name.as_str() == "is_empty" {
let sig = cx.tcx.fn_sig(item.def_id);
let ty = sig.skip_binder();
ty.inputs().len() == 1
} else {
false
}
} else {
false
}
}

/// Checks the inherent impl's items for an `is_empty(self)` method.
fn has_is_empty_impl(cx: &LateContext<'_>, id: DefId) -> bool {
cx.tcx.inherent_impls(id).iter().any(|imp| {
cx.tcx
.associated_items(*imp)
.in_definition_order()
.any(|item| is_is_empty(cx, &item))
})
}

let ty = &cx.typeck_results().expr_ty(expr).peel_refs();
match ty.kind() {
ty::Dynamic(ref tt, ..) => tt.principal().map_or(false, |principal| {
cx.tcx
.associated_items(principal.def_id())
.in_definition_order()
.any(|item| is_is_empty(cx, &item))
}),
ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id),
ty::Adt(id, _) => has_is_empty_impl(cx, id.did),
ty::Array(..) | ty::Slice(..) | ty::Str => true,
_ => false,
}
}
5 changes: 5 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ mod checked_conversions;
mod cognitive_complexity;
mod collapsible_if;
mod comparison_chain;
mod comparison_to_empty;
mod copies;
mod copy_iterator;
mod create_dir;
Expand Down Expand Up @@ -523,6 +524,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&cognitive_complexity::COGNITIVE_COMPLEXITY,
&collapsible_if::COLLAPSIBLE_IF,
&comparison_chain::COMPARISON_CHAIN,
&comparison_to_empty::COMPARISON_TO_EMPTY,
&copies::IFS_SAME_COND,
&copies::IF_SAME_THEN_ELSE,
&copies::MATCH_SAME_ARMS,
Expand Down Expand Up @@ -1139,6 +1141,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
store.register_late_pass(move || box disallowed_method::DisallowedMethod::new(&disallowed_methods));
store.register_early_pass(|| box asm_syntax::InlineAsmX86AttSyntax);
store.register_early_pass(|| box asm_syntax::InlineAsmX86IntelSyntax);
store.register_late_pass(|| box comparison_to_empty::ComparisonToEmpty);


store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
Expand Down Expand Up @@ -1299,6 +1302,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&bytecount::NAIVE_BYTECOUNT),
LintId::of(&collapsible_if::COLLAPSIBLE_IF),
LintId::of(&comparison_chain::COMPARISON_CHAIN),
LintId::of(&comparison_to_empty::COMPARISON_TO_EMPTY),
LintId::of(&copies::IFS_SAME_COND),
LintId::of(&copies::IF_SAME_THEN_ELSE),
LintId::of(&derive::DERIVE_HASH_XOR_EQ),
Expand Down Expand Up @@ -1555,6 +1559,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&blocks_in_if_conditions::BLOCKS_IN_IF_CONDITIONS),
LintId::of(&collapsible_if::COLLAPSIBLE_IF),
LintId::of(&comparison_chain::COMPARISON_CHAIN),
LintId::of(&comparison_to_empty::COMPARISON_TO_EMPTY),
LintId::of(&doc::MISSING_SAFETY_DOC),
LintId::of(&doc::NEEDLESS_DOCTEST_MAIN),
LintId::of(&enum_variants::ENUM_VARIANT_NAMES),
Expand Down
7 changes: 7 additions & 0 deletions src/lintlist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,13 @@ vec![
deprecation: None,
module: "comparison_chain",
},
Lint {
name: "comparison_to_empty",
group: "style",
desc: "default lint description",
deprecation: None,
module: "comparison_to_empty",
},
Lint {
name: "copy_iterator",
group: "pedantic",
Expand Down
23 changes: 23 additions & 0 deletions tests/ui/comparison_to_empty.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// run-rustfix

#![warn(clippy::comparison_to_empty)]

fn main() {
// Disallow comparisons to empty
let s = String::new();
let _ = s.is_empty();
let _ = !s.is_empty();

let v = vec![0];
let _ = v.is_empty();
let _ = !v.is_empty();

// Allow comparisons to non-empty
let s = String::new();
let _ = s == " ";
let _ = s != " ";

let v = vec![0];
let _ = v == [0];
let _ = v != [0];
}
23 changes: 23 additions & 0 deletions tests/ui/comparison_to_empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// run-rustfix

#![warn(clippy::comparison_to_empty)]

fn main() {
// Disallow comparisons to empty
let s = String::new();
let _ = s == "";
let _ = s != "";

let v = vec![0];
let _ = v == [];
let _ = v != [];

// Allow comparisons to non-empty
let s = String::new();
let _ = s == " ";
let _ = s != " ";

let v = vec![0];
let _ = v == [0];
let _ = v != [0];
}
28 changes: 28 additions & 0 deletions tests/ui/comparison_to_empty.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
error: comparison to empty slice
--> $DIR/comparison_to_empty.rs:8:13
|
LL | let _ = s == "";
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `s.is_empty()`
|
= note: `-D clippy::comparison-to-empty` implied by `-D warnings`

error: comparison to empty slice
--> $DIR/comparison_to_empty.rs:9:13
|
LL | let _ = s != "";
| ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!s.is_empty()`

error: comparison to empty slice
--> $DIR/comparison_to_empty.rs:12:13
|
LL | let _ = v == [];
| ^^^^^^^ help: using `is_empty` is clearer and more explicit: `v.is_empty()`

error: comparison to empty slice
--> $DIR/comparison_to_empty.rs:13:13
|
LL | let _ = v != [];
| ^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!v.is_empty()`

error: aborting due to 4 previous errors