#![feature(inline_const)] #![warn(clippy::const_is_empty)] #![allow(clippy::needless_late_init, unused_must_use)] fn test_literal() { if "".is_empty() { //~^ERROR: this expression always evaluates to true } if "foobar".is_empty() { //~^ERROR: this expression always evaluates to false } } fn test_byte_literal() { if b"".is_empty() { //~^ERROR: this expression always evaluates to true } if b"foobar".is_empty() { //~^ERROR: this expression always evaluates to false } } fn test_no_mut() { let mut empty = ""; if empty.is_empty() { // No lint because it is mutable } } fn test_propagated() { let empty = ""; let non_empty = "foobar"; let empty2 = empty; let non_empty2 = non_empty; if empty2.is_empty() { //~^ERROR: this expression always evaluates to true } if non_empty2.is_empty() { //~^ERROR: this expression always evaluates to false } } const EMPTY_STR: &str = ""; const NON_EMPTY_STR: &str = "foo"; const EMPTY_BSTR: &[u8] = b""; const NON_EMPTY_BSTR: &[u8] = b"foo"; const EMPTY_U8_SLICE: &[u8] = &[]; const NON_EMPTY_U8_SLICE: &[u8] = &[1, 2]; const EMPTY_SLICE: &[u32] = &[]; const NON_EMPTY_SLICE: &[u32] = &[1, 2]; const NON_EMPTY_SLICE_REPEAT: &[u32] = &[1; 2]; const EMPTY_ARRAY: [u32; 0] = []; const EMPTY_ARRAY_REPEAT: [u32; 0] = [1; 0]; const NON_EMPTY_ARRAY: [u32; 2] = [1, 2]; const NON_EMPTY_ARRAY_REPEAT: [u32; 2] = [1; 2]; const EMPTY_REF_ARRAY: &[u32; 0] = &[]; const NON_EMPTY_REF_ARRAY: &[u32; 3] = &[1, 2, 3]; fn test_from_const() { let _ = EMPTY_STR.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = NON_EMPTY_STR.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = EMPTY_BSTR.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = NON_EMPTY_BSTR.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = EMPTY_ARRAY.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = EMPTY_ARRAY_REPEAT.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = EMPTY_U8_SLICE.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = NON_EMPTY_U8_SLICE.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = NON_EMPTY_ARRAY.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = NON_EMPTY_ARRAY_REPEAT.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = EMPTY_REF_ARRAY.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = NON_EMPTY_REF_ARRAY.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = EMPTY_SLICE.is_empty(); //~^ ERROR: this expression always evaluates to true let _ = NON_EMPTY_SLICE.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = NON_EMPTY_SLICE_REPEAT.is_empty(); //~^ ERROR: this expression always evaluates to false } fn main() { let value = "foobar"; let _ = value.is_empty(); //~^ ERROR: this expression always evaluates to false let x = value; let _ = x.is_empty(); //~^ ERROR: this expression always evaluates to false let _ = "".is_empty(); //~^ ERROR: this expression always evaluates to true let _ = b"".is_empty(); //~^ ERROR: this expression always evaluates to true } fn str_from_arg(var: &str) { var.is_empty(); // Do not lint, we know nothiny about var } fn update_str() { let mut value = "duck"; value = "penguin"; let _ = value.is_empty(); // Do not lint since value is mutable } fn macros() { // Content from Macro let file = include_str!("const_is_empty.rs"); let _ = file.is_empty(); // No lint because initializer comes from a macro result let var = env!("PATH"); let _ = var.is_empty(); // No lint because initializer comes from a macro result } fn conditional_value() { let value; if true { value = "hey"; } else { value = "hej"; } let _ = value.is_empty(); // Do not lint, current constant folding is too simple to detect this } fn cfg_conditioned() { #[cfg(test)] let val = ""; #[cfg(not(test))] let val = "foo"; let _ = val.is_empty(); // Do not lint, value depend on a #[cfg(…)] directive } fn not_cfg_conditioned() { let val = ""; #[cfg(not(target_os = "inexistent"))] let _ = val.is_empty(); //~^ ERROR: this expression always evaluates to true } const fn const_rand() -> &'static str { "17" } fn const_expressions() { let _ = const { if true { "1" } else { "2" } }.is_empty(); // Do not lint, we do not recurse into boolean expressions let _ = const_rand().is_empty(); // Do not lint, we do not recurse into functions } fn constant_from_external_crate() { let _ = std::env::consts::EXE_EXTENSION.is_empty(); // Do not lint, `exe_ext` comes from the `std` crate }