diff options
Diffstat (limited to 'tests')
462 files changed, 10962 insertions, 2108 deletions
diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 99a01257a7b..6b6dfd7b81e 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -7,17 +7,19 @@ use askama::filters::Safe; use cargo_metadata::Message; use cargo_metadata::diagnostic::{Applicability, Diagnostic}; use clippy_config::ClippyConfiguration; -use clippy_lints::LintInfo; use clippy_lints::declared_lints::LINTS; use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use declare_clippy_lint::LintInfo; use pulldown_cmark::{Options, Parser, html}; use serde::Deserialize; use test_utils::IS_RUSTC_TEST_SUITE; use ui_test::custom_flags::Flag; use ui_test::custom_flags::edition::Edition; use ui_test::custom_flags::rustfix::RustfixMode; +use ui_test::dependencies::DependencyBuilder; use ui_test::spanned::Spanned; -use ui_test::{Args, CommandBuilder, Config, Match, error_on_output_conflict, status_emitter}; +use ui_test::status_emitter::StatusEmitter; +use ui_test::{Args, CommandBuilder, Config, Match, error_on_output_conflict}; use std::collections::{BTreeMap, HashMap}; use std::env::{self, set_var, var_os}; @@ -27,46 +29,26 @@ use std::path::{Path, PathBuf}; use std::sync::mpsc::{Sender, channel}; use std::{fs, iter, thread}; -// Test dependencies may need an `extern crate` here to ensure that they show up -// in the depinfo file (otherwise cargo thinks they are unused) -extern crate futures; -extern crate if_chain; -extern crate itertools; -extern crate parking_lot; -extern crate quote; -extern crate syn; -extern crate tokio; - mod test_utils; -/// All crates used in UI tests are listed here -static TEST_DEPENDENCIES: &[&str] = &[ - "clippy_config", - "clippy_lints", - "clippy_utils", - "futures", - "if_chain", - "itertools", - "parking_lot", - "quote", - "regex", - "serde_derive", - "serde", - "syn", - "tokio", -]; - -/// Produces a string with an `--extern` flag for all UI test crate -/// dependencies. +/// All crates used in internal UI tests are listed here. +/// We directly re-use these crates from their normal clippy builds, so we don't have them +/// in `clippy_test_devs`. That saves a lot of time but also means they don't work in a stage 1 +/// test in rustc bootstrap. +static INTERNAL_TEST_DEPENDENCIES: &[&str] = &["clippy_config", "clippy_lints", "clippy_utils"]; + +/// Produces a string with an `--extern` flag for all `INTERNAL_TEST_DEPENDENCIES`. /// /// The dependency files are located by parsing the depinfo file for this test /// module. This assumes the `-Z binary-dep-depinfo` flag is enabled. All test /// dependencies must be added to Cargo.toml at the project root. Test /// dependencies that are not *directly* used by this test module require an /// `extern crate` declaration. -fn extern_flags() -> Vec<String> { +fn internal_extern_flags() -> Vec<String> { + let current_exe_path = env::current_exe().unwrap(); + let deps_path = current_exe_path.parent().unwrap(); let current_exe_depinfo = { - let mut path = env::current_exe().unwrap(); + let mut path = current_exe_path.clone(); path.set_extension("d"); fs::read_to_string(path).unwrap() }; @@ -88,15 +70,14 @@ fn extern_flags() -> Vec<String> { Some((name, path_str)) }; if let Some((name, path)) = parse_name_path() - && TEST_DEPENDENCIES.contains(&name) + && INTERNAL_TEST_DEPENDENCIES.contains(&name) { // A dependency may be listed twice if it is available in sysroot, - // and the sysroot dependencies are listed first. As of the writing, - // this only seems to apply to if_chain. + // and the sysroot dependencies are listed first. crates.insert(name, path); } } - let not_found: Vec<&str> = TEST_DEPENDENCIES + let not_found: Vec<&str> = INTERNAL_TEST_DEPENDENCIES .iter() .copied() .filter(|n| !crates.contains_key(n)) @@ -111,6 +92,7 @@ fn extern_flags() -> Vec<String> { crates .into_iter() .map(|(name, path)| format!("--extern={name}={path}")) + .chain([format!("-Ldependency={}", deps_path.display())]) .collect() } @@ -119,7 +101,6 @@ const RUN_INTERNAL_TESTS: bool = cfg!(feature = "internal"); struct TestContext { args: Args, - extern_flags: Vec<String>, diagnostic_collector: Option<DiagnosticCollector>, collector_thread: Option<thread::JoinHandle<()>>, } @@ -134,7 +115,6 @@ impl TestContext { .unzip(); Self { args, - extern_flags: extern_flags(), diagnostic_collector, collector_thread, } @@ -144,8 +124,17 @@ impl TestContext { let target_dir = PathBuf::from(var_os("CARGO_TARGET_DIR").unwrap_or_else(|| "target".into())); let mut config = Config { output_conflict_handling: error_on_output_conflict, + // Pre-fill filters with TESTNAME; will be later extended with `self.args`. filter_files: env::var("TESTNAME") - .map(|filters| filters.split(',').map(str::to_string).collect()) + .map(|filters| { + filters + .split(',') + // Make sure that if TESTNAME is empty we produce the empty list here, + // not a list containing an empty string. + .filter(|s| !s.is_empty()) + .map(str::to_string) + .collect() + }) .unwrap_or_default(), target: None, bless_command: Some(if IS_RUSTC_TEST_SUITE { @@ -158,6 +147,40 @@ impl TestContext { }; let defaults = config.comment_defaults.base(); defaults.set_custom("edition", Edition("2024".into())); + defaults.set_custom( + "dependencies", + DependencyBuilder { + program: { + let mut p = CommandBuilder::cargo(); + // If we run in bootstrap, we need to use the right compiler for building the + // tests -- not the compiler that built clippy, but the compiler that got linked + // into clippy. Just invoking TEST_RUSTC does not work because LD_LIBRARY_PATH + // is set in a way that makes it pick the wrong sysroot. Sadly due to + // <https://github.com/rust-lang/cargo/issues/4423> we cannot use RUSTFLAGS to + // set `--sysroot`, so we need to use bootstrap's rustc wrapper. That wrapper + // however has some staging logic that is hurting us here, so to work around + // that we set both the "real" and "staging" rustc to TEST_RUSTC, including the + // associated library paths. + #[expect( + clippy::option_env_unwrap, + reason = "TEST_RUSTC will ensure that the requested env vars are set during compile time" + )] + if let Some(rustc) = option_env!("TEST_RUSTC") { + let libdir = option_env!("TEST_RUSTC_LIB").unwrap(); + let sysroot = option_env!("TEST_SYSROOT").unwrap(); + p.envs.push(("RUSTC_REAL".into(), Some(rustc.into()))); + p.envs.push(("RUSTC_REAL_LIBDIR".into(), Some(libdir.into()))); + p.envs.push(("RUSTC_SNAPSHOT".into(), Some(rustc.into()))); + p.envs.push(("RUSTC_SNAPSHOT_LIBDIR".into(), Some(libdir.into()))); + p.envs.push(("RUSTC_SYSROOT".into(), Some(sysroot.into()))); + } + p + }, + crate_manifest_path: Path::new("clippy_test_deps").join("Cargo.toml"), + build_std: None, + bless_lockfile: self.args.bless, + }, + ); defaults.exit_status = None.into(); if mandatory_annotations { defaults.require_annotations = Some(Spanned::dummy(true)).into(); @@ -182,12 +205,10 @@ impl TestContext { "-Zui-testing", "-Zdeduplicate-diagnostics=no", "-Dwarnings", - &format!("-Ldependency={}", deps_path.display()), ] .map(OsString::from), ); - config.program.args.extend(self.extern_flags.iter().map(OsString::from)); // Prevent rustc from creating `rustc-ice-*` files the console output is enough. config.program.envs.push(("RUSTC_ICE".into(), Some("0".into()))); @@ -195,6 +216,9 @@ impl TestContext { let dep = format!("-Ldependency={}", Path::new(host_libs).join("deps").display()); config.program.args.push(dep.into()); } + if let Some(sysroot) = option_env!("TEST_SYSROOT") { + config.program.args.push(format!("--sysroot={sysroot}").into()); + } config.program.program = profile_path.join(if cfg!(windows) { "clippy-driver.exe" @@ -217,7 +241,7 @@ fn run_ui(cx: &TestContext) { vec![config], ui_test::default_file_filter, ui_test::default_per_file_config, - status_emitter::Text::from(cx.args.format), + Box::<dyn StatusEmitter>::from(cx.args.format), ) .unwrap(); } @@ -227,13 +251,17 @@ fn run_internal_tests(cx: &TestContext) { return; } let mut config = cx.base_config("ui-internal", true); + config + .program + .args + .extend(internal_extern_flags().iter().map(OsString::from)); config.bless_command = Some("cargo uitest --features internal -- -- --bless".into()); ui_test::run_tests_generic( vec![config], ui_test::default_file_filter, ui_test::default_per_file_config, - status_emitter::Text::from(cx.args.format), + Box::<dyn StatusEmitter>::from(cx.args.format), ) .unwrap(); } @@ -257,7 +285,7 @@ fn run_ui_toml(cx: &TestContext) { .envs .push(("CLIPPY_CONF_DIR".into(), Some(path.parent().unwrap().into()))); }, - status_emitter::Text::from(cx.args.format), + Box::<dyn StatusEmitter>::from(cx.args.format), ) .unwrap(); } @@ -304,7 +332,7 @@ fn run_ui_cargo(cx: &TestContext) { .then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)) }, |_config, _file_contents| {}, - status_emitter::Text::from(cx.args.format), + Box::<dyn StatusEmitter>::from(cx.args.format), ) .unwrap(); } @@ -405,6 +433,7 @@ fn ui_cargo_toml_metadata() { #[derive(Template)] #[template(path = "index_template.html")] struct Renderer<'a> { + count: usize, lints: &'a Vec<LintMetadata>, } @@ -484,7 +513,12 @@ impl DiagnosticCollector { fs::write( "util/gh-pages/index.html", - Renderer { lints: &metadata }.render().unwrap(), + Renderer { + count: LINTS.len(), + lints: &metadata, + } + .render() + .unwrap(), ) .unwrap(); }); @@ -568,10 +602,10 @@ impl LintMetadata { Self { id: name, id_location: Some(lint.location), - group: lint.category_str(), + group: lint.category.name(), level: lint.lint.default_level.as_str(), docs, - version: lint.version.unwrap(), + version: lint.version, applicability, } } diff --git a/tests/config-consistency.rs b/tests/config-consistency.rs new file mode 100644 index 00000000000..9e7ca26c7d4 --- /dev/null +++ b/tests/config-consistency.rs @@ -0,0 +1,30 @@ +#![feature(rustc_private)] + +// This test checks that all lints defined in `clippy_config::conf` in `#[lints]` +// attributes exist as Clippy lints. +// +// This test is a no-op if run as part of the compiler test suite +// and will always succeed. + +use std::collections::HashSet; + +#[test] +fn config_consistency() { + if option_env!("RUSTC_TEST_SUITE").is_some() { + return; + } + + let lint_names: HashSet<String> = clippy_lints::declared_lints::LINTS + .iter() + .map(|lint_info| lint_info.lint.name.strip_prefix("clippy::").unwrap().to_lowercase()) + .collect(); + for conf in clippy_config::get_configuration_metadata() { + for lint in conf.lints { + assert!( + lint_names.contains(*lint), + "Configuration option {} references lint `{lint}` which does not exist", + conf.name + ); + } + } +} diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 4ac2bd53285..389616801fc 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -40,6 +40,7 @@ fn dogfood() { "clippy_lints", "clippy_utils", "clippy_config", + "declare_clippy_lint", "lintcheck", "rustc_tools_util", ] { diff --git a/tests/missing-test-files.rs b/tests/missing-test-files.rs index 565dcd73f58..63f960c92fa 100644 --- a/tests/missing-test-files.rs +++ b/tests/missing-test-files.rs @@ -1,6 +1,6 @@ #![warn(rust_2018_idioms, unused_lifetimes)] #![allow(clippy::assertions_on_constants)] -#![feature(path_file_prefix)] +#![cfg_attr(bootstrap, feature(path_file_prefix))] use std::cmp::Ordering; use std::ffi::OsStr; diff --git a/tests/no-profile-in-cargo-toml.rs b/tests/no-profile-in-cargo-toml.rs new file mode 100644 index 00000000000..2ad9bfb75de --- /dev/null +++ b/tests/no-profile-in-cargo-toml.rs @@ -0,0 +1,34 @@ +// Check that we do not have `profile.*` sections in our `Cargo.toml` files, +// as this causes warnings when run from the compiler repository which includes +// Clippy in a workspace. +// +// Those sections can be put into `.cargo/config.toml` which will be read +// when commands are issued from the top-level Clippy directory, outside of +// a workspace. + +use std::fs::File; +use std::io::{self, BufRead as _}; +use walkdir::WalkDir; + +#[test] +fn no_profile_in_cargo_toml() { + // This check could parse `Cargo.toml` using a TOML deserializer, but in practice + // profile sections would be added at the beginning of a line as `[profile.*]`, so + // keep it fast and simple. + for entry in WalkDir::new(".") + .into_iter() + .filter_map(Result::ok) + .filter(|e| e.file_name().to_str() == Some("Cargo.toml")) + { + for line in io::BufReader::new(File::open(entry.path()).unwrap()) + .lines() + .map(Result::unwrap) + { + if line.starts_with("[profile.") { + eprintln!("Profile section `{line}` found in file `{}`.", entry.path().display()); + eprintln!("Use `.cargo/config.toml` for profiles specific to the standalone Clippy repository."); + panic!("Profile section found in `Cargo.toml`"); + } + } + } +} diff --git a/tests/symbols-used.rs b/tests/symbols-used.rs index bc0456711fb..a1049ba64d5 100644 --- a/tests/symbols-used.rs +++ b/tests/symbols-used.rs @@ -75,7 +75,7 @@ fn all_symbols_are_used() -> Result<()> { for sym in extra { eprintln!(" - {sym}"); } - Err(format!("extra symbols found — remove them {SYM_FILE}"))?; + Err(format!("extra symbols found — remove them from {SYM_FILE}"))?; } Ok(()) } diff --git a/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr index 14a6b5047b1..666b842bf80 100644 --- a/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr +++ b/tests/ui-cargo/cargo_rust_version/fail_file_attr/Cargo.stderr @@ -7,7 +7,7 @@ error: unnecessary structure name repetition note: the lint level is defined here --> src/main.rs:6:9 | -6 | #![deny(clippy::use_self)] + 6 | #![deny(clippy::use_self)] | ^^^^^^^^^^^^^^^^ error: unnecessary structure name repetition diff --git a/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr index b626551e35b..8db52c47ad5 100644 --- a/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr +++ b/tests/ui-cargo/duplicate_mod/fail/Cargo.stderr @@ -14,10 +14,10 @@ error: file is loaded as a module multiple times: `src/b.rs` error: file is loaded as a module multiple times: `src/c.rs` --> src/main.rs:7:1 | -7 | mod c; + 7 | mod c; | ^^^^^^ first loaded here -8 | / #[path = "c.rs"] -9 | | mod c2; + 8 | / #[path = "c.rs"] + 9 | | mod c2; | |_______^ loaded again here 10 | / #[path = "c.rs"] 11 | | mod c3; @@ -44,8 +44,8 @@ error: file is loaded as a module multiple times: `src/from_other_module.rs` | ::: src/other_module/mod.rs:1:1 | -1 | / #[path = "../from_other_module.rs"] -2 | | mod m; + 1 | / #[path = "../from_other_module.rs"] + 2 | | mod m; | |______^ loaded again here | = help: replace all but one `mod` item with `use` items diff --git a/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr b/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr index 059427d8ee0..a87339a9a30 100644 --- a/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr +++ b/tests/ui-cargo/lint_groups_priority/fail/Cargo.stderr @@ -1,7 +1,7 @@ error: lint group `rust_2018_idioms` has the same priority (0) as a lint --> Cargo.toml:7:1 | -7 | rust_2018_idioms = "warn" + 7 | rust_2018_idioms = "warn" | ^^^^^^^^^^^^^^^^ ------ has an implicit priority of 0 ... 12 | unused_attributes = { level = "allow" } @@ -11,8 +11,8 @@ error: lint group `rust_2018_idioms` has the same priority (0) as a lint = note: `#[deny(clippy::lint_groups_priority)]` on by default help: to have lints override the group set `rust_2018_idioms` to a lower priority | -7 - rust_2018_idioms = "warn" -7 + rust_2018_idioms = { level = "warn", priority = -1 } + 7 - rust_2018_idioms = "warn" + 7 + rust_2018_idioms = { level = "warn", priority = -1 } | error: lint group `unused` has the same priority (0) as a lint diff --git a/tests/ui-cargo/undocumented_unsafe_blocks/fail/Cargo.stderr b/tests/ui-cargo/undocumented_unsafe_blocks/fail/Cargo.stderr new file mode 100644 index 00000000000..59a7146ac90 --- /dev/null +++ b/tests/ui-cargo/undocumented_unsafe_blocks/fail/Cargo.stderr @@ -0,0 +1,26 @@ +error: module has unnecessary safety comment + --> src/main.rs:2:1 + | +2 | mod x {} + | ^^^^^^^^ + | +help: consider removing the safety comment + --> src/main.rs:1:1 + | +1 | // SAFETY: ... + | ^^^^^^^^^^^^^^ + = note: requested on the command line with `-D clippy::unnecessary-safety-comment` + +error: module has unnecessary safety comment + --> src/main.rs:5:1 + | +5 | mod y {} + | ^^^^^^^^ + | +help: consider removing the safety comment + --> src/main.rs:4:1 + | +4 | // SAFETY: ... + | ^^^^^^^^^^^^^^ + +error: could not compile `undocumented_unsafe_blocks` (bin "undocumented_unsafe_blocks") due to 2 previous errors diff --git a/tests/ui-cargo/undocumented_unsafe_blocks/fail/Cargo.toml b/tests/ui-cargo/undocumented_unsafe_blocks/fail/Cargo.toml new file mode 100644 index 00000000000..36bb3472df0 --- /dev/null +++ b/tests/ui-cargo/undocumented_unsafe_blocks/fail/Cargo.toml @@ -0,0 +1,12 @@ +# Reproducing #14553 requires the `# Safety` comment to be in the first line of +# the file. Since `unnecessary_safety_comment` is not enabled by default, we +# will set it up here. + +[package] +name = "undocumented_unsafe_blocks" +edition = "2024" +publish = false +version = "0.1.0" + +[lints.clippy] +unnecessary_safety_comment = "deny" diff --git a/tests/ui-cargo/undocumented_unsafe_blocks/fail/src/main.rs b/tests/ui-cargo/undocumented_unsafe_blocks/fail/src/main.rs new file mode 100644 index 00000000000..5cafcff99dd --- /dev/null +++ b/tests/ui-cargo/undocumented_unsafe_blocks/fail/src/main.rs @@ -0,0 +1,7 @@ +// SAFETY: ... +mod x {} + +// SAFETY: ... +mod y {} + +fn main() {} diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr index a3c35a31c33..87e4b0c5c7d 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default.stderr @@ -136,13 +136,13 @@ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:5 | LL | const A: bool; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:153:5 | LL | type SomeType; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 @@ -172,13 +172,13 @@ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:189:5 | LL | const A: bool = false; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:5 | LL | type SomeType = (); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 15 previous errors diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr index a3c35a31c33..87e4b0c5c7d 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.default_exp.stderr @@ -136,13 +136,13 @@ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:5 | LL | const A: bool; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:153:5 | LL | type SomeType; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 @@ -172,13 +172,13 @@ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:189:5 | LL | const A: bool = false; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:5 | LL | type SomeType = (); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 15 previous errors diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr index 3fdd706fc62..40505e2a1c4 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.ord_within.stderr @@ -211,13 +211,13 @@ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:155:5 | LL | const A: bool; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:153:5 | LL | type SomeType; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:171:11 @@ -247,13 +247,13 @@ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:189:5 | LL | const A: bool = false; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:187:5 | LL | type SomeType = (); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed.rs:207:11 diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr index 730f12c38a0..d8db2243d41 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.var_1.stderr @@ -28,25 +28,25 @@ error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 | LL | type SomeType = (); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `A` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:117:5 | LL | const A: bool = false; - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of impl items (defined order: [Fn, Type, Const]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:122:5 | LL | fn a() {} - | ^^^^^^^^^ + | ^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:119:5 | LL | type SomeType = (); - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of items (must be alphabetically ordered) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:149:8 @@ -76,13 +76,13 @@ error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:163:5 | LL | type SomeType; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `A` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:161:5 | LL | const A: bool; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: incorrect ordering of trait items (defined order: [Fn, Type, Const]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:166:5 @@ -94,7 +94,7 @@ note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_mixed_var_1.rs:163:5 | LL | type SomeType; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 8 previous errors diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr index 77596ba2394..7f6bddf8005 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.only_impl.stderr @@ -16,25 +16,25 @@ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:46:5 | LL | type SomeType = i8; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `a` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:43:5 | LL | fn a() {} - | ^^^^^^^^^ + | ^^^^^^ error: incorrect ordering of impl items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:49:5 | LL | const A: bool = true; - | ^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_impl.rs:46:5 | LL | type SomeType = i8; - | ^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr index 3d903330be8..a7cff238b78 100644 --- a/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr +++ b/tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.only_trait.stderr @@ -28,13 +28,13 @@ error: incorrect ordering of trait items (defined order: [Const, Type, Fn]) --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:45:5 | LL | const A: bool; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ | note: should be placed before `SomeType` --> tests/ui-toml/arbitrary_source_item_ordering/ordering_only_trait.rs:43:5 | LL | type SomeType; - | ^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr index 8a85d38fba3..608264beb10 100644 --- a/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr +++ b/tests/ui-toml/check_incompatible_msrv_in_tests/check_incompatible_msrv_in_tests.enabled.stderr @@ -18,6 +18,8 @@ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is | LL | sleep(Duration::new(1, 0)); | ^^^^^ + | + = note: you may want to conditionally increase the MSRV considered by Clippy using the `clippy::msrv` attribute error: aborting due to 3 previous errors diff --git a/tests/ui-toml/collapsible_if/collapsible_else_if.fixed b/tests/ui-toml/collapsible_if/collapsible_else_if.fixed new file mode 100644 index 00000000000..0dc0fc230c8 --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_else_if.fixed @@ -0,0 +1,50 @@ +#![allow(clippy::eq_op, clippy::nonminimal_bool)] + +#[rustfmt::skip] +#[warn(clippy::collapsible_if)] +fn main() { + let (x, y) = ("hello", "world"); + + if x == "hello" { + todo!() + } + // Comment must be kept + else if y == "world" { + println!("Hello world!"); + } + //~^^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } // Inner comment + else if y == "world" { + println!("Hello world!"); + } + //~^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } + /* Inner comment */ + else if y == "world" { + println!("Hello world!"); + } + //~^^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } /* Inner comment */ + else if y == "world" { + println!("Hello world!"); + } + //~^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } /* This should not be removed */ /* So does this */ + // Comment must be kept + else if y == "world" { + println!("Hello world!"); + } + //~^^^^^^ collapsible_else_if +} diff --git a/tests/ui-toml/collapsible_if/collapsible_else_if.rs b/tests/ui-toml/collapsible_if/collapsible_else_if.rs new file mode 100644 index 00000000000..8344c122f16 --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_else_if.rs @@ -0,0 +1,55 @@ +#![allow(clippy::eq_op, clippy::nonminimal_bool)] + +#[rustfmt::skip] +#[warn(clippy::collapsible_if)] +fn main() { + let (x, y) = ("hello", "world"); + + if x == "hello" { + todo!() + } else { + // Comment must be kept + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } else { // Inner comment + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } else { + /* Inner comment */ + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } else { /* Inner comment */ + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^ collapsible_else_if + + if x == "hello" { + todo!() + } /* This should not be removed */ else /* So does this */ { + // Comment must be kept + if y == "world" { + println!("Hello world!"); + } + } + //~^^^^^^ collapsible_else_if +} diff --git a/tests/ui-toml/collapsible_if/collapsible_else_if.stderr b/tests/ui-toml/collapsible_if/collapsible_else_if.stderr new file mode 100644 index 00000000000..0ffe5f0a960 --- /dev/null +++ b/tests/ui-toml/collapsible_if/collapsible_else_if.stderr @@ -0,0 +1,105 @@ +error: this `else { if .. }` block can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_else_if.rs:10:12 + | +LL | } else { + | ____________^ +LL | | // Comment must be kept +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::collapsible-else-if` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::collapsible_else_if)]` +help: collapse nested if block + | +LL ~ } +LL | // Comment must be kept +LL ~ else if y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `else { if .. }` block can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_else_if.rs:20:12 + | +LL | } else { // Inner comment + | ____________^ +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ } // Inner comment +LL ~ else if y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `else { if .. }` block can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_else_if.rs:29:12 + | +LL | } else { + | ____________^ +LL | | /* Inner comment */ +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ } +LL | /* Inner comment */ +LL ~ else if y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `else { if .. }` block can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_else_if.rs:39:12 + | +LL | } else { /* Inner comment */ + | ____________^ +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ } /* Inner comment */ +LL ~ else if y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: this `else { if .. }` block can be collapsed + --> tests/ui-toml/collapsible_if/collapsible_else_if.rs:48:64 + | +LL | } /* This should not be removed */ else /* So does this */ { + | ________________________________________________________________^ +LL | | // Comment must be kept +LL | | if y == "world" { +LL | | println!("Hello world!"); +LL | | } +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ } /* This should not be removed */ /* So does this */ +LL | // Comment must be kept +LL ~ else if y == "world" { +LL | println!("Hello world!"); +LL ~ } + | + +error: aborting due to 5 previous errors + diff --git a/tests/ui-toml/enum_variant_size/enum_variant_size.stderr b/tests/ui-toml/enum_variant_size/enum_variant_size.stderr index 020b3cc7878..a5dfd7015a3 100644 --- a/tests/ui-toml/enum_variant_size/enum_variant_size.stderr +++ b/tests/ui-toml/enum_variant_size/enum_variant_size.stderr @@ -12,7 +12,7 @@ LL | | } | = note: `-D clippy::large-enum-variant` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]` -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B([u8; 501]), LL + B(Box<[u8; 501]>), diff --git a/tests/ui-toml/functions_maxlines/test.stderr b/tests/ui-toml/functions_maxlines/test.stderr index 14a49cb76c1..e856963c87d 100644 --- a/tests/ui-toml/functions_maxlines/test.stderr +++ b/tests/ui-toml/functions_maxlines/test.stderr @@ -1,12 +1,8 @@ error: this function has too many lines (2/1) --> tests/ui-toml/functions_maxlines/test.rs:19:1 | -LL | / fn too_many_lines() { -LL | | -LL | | println!("This is bad."); -LL | | println!("This is bad."); -LL | | } - | |_^ +LL | fn too_many_lines() { + | ^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-lines` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_lines)]` @@ -14,35 +10,20 @@ LL | | } error: this function has too many lines (4/1) --> tests/ui-toml/functions_maxlines/test.rs:26:1 | -LL | / async fn async_too_many_lines() { -LL | | -LL | | println!("This is bad."); -LL | | println!("This is bad."); -LL | | } - | |_^ +LL | async fn async_too_many_lines() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many lines (4/1) --> tests/ui-toml/functions_maxlines/test.rs:33:1 | -LL | / fn closure_too_many_lines() { -LL | | -LL | | let _ = { -LL | | println!("This is bad."); -LL | | println!("This is bad."); -LL | | }; -LL | | } - | |_^ +LL | fn closure_too_many_lines() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this function has too many lines (2/1) --> tests/ui-toml/functions_maxlines/test.rs:56:1 | -LL | / fn comment_before_code() { -LL | | -LL | | let _ = "test"; -LL | | /* This comment extends to the front of -LL | | the code but this line should still count. */ let _ = 5; -LL | | } - | |_^ +LL | fn comment_before_code() { + | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index 8a2f201009a..bfc14be5421 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -240,7 +240,7 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: | = help: consider adding a safety comment on the preceding line -error: constant item has unnecessary safety comment +error: constant has unnecessary safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 | LL | const BIG_NUMBER: i32 = 1000000; diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index e9c5e5f9f11..cebfc48a884 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -240,7 +240,7 @@ LL | unsafe impl TrailingComment for () {} // SAFETY: | = help: consider adding a safety comment on the preceding line -error: constant item has unnecessary safety comment +error: constant has unnecessary safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:508:5 | LL | const BIG_NUMBER: i32 = 1000000; @@ -450,5 +450,13 @@ help: consider removing the safety comment LL | // SAFETY: unnecessary_safety_comment triggers here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 52 previous errors +error: unsafe block missing a safety comment + --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:733:12 + | +LL | return unsafe { h() }; + | ^^^^^^^^^^^^^^ + | + = help: consider adding a safety comment on the preceding line + +error: aborting due to 53 previous errors diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs index 91a02bc3d7c..a2d7c1b6c79 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs @@ -723,4 +723,15 @@ fn issue_13039() { _ = unsafe { foo() } } +fn rfl_issue15034() -> i32 { + unsafe fn h() -> i32 { + 1i32 + } + // This shouldn't lint with accept-comment-above-attributes! Thus fixing a false positive! + // SAFETY: My safety comment! + #[allow(clippy::unnecessary_cast)] + return unsafe { h() }; + //~[disabled]^ ERROR: unsafe block missing a safety comment +} + fn main() {} diff --git a/tests/ui-toml/wildcard_imports/wildcard_imports.fixed b/tests/ui-toml/wildcard_imports/wildcard_imports.fixed index 20511cbed16..ec9fbcfd4a3 100644 --- a/tests/ui-toml/wildcard_imports/wildcard_imports.fixed +++ b/tests/ui-toml/wildcard_imports/wildcard_imports.fixed @@ -1,3 +1,4 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs #![warn(clippy::wildcard_imports)] mod prelude { @@ -13,6 +14,10 @@ mod my_crate { pub mod utils { pub fn my_util_fn() {} } + + pub mod utils2 { + pub const SOME_CONST: u32 = 1; + } } pub use utils::{BAR, print}; @@ -22,6 +27,12 @@ use my_crate::utils::my_util_fn; use prelude::FOO; //~^ ERROR: usage of wildcard import +proc_macros::external! { + use my_crate::utils2::*; + + static SOME_STATIC: u32 = SOME_CONST; +} + fn main() { let _ = FOO; let _ = BAR; diff --git a/tests/ui-toml/wildcard_imports/wildcard_imports.rs b/tests/ui-toml/wildcard_imports/wildcard_imports.rs index 8d05910f471..233ee19f89b 100644 --- a/tests/ui-toml/wildcard_imports/wildcard_imports.rs +++ b/tests/ui-toml/wildcard_imports/wildcard_imports.rs @@ -1,3 +1,4 @@ +//@aux-build:../../ui/auxiliary/proc_macros.rs #![warn(clippy::wildcard_imports)] mod prelude { @@ -13,6 +14,10 @@ mod my_crate { pub mod utils { pub fn my_util_fn() {} } + + pub mod utils2 { + pub const SOME_CONST: u32 = 1; + } } pub use utils::*; @@ -22,6 +27,12 @@ use my_crate::utils::*; use prelude::*; //~^ ERROR: usage of wildcard import +proc_macros::external! { + use my_crate::utils2::*; + + static SOME_STATIC: u32 = SOME_CONST; +} + fn main() { let _ = FOO; let _ = BAR; diff --git a/tests/ui-toml/wildcard_imports/wildcard_imports.stderr b/tests/ui-toml/wildcard_imports/wildcard_imports.stderr index 5e624dd6c3c..5d37cb705f5 100644 --- a/tests/ui-toml/wildcard_imports/wildcard_imports.stderr +++ b/tests/ui-toml/wildcard_imports/wildcard_imports.stderr @@ -1,5 +1,5 @@ error: usage of wildcard import - --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:18:9 + --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:23:9 | LL | pub use utils::*; | ^^^^^^^^ help: try: `utils::{BAR, print}` @@ -8,13 +8,13 @@ LL | pub use utils::*; = help: to override `-D warnings` add `#[allow(clippy::wildcard_imports)]` error: usage of wildcard import - --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:20:5 + --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:25:5 | LL | use my_crate::utils::*; | ^^^^^^^^^^^^^^^^^^ help: try: `my_crate::utils::my_util_fn` error: usage of wildcard import - --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:22:5 + --> tests/ui-toml/wildcard_imports/wildcard_imports.rs:27:5 | LL | use prelude::*; | ^^^^^^^^^^ help: try: `prelude::FOO` diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index 6461666be8f..fc493421a16 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -106,4 +106,19 @@ fn main() { //~^ approx_constant let no_tau = 6.3; + + // issue #15194 + #[allow(clippy::excessive_precision)] + let x: f64 = 3.1415926535897932384626433832; + //~^ approx_constant + + #[allow(clippy::excessive_precision)] + let _: f64 = 003.14159265358979311599796346854418516159057617187500; + //~^ approx_constant + + let almost_frac_1_sqrt_2 = 00.70711; + //~^ approx_constant + + let almost_frac_1_sqrt_2 = 00.707_11; + //~^ approx_constant } diff --git a/tests/ui/approx_const.stderr b/tests/ui/approx_const.stderr index f7bda0468cb..32a3517ff2e 100644 --- a/tests/ui/approx_const.stderr +++ b/tests/ui/approx_const.stderr @@ -184,5 +184,37 @@ LL | let almost_tau = 6.28; | = help: consider using the constant directly -error: aborting due to 23 previous errors +error: approximate value of `f{32, 64}::consts::PI` found + --> tests/ui/approx_const.rs:112:18 + | +LL | let x: f64 = 3.1415926535897932384626433832; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using the constant directly + +error: approximate value of `f{32, 64}::consts::PI` found + --> tests/ui/approx_const.rs:116:18 + | +LL | let _: f64 = 003.14159265358979311599796346854418516159057617187500; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider using the constant directly + +error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found + --> tests/ui/approx_const.rs:119:32 + | +LL | let almost_frac_1_sqrt_2 = 00.70711; + | ^^^^^^^^ + | + = help: consider using the constant directly + +error: approximate value of `f{32, 64}::consts::FRAC_1_SQRT_2` found + --> tests/ui/approx_const.rs:122:32 + | +LL | let almost_frac_1_sqrt_2 = 00.707_11; + | ^^^^^^^^^ + | + = help: consider using the constant directly + +error: aborting due to 27 previous errors diff --git a/tests/ui/arc_with_non_send_sync.stderr b/tests/ui/arc_with_non_send_sync.stderr index 5556b0df88c..ce726206b0c 100644 --- a/tests/ui/arc_with_non_send_sync.stderr +++ b/tests/ui/arc_with_non_send_sync.stderr @@ -5,7 +5,7 @@ LL | let _ = Arc::new(RefCell::new(42)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Arc<RefCell<i32>>` is not `Send` and `Sync` as `RefCell<i32>` is not `Sync` - = help: if the `Arc` will not used be across threads replace it with an `Rc` + = help: if the `Arc` will not be used across threads replace it with an `Rc` = help: otherwise make `RefCell<i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex` = note: `-D clippy::arc-with-non-send-sync` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::arc_with_non_send_sync)]` @@ -17,7 +17,7 @@ LL | let _ = Arc::new(mutex.lock().unwrap()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Arc<MutexGuard<'_, i32>>` is not `Send` and `Sync` as `MutexGuard<'_, i32>` is not `Send` - = help: if the `Arc` will not used be across threads replace it with an `Rc` + = help: if the `Arc` will not be used across threads replace it with an `Rc` = help: otherwise make `MutexGuard<'_, i32>` `Send` and `Sync` or consider a wrapper type such as `Mutex` error: usage of an `Arc` that is not `Send` and `Sync` @@ -27,7 +27,7 @@ LL | let _ = Arc::new(&42 as *const i32); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `Arc<*const i32>` is not `Send` and `Sync` as `*const i32` is neither `Send` nor `Sync` - = help: if the `Arc` will not used be across threads replace it with an `Rc` + = help: if the `Arc` will not be used across threads replace it with an `Rc` = help: otherwise make `*const i32` `Send` and `Sync` or consider a wrapper type such as `Mutex` error: aborting due to 3 previous errors diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs index 21be2af201f..3245b2c983e 100644 --- a/tests/ui/arithmetic_side_effects.rs +++ b/tests/ui/arithmetic_side_effects.rs @@ -664,6 +664,20 @@ pub fn issue_12318() { //~^ arithmetic_side_effects } +pub fn issue_15225() { + use core::num::{NonZero, NonZeroU8}; + + let one = const { NonZeroU8::new(1).unwrap() }; + let _ = one.get() - 1; + + let one: NonZero<u8> = const { NonZero::new(1).unwrap() }; + let _ = one.get() - 1; + + type AliasedType = u8; + let one: NonZero<AliasedType> = const { NonZero::new(1).unwrap() }; + let _ = one.get() - 1; +} + pub fn explicit_methods() { use core::ops::Add; let one: i32 = 1; diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr index e15fb612be5..4150493ba94 100644 --- a/tests/ui/arithmetic_side_effects.stderr +++ b/tests/ui/arithmetic_side_effects.stderr @@ -758,13 +758,13 @@ LL | one.sub_assign(1); | ^^^^^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:670:5 + --> tests/ui/arithmetic_side_effects.rs:684:5 | LL | one.add(&one); | ^^^^^^^^^^^^^ error: arithmetic operation that can potentially result in unexpected side-effects - --> tests/ui/arithmetic_side_effects.rs:672:5 + --> tests/ui/arithmetic_side_effects.rs:686:5 | LL | Box::new(one).add(one); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/as_ptr_cast_mut.fixed b/tests/ui/as_ptr_cast_mut.fixed new file mode 100644 index 00000000000..fe9c5dca5ba --- /dev/null +++ b/tests/ui/as_ptr_cast_mut.fixed @@ -0,0 +1,38 @@ +#![allow(unused)] +#![warn(clippy::as_ptr_cast_mut)] +#![allow(clippy::wrong_self_convention, clippy::unnecessary_cast)] + +struct MutPtrWrapper(Vec<u8>); +impl MutPtrWrapper { + fn as_ptr(&mut self) -> *const u8 { + self.0.as_mut_ptr() as *const u8 + } +} + +struct Covariant<T>(*const T); +impl<T> Covariant<T> { + fn as_ptr(self) -> *const T { + self.0 + } +} + +fn main() { + let mut string = String::new(); + let _ = string.as_mut_ptr(); + //~^ as_ptr_cast_mut + + let _ = string.as_ptr() as *const i8; + let _ = string.as_mut_ptr(); + let _ = string.as_mut_ptr() as *mut u8; + let _ = string.as_mut_ptr() as *const u8; + + let nn = std::ptr::NonNull::new(4 as *mut u8).unwrap(); + let _ = nn.as_ptr() as *mut u8; + + let mut wrap = MutPtrWrapper(Vec::new()); + let _ = wrap.as_ptr() as *mut u8; + + let mut local = 4; + let ref_with_write_perm = Covariant(std::ptr::addr_of_mut!(local) as *const _); + let _ = ref_with_write_perm.as_ptr() as *mut u8; +} diff --git a/tests/ui/as_ptr_cast_mut.rs b/tests/ui/as_ptr_cast_mut.rs index baf7279adc4..3f22c2058d0 100644 --- a/tests/ui/as_ptr_cast_mut.rs +++ b/tests/ui/as_ptr_cast_mut.rs @@ -1,7 +1,6 @@ #![allow(unused)] #![warn(clippy::as_ptr_cast_mut)] #![allow(clippy::wrong_self_convention, clippy::unnecessary_cast)] -//@no-rustfix: incorrect suggestion struct MutPtrWrapper(Vec<u8>); impl MutPtrWrapper { @@ -22,9 +21,6 @@ fn main() { let _ = string.as_ptr() as *mut u8; //~^ as_ptr_cast_mut - let _: *mut i8 = string.as_ptr() as *mut _; - //~^ as_ptr_cast_mut - let _ = string.as_ptr() as *const i8; let _ = string.as_mut_ptr(); let _ = string.as_mut_ptr() as *mut u8; diff --git a/tests/ui/as_ptr_cast_mut.stderr b/tests/ui/as_ptr_cast_mut.stderr index b3fc223ccdb..fa9fb23e2d0 100644 --- a/tests/ui/as_ptr_cast_mut.stderr +++ b/tests/ui/as_ptr_cast_mut.stderr @@ -1,5 +1,5 @@ error: casting the result of `as_ptr` to *mut u8 - --> tests/ui/as_ptr_cast_mut.rs:22:13 + --> tests/ui/as_ptr_cast_mut.rs:21:13 | LL | let _ = string.as_ptr() as *mut u8; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()` @@ -7,11 +7,5 @@ LL | let _ = string.as_ptr() as *mut u8; = note: `-D clippy::as-ptr-cast-mut` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::as_ptr_cast_mut)]` -error: casting the result of `as_ptr` to *mut i8 - --> tests/ui/as_ptr_cast_mut.rs:25:22 - | -LL | let _: *mut i8 = string.as_ptr() as *mut _; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/as_ptr_cast_mut_unfixable.rs b/tests/ui/as_ptr_cast_mut_unfixable.rs new file mode 100644 index 00000000000..a8f6b06bd4f --- /dev/null +++ b/tests/ui/as_ptr_cast_mut_unfixable.rs @@ -0,0 +1,16 @@ +//@no-rustfix +#![allow(unused)] +#![warn(clippy::as_ptr_cast_mut)] + +fn main() { + let mut string = String::new(); + + // the `*mut _` is actually necessary since it does two things at once: + // - changes the mutability (caught by the lint) + // - changes the type + // + // and so replacing this with `as_mut_ptr` removes the second thing, + // resulting in a type mismatch + let _: *mut i8 = string.as_ptr() as *mut _; + //~^ as_ptr_cast_mut +} diff --git a/tests/ui/as_ptr_cast_mut_unfixable.stderr b/tests/ui/as_ptr_cast_mut_unfixable.stderr new file mode 100644 index 00000000000..c5bcad6f4df --- /dev/null +++ b/tests/ui/as_ptr_cast_mut_unfixable.stderr @@ -0,0 +1,11 @@ +error: casting the result of `as_ptr` to *mut i8 + --> tests/ui/as_ptr_cast_mut_unfixable.rs:14:22 + | +LL | let _: *mut i8 = string.as_ptr() as *mut _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `string.as_mut_ptr()` + | + = note: `-D clippy::as-ptr-cast-mut` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::as_ptr_cast_mut)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/assign_ops.fixed b/tests/ui/assign_ops.fixed index 3bc6885d7c3..2046d089d6a 100644 --- a/tests/ui/assign_ops.fixed +++ b/tests/ui/assign_ops.fixed @@ -1,8 +1,9 @@ #![allow(clippy::useless_vec)] #![warn(clippy::assign_op_pattern)] -#![feature(const_trait_impl, const_ops)] +#![feature(const_ops)] +#![feature(const_trait_impl)] -use core::num::Wrapping; +use std::num::Wrapping; use std::ops::{Mul, MulAssign}; fn main() { @@ -82,16 +83,28 @@ mod issue14871 { pub trait Number: Copy + Add<Self, Output = Self> + AddAssign { const ZERO: Self; const ONE: Self; + + fn non_constant(value: usize) -> Self { + let mut res = Self::ZERO; + let mut count = 0; + while count < value { + res += Self::ONE; + //~^ assign_op_pattern + count += 1; + //~^ assign_op_pattern + } + res + } } - #[const_trait] - pub trait NumberConstants { + #[rustfmt::skip] // rustfmt doesn't understand the order of pub const on traits (yet) + pub const trait NumberConstants { fn constant(value: usize) -> Self; } impl<T> const NumberConstants for T where - T: Number + ~const core::ops::Add, + T: Number + [const] std::ops::Add, { fn constant(value: usize) -> Self { let mut res = Self::ZERO; @@ -99,8 +112,28 @@ mod issue14871 { while count < value { res = res + Self::ONE; count += 1; + //~^ assign_op_pattern } res } } + + pub struct S; + + impl const std::ops::Add for S { + type Output = S; + fn add(self, _rhs: S) -> S { + S + } + } + + impl const std::ops::AddAssign for S { + fn add_assign(&mut self, rhs: S) {} + } + + const fn do_add() { + let mut s = S; + s += S; + //~^ assign_op_pattern + } } diff --git a/tests/ui/assign_ops.rs b/tests/ui/assign_ops.rs index f1f8f9daff9..f83a40f5547 100644 --- a/tests/ui/assign_ops.rs +++ b/tests/ui/assign_ops.rs @@ -1,8 +1,9 @@ #![allow(clippy::useless_vec)] #![warn(clippy::assign_op_pattern)] -#![feature(const_trait_impl, const_ops)] +#![feature(const_ops)] +#![feature(const_trait_impl)] -use core::num::Wrapping; +use std::num::Wrapping; use std::ops::{Mul, MulAssign}; fn main() { @@ -82,25 +83,57 @@ mod issue14871 { pub trait Number: Copy + Add<Self, Output = Self> + AddAssign { const ZERO: Self; const ONE: Self; + + fn non_constant(value: usize) -> Self { + let mut res = Self::ZERO; + let mut count = 0; + while count < value { + res = res + Self::ONE; + //~^ assign_op_pattern + count = count + 1; + //~^ assign_op_pattern + } + res + } } - #[const_trait] - pub trait NumberConstants { + #[rustfmt::skip] // rustfmt doesn't understand the order of pub const on traits (yet) + pub const trait NumberConstants { fn constant(value: usize) -> Self; } impl<T> const NumberConstants for T where - T: Number + ~const core::ops::Add, + T: Number + [const] std::ops::Add, { fn constant(value: usize) -> Self { let mut res = Self::ZERO; let mut count = 0; while count < value { res = res + Self::ONE; - count += 1; + count = count + 1; + //~^ assign_op_pattern } res } } + + pub struct S; + + impl const std::ops::Add for S { + type Output = S; + fn add(self, _rhs: S) -> S { + S + } + } + + impl const std::ops::AddAssign for S { + fn add_assign(&mut self, rhs: S) {} + } + + const fn do_add() { + let mut s = S; + s = s + S; + //~^ assign_op_pattern + } } diff --git a/tests/ui/assign_ops.stderr b/tests/ui/assign_ops.stderr index c5e698b3ee1..a4fca04893c 100644 --- a/tests/ui/assign_ops.stderr +++ b/tests/ui/assign_ops.stderr @@ -1,5 +1,5 @@ error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:10:5 + --> tests/ui/assign_ops.rs:11:5 | LL | a = a + 1; | ^^^^^^^^^ help: replace it with: `a += 1` @@ -8,70 +8,94 @@ LL | a = a + 1; = help: to override `-D warnings` add `#[allow(clippy::assign_op_pattern)]` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:12:5 + --> tests/ui/assign_ops.rs:13:5 | LL | a = 1 + a; | ^^^^^^^^^ help: replace it with: `a += 1` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:14:5 + --> tests/ui/assign_ops.rs:15:5 | LL | a = a - 1; | ^^^^^^^^^ help: replace it with: `a -= 1` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:16:5 + --> tests/ui/assign_ops.rs:17:5 | LL | a = a * 99; | ^^^^^^^^^^ help: replace it with: `a *= 99` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:18:5 + --> tests/ui/assign_ops.rs:19:5 | LL | a = 42 * a; | ^^^^^^^^^^ help: replace it with: `a *= 42` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:20:5 + --> tests/ui/assign_ops.rs:21:5 | LL | a = a / 2; | ^^^^^^^^^ help: replace it with: `a /= 2` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:22:5 + --> tests/ui/assign_ops.rs:23:5 | LL | a = a % 5; | ^^^^^^^^^ help: replace it with: `a %= 5` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:24:5 + --> tests/ui/assign_ops.rs:25:5 | LL | a = a & 1; | ^^^^^^^^^ help: replace it with: `a &= 1` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:31:5 + --> tests/ui/assign_ops.rs:32:5 | LL | s = s + "bla"; | ^^^^^^^^^^^^^ help: replace it with: `s += "bla"` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:36:5 + --> tests/ui/assign_ops.rs:37:5 | LL | a = a + Wrapping(1u32); | ^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `a += Wrapping(1u32)` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:39:5 + --> tests/ui/assign_ops.rs:40:5 | LL | v[0] = v[0] + v[1]; | ^^^^^^^^^^^^^^^^^^ help: replace it with: `v[0] += v[1]` error: manual implementation of an assign operation - --> tests/ui/assign_ops.rs:52:5 + --> tests/ui/assign_ops.rs:53:5 | LL | buf = buf + cows.clone(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `buf += cows.clone()` -error: aborting due to 12 previous errors +error: manual implementation of an assign operation + --> tests/ui/assign_ops.rs:91:17 + | +LL | res = res + Self::ONE; + | ^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `res += Self::ONE` + +error: manual implementation of an assign operation + --> tests/ui/assign_ops.rs:93:17 + | +LL | count = count + 1; + | ^^^^^^^^^^^^^^^^^ help: replace it with: `count += 1` + +error: manual implementation of an assign operation + --> tests/ui/assign_ops.rs:114:17 + | +LL | count = count + 1; + | ^^^^^^^^^^^^^^^^^ help: replace it with: `count += 1` + +error: manual implementation of an assign operation + --> tests/ui/assign_ops.rs:136:9 + | +LL | s = s + S; + | ^^^^^^^^^ help: replace it with: `s += S` + +error: aborting due to 16 previous errors diff --git a/tests/ui/author/if.stdout b/tests/ui/author/if.stdout index da359866bff..dbff55634ea 100644 --- a/tests/ui/author/if.stdout +++ b/tests/ui/author/if.stdout @@ -1,8 +1,7 @@ if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && let ExprKind::If(cond, then, Some(else_expr)) = init.kind - && let ExprKind::DropTemps(expr) = cond.kind - && let ExprKind::Lit(ref lit) = expr.kind + && let ExprKind::Lit(ref lit) = cond.kind && let LitKind::Bool(true) = lit.node && let ExprKind::Block(block, None) = then.kind && block.stmts.len() == 1 diff --git a/tests/ui/author/macro_in_closure.stdout b/tests/ui/author/macro_in_closure.stdout index 5f8a4ce2363..49595e2fec2 100644 --- a/tests/ui/author/macro_in_closure.stdout +++ b/tests/ui/author/macro_in_closure.stdout @@ -9,28 +9,35 @@ if let StmtKind::Let(local) = stmt.kind && let ExprKind::Call(func, args) = e.kind && paths::STD_IO_STDIO__PRINT.matches_path(cx, func) // Add the path to `clippy_utils::paths` if needed && args.len() == 1 - && let ExprKind::Call(func1, args1) = args[0].kind - && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed - && args1.len() == 2 + && let ExprKind::Block(block1, None) = args[0].kind + && block1.stmts.len() == 1 + && let StmtKind::Let(local1) = block1.stmts[0].kind + && let Some(init1) = local1.init + && let ExprKind::Array(elements) = init1.kind + && elements.len() == 1 + && let ExprKind::Call(func1, args1) = elements[0].kind + && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed + && args1.len() == 1 && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind - && let ExprKind::Array(elements) = inner.kind - && elements.len() == 2 - && let ExprKind::Lit(ref lit) = elements[0].kind + && let PatKind::Binding(BindingMode::NONE, _, name, None) = local1.pat.kind + && name.as_str() == "args" + && let Some(trailing_expr) = block1.expr + && let ExprKind::Call(func2, args2) = trailing_expr.kind + && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed + && args2.len() == 2 + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args2[0].kind + && let ExprKind::Array(elements1) = inner1.kind + && elements1.len() == 2 + && let ExprKind::Lit(ref lit) = elements1[0].kind && let LitKind::Str(s, _) = lit.node && s.as_str() == "" - && let ExprKind::Lit(ref lit1) = elements[1].kind + && let ExprKind::Lit(ref lit1) = elements1[1].kind && let LitKind::Str(s1, _) = lit1.node && s1.as_str() == "\n" - && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind - && let ExprKind::Array(elements1) = inner1.kind - && elements1.len() == 1 - && let ExprKind::Call(func2, args2) = elements1[0].kind - && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed - && args2.len() == 1 - && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[1].kind && block.expr.is_none() - && let PatKind::Binding(BindingMode::NONE, _, name, None) = local.pat.kind - && name.as_str() == "print_text" + && let PatKind::Binding(BindingMode::NONE, _, name1, None) = local.pat.kind + && name1.as_str() == "print_text" { // report your lint here } diff --git a/tests/ui/author/macro_in_loop.stdout b/tests/ui/author/macro_in_loop.stdout index ecc25254311..4fc7b49464d 100644 --- a/tests/ui/author/macro_in_loop.stdout +++ b/tests/ui/author/macro_in_loop.stdout @@ -19,25 +19,32 @@ if let Some(higher::ForLoop { pat: pat, arg: arg, body: body, .. }) = higher::Fo && let ExprKind::Call(func, args) = e1.kind && paths::STD_IO_STDIO__PRINT.matches_path(cx, func) // Add the path to `clippy_utils::paths` if needed && args.len() == 1 - && let ExprKind::Call(func1, args1) = args[0].kind - && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed - && args1.len() == 2 + && let ExprKind::Block(block2, None) = args[0].kind + && block2.stmts.len() == 1 + && let StmtKind::Let(local) = block2.stmts[0].kind + && let Some(init) = local.init + && let ExprKind::Array(elements) = init.kind + && elements.len() == 1 + && let ExprKind::Call(func1, args1) = elements[0].kind + && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func1) // Add the path to `clippy_utils::paths` if needed + && args1.len() == 1 && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner) = args1[0].kind - && let ExprKind::Array(elements) = inner.kind - && elements.len() == 2 - && let ExprKind::Lit(ref lit2) = elements[0].kind + && let PatKind::Binding(BindingMode::NONE, _, name1, None) = local.pat.kind + && name1.as_str() == "args" + && let Some(trailing_expr) = block2.expr + && let ExprKind::Call(func2, args2) = trailing_expr.kind + && paths::CORE_FMT_RT_NEW_V1.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed + && args2.len() == 2 + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args2[0].kind + && let ExprKind::Array(elements1) = inner1.kind + && elements1.len() == 2 + && let ExprKind::Lit(ref lit2) = elements1[0].kind && let LitKind::Str(s, _) = lit2.node && s.as_str() == "" - && let ExprKind::Lit(ref lit3) = elements[1].kind + && let ExprKind::Lit(ref lit3) = elements1[1].kind && let LitKind::Str(s1, _) = lit3.node && s1.as_str() == "\n" - && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner1) = args1[1].kind - && let ExprKind::Array(elements1) = inner1.kind - && elements1.len() == 1 - && let ExprKind::Call(func2, args2) = elements1[0].kind - && paths::CORE_FMT_RT_ARGUMENT_NEW_DISPLAY.matches_path(cx, func2) // Add the path to `clippy_utils::paths` if needed - && args2.len() == 1 - && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[0].kind + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, inner2) = args2[1].kind && block1.expr.is_none() && block.expr.is_none() { diff --git a/tests/ui/author/struct.stdout b/tests/ui/author/struct.stdout index 1e8fbafd30c..2dedab56dce 100644 --- a/tests/ui/author/struct.stdout +++ b/tests/ui/author/struct.stdout @@ -2,8 +2,7 @@ if let ExprKind::Struct(qpath, fields, None) = expr.kind && fields.len() == 1 && fields[0].ident.as_str() == "field" && let ExprKind::If(cond, then, Some(else_expr)) = fields[0].expr.kind - && let ExprKind::DropTemps(expr1) = cond.kind - && let ExprKind::Lit(ref lit) = expr1.kind + && let ExprKind::Lit(ref lit) = cond.kind && let LitKind::Bool(true) = lit.node && let ExprKind::Block(block, None) = then.kind && block.stmts.is_empty() diff --git a/tests/ui/auxiliary/external_item.rs b/tests/ui/auxiliary/external_item.rs index ca4bc369e44..621e18f5c01 100644 --- a/tests/ui/auxiliary/external_item.rs +++ b/tests/ui/auxiliary/external_item.rs @@ -4,4 +4,4 @@ impl _ExternalStruct { pub fn _foo(self) {} } -pub fn _exernal_foo() {} +pub fn _external_foo() {} diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index 5992d15935d..54650922871 100644 --- a/tests/ui/auxiliary/proc_macro_derive.rs +++ b/tests/ui/auxiliary/proc_macro_derive.rs @@ -16,7 +16,7 @@ pub fn derive(_: TokenStream) -> TokenStream { let output = quote! { // Should not trigger `useless_attribute` #[allow(dead_code)] - extern crate rustc_middle; + extern crate core; }; output } diff --git a/tests/ui/bool_assert_comparison.fixed b/tests/ui/bool_assert_comparison.fixed index 721d8b2c2dc..ec76abbef05 100644 --- a/tests/ui/bool_assert_comparison.fixed +++ b/tests/ui/bool_assert_comparison.fixed @@ -1,7 +1,7 @@ #![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)] #![warn(clippy::bool_assert_comparison)] -use std::ops::Not; +use std::ops::{Add, Not}; macro_rules! a { () => { @@ -62,6 +62,14 @@ impl Not for ImplNotTraitWithBool { } } +impl Add for ImplNotTraitWithBool { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + self + } +} + #[derive(Debug)] struct NonCopy; @@ -94,7 +102,7 @@ fn main() { assert_eq!(a!(), "".is_empty()); assert_eq!("".is_empty(), b!()); assert_eq!(a, true); - assert!(b); + assert!(!!b); //~^ bool_assert_comparison assert_ne!("a".len(), 1); @@ -122,7 +130,7 @@ fn main() { debug_assert_eq!(a!(), "".is_empty()); debug_assert_eq!("".is_empty(), b!()); debug_assert_eq!(a, true); - debug_assert!(b); + debug_assert!(!!b); //~^ bool_assert_comparison debug_assert_ne!("a".len(), 1); @@ -167,7 +175,7 @@ fn main() { use debug_assert_eq as renamed; renamed!(a, true); - debug_assert!(b); + debug_assert!(!!b); //~^ bool_assert_comparison let non_copy = NonCopy; @@ -199,4 +207,12 @@ fn main() { //~^ bool_assert_comparison debug_assert!(!"requires negation".is_empty()); //~^ bool_assert_comparison + assert!(!b); + //~^ bool_assert_comparison + assert!(!(!b)); + //~^ bool_assert_comparison + assert!(!!(b + b)); + //~^ bool_assert_comparison + assert!(!(b + b)); + //~^ bool_assert_comparison } diff --git a/tests/ui/bool_assert_comparison.rs b/tests/ui/bool_assert_comparison.rs index 5ab4f475b06..40824a23c82 100644 --- a/tests/ui/bool_assert_comparison.rs +++ b/tests/ui/bool_assert_comparison.rs @@ -1,7 +1,7 @@ #![allow(unused, clippy::assertions_on_constants, clippy::const_is_empty)] #![warn(clippy::bool_assert_comparison)] -use std::ops::Not; +use std::ops::{Add, Not}; macro_rules! a { () => { @@ -62,6 +62,14 @@ impl Not for ImplNotTraitWithBool { } } +impl Add for ImplNotTraitWithBool { + type Output = Self; + + fn add(self, other: Self) -> Self::Output { + self + } +} + #[derive(Debug)] struct NonCopy; @@ -199,4 +207,12 @@ fn main() { //~^ bool_assert_comparison debug_assert_eq!("requires negation".is_empty(), false); //~^ bool_assert_comparison + assert_eq!(!b, true); + //~^ bool_assert_comparison + assert_eq!(!b, false); + //~^ bool_assert_comparison + assert_eq!(b + b, true); + //~^ bool_assert_comparison + assert_eq!(b + b, false); + //~^ bool_assert_comparison } diff --git a/tests/ui/bool_assert_comparison.stderr b/tests/ui/bool_assert_comparison.stderr index a1d0af54361..f823f08f31d 100644 --- a/tests/ui/bool_assert_comparison.stderr +++ b/tests/ui/bool_assert_comparison.stderr @@ -1,5 +1,5 @@ error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:87:5 + --> tests/ui/bool_assert_comparison.rs:95:5 | LL | assert_eq!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + assert!(!"a".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:89:5 + --> tests/ui/bool_assert_comparison.rs:97:5 | LL | assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + assert!("".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:91:5 + --> tests/ui/bool_assert_comparison.rs:99:5 | LL | assert_eq!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + assert!("".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:97:5 + --> tests/ui/bool_assert_comparison.rs:105:5 | LL | assert_eq!(b, true); | ^^^^^^^^^^^^^^^^^^^ @@ -45,11 +45,11 @@ LL | assert_eq!(b, true); help: replace it with `assert!(..)` | LL - assert_eq!(b, true); -LL + assert!(b); +LL + assert!(!!b); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:101:5 + --> tests/ui/bool_assert_comparison.rs:109:5 | LL | assert_ne!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + assert!("a".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:103:5 + --> tests/ui/bool_assert_comparison.rs:111:5 | LL | assert_ne!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + assert!(!"".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:105:5 + --> tests/ui/bool_assert_comparison.rs:113:5 | LL | assert_ne!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + assert!(!"".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:111:5 + --> tests/ui/bool_assert_comparison.rs:119:5 | LL | assert_ne!(b, true); | ^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + assert!(!b); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:115:5 + --> tests/ui/bool_assert_comparison.rs:123:5 | LL | debug_assert_eq!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -109,7 +109,7 @@ LL + debug_assert!(!"a".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:117:5 + --> tests/ui/bool_assert_comparison.rs:125:5 | LL | debug_assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:119:5 + --> tests/ui/bool_assert_comparison.rs:127:5 | LL | debug_assert_eq!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:125:5 + --> tests/ui/bool_assert_comparison.rs:133:5 | LL | debug_assert_eq!(b, true); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -141,11 +141,11 @@ LL | debug_assert_eq!(b, true); help: replace it with `debug_assert!(..)` | LL - debug_assert_eq!(b, true); -LL + debug_assert!(b); +LL + debug_assert!(!!b); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:129:5 + --> tests/ui/bool_assert_comparison.rs:137:5 | LL | debug_assert_ne!("a".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + debug_assert!("a".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:131:5 + --> tests/ui/bool_assert_comparison.rs:139:5 | LL | debug_assert_ne!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + debug_assert!(!"".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:133:5 + --> tests/ui/bool_assert_comparison.rs:141:5 | LL | debug_assert_ne!(true, "".is_empty()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + debug_assert!(!"".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:139:5 + --> tests/ui/bool_assert_comparison.rs:147:5 | LL | debug_assert_ne!(b, true); | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + debug_assert!(!b); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:145:5 + --> tests/ui/bool_assert_comparison.rs:153:5 | LL | assert_eq!("a".is_empty(), false, "tadam {}", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", 1); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:147:5 + --> tests/ui/bool_assert_comparison.rs:155:5 | LL | assert_eq!("a".is_empty(), false, "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:149:5 + --> tests/ui/bool_assert_comparison.rs:157:5 | LL | assert_eq!(false, "a".is_empty(), "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + assert!(!"a".is_empty(), "tadam {}", true); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:155:5 + --> tests/ui/bool_assert_comparison.rs:163:5 | LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -241,7 +241,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", 1); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:157:5 + --> tests/ui/bool_assert_comparison.rs:165:5 | LL | debug_assert_eq!("a".is_empty(), false, "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -253,7 +253,7 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:159:5 + --> tests/ui/bool_assert_comparison.rs:167:5 | LL | debug_assert_eq!(false, "a".is_empty(), "tadam {}", true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -265,31 +265,35 @@ LL + debug_assert!(!"a".is_empty(), "tadam {}", true); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:163:5 + --> tests/ui/bool_assert_comparison.rs:171:5 | LL | assert_eq!(a!(), true); | ^^^^^^^^^^^^^^^^^^^^^^ | help: replace it with `assert!(..)` | -LL - assert_eq!(a!(), true); -LL + assert!(a!()); +LL | true +... +LL | +LL ~ assert!(a!()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:165:5 + --> tests/ui/bool_assert_comparison.rs:173:5 | LL | assert_eq!(true, b!()); | ^^^^^^^^^^^^^^^^^^^^^^ | help: replace it with `assert!(..)` | -LL - assert_eq!(true, b!()); -LL + assert!(b!()); +LL | true +... +LL | +LL ~ assert!(b!()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:170:5 + --> tests/ui/bool_assert_comparison.rs:178:5 | LL | renamed!(b, true); | ^^^^^^^^^^^^^^^^^ @@ -297,11 +301,11 @@ LL | renamed!(b, true); help: replace it with `debug_assert!(..)` | LL - renamed!(b, true); -LL + debug_assert!(b); +LL + debug_assert!(!!b); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:185:5 + --> tests/ui/bool_assert_comparison.rs:193:5 | LL | assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -313,7 +317,7 @@ LL + assert!("".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:187:5 + --> tests/ui/bool_assert_comparison.rs:195:5 | LL | assert_ne!("".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -325,7 +329,7 @@ LL + assert!("".is_empty()); | error: used `assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:189:5 + --> tests/ui/bool_assert_comparison.rs:197:5 | LL | assert_ne!("requires negation".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -337,7 +341,7 @@ LL + assert!(!"requires negation".is_empty()); | error: used `assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:191:5 + --> tests/ui/bool_assert_comparison.rs:199:5 | LL | assert_eq!("requires negation".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -349,7 +353,7 @@ LL + assert!(!"requires negation".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:194:5 + --> tests/ui/bool_assert_comparison.rs:202:5 | LL | debug_assert_eq!("".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -361,7 +365,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:196:5 + --> tests/ui/bool_assert_comparison.rs:204:5 | LL | debug_assert_ne!("".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -373,7 +377,7 @@ LL + debug_assert!("".is_empty()); | error: used `debug_assert_ne!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:198:5 + --> tests/ui/bool_assert_comparison.rs:206:5 | LL | debug_assert_ne!("requires negation".is_empty(), true); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -385,7 +389,7 @@ LL + debug_assert!(!"requires negation".is_empty()); | error: used `debug_assert_eq!` with a literal bool - --> tests/ui/bool_assert_comparison.rs:200:5 + --> tests/ui/bool_assert_comparison.rs:208:5 | LL | debug_assert_eq!("requires negation".is_empty(), false); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -396,5 +400,53 @@ LL - debug_assert_eq!("requires negation".is_empty(), false); LL + debug_assert!(!"requires negation".is_empty()); | -error: aborting due to 33 previous errors +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:210:5 + | +LL | assert_eq!(!b, true); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(!b, true); +LL + assert!(!b); + | + +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:212:5 + | +LL | assert_eq!(!b, false); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(!b, false); +LL + assert!(!(!b)); + | + +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:214:5 + | +LL | assert_eq!(b + b, true); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(b + b, true); +LL + assert!(!!(b + b)); + | + +error: used `assert_eq!` with a literal bool + --> tests/ui/bool_assert_comparison.rs:216:5 + | +LL | assert_eq!(b + b, false); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace it with `assert!(..)` + | +LL - assert_eq!(b + b, false); +LL + assert!(!(b + b)); + | + +error: aborting due to 37 previous errors diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 166abbe549c..b0b60104c0b 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -1,97 +1,41 @@ #![allow(non_local_definitions, clippy::needless_if)] #![warn(clippy::bool_comparison)] -#![allow(clippy::non_canonical_partial_ord_impl, clippy::nonminimal_bool)] +#![allow(clippy::non_canonical_partial_ord_impl)] fn main() { let x = true; - if x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if !x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if !x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if !x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if !x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if !x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if !x { - //~^ bool_comparison - "yes" - } else { - "no" - }; + let _ = if x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if !x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if !x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if !x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if !x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if !x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if !x { "yes" } else { "no" }; + //~^ bool_comparison + let y = true; - if !x & y { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x & !y { - //~^ bool_comparison - "yes" - } else { - "no" - }; + let _ = if !x & y { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x & !y { "yes" } else { "no" }; + //~^ bool_comparison } -#[allow(dead_code)] fn issue3703() { struct Foo; impl PartialEq<bool> for Foo { @@ -127,26 +71,6 @@ fn issue3703() { if false < Foo {} } -#[allow(dead_code)] -fn issue4983() { - let a = true; - let b = false; - - if a != b {}; - //~^ bool_comparison - if a != b {}; - //~^ bool_comparison - if a == b {}; - if !a == !b {}; - - if b != a {}; - //~^ bool_comparison - if b != a {}; - //~^ bool_comparison - if b == a {}; - if !b == !a {}; -} - macro_rules! m { ($func:ident) => { $func() @@ -157,7 +81,6 @@ fn func() -> bool { true } -#[allow(dead_code)] fn issue3973() { // ok, don't lint on `cfg` invocation if false == cfg!(feature = "debugging") {} @@ -196,6 +119,34 @@ fn issue9907() { //~^ bool_comparison // This is not part of the issue, but an unexpected found when fixing the issue, // the provided span was inside of macro rather than the macro callsite. - let _ = ((1 < 2) != m!(func)) as usize; + let _ = ((1 < 2) & !m!(func)) as usize; //~^ bool_comparison } + +#[allow(clippy::nonminimal_bool)] +fn issue15367() { + let a = true; + let b = false; + + // these cases are handled by `nonminimal_bool`, so don't double-lint + if a == !b {}; + if !a == b {}; + if b == !a {}; + if !b == a {}; +} + +fn issue15497() { + fn func() -> bool { + true + } + + fn foo(x: bool) -> bool { + x & !m!(func) + //~^ bool_comparison + } + + fn bar(x: bool) -> bool { + !x & m!(func) + //~^ bool_comparison + } +} diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 7265c2b4c5a..1b1108d6ce5 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -1,97 +1,41 @@ #![allow(non_local_definitions, clippy::needless_if)] #![warn(clippy::bool_comparison)] -#![allow(clippy::non_canonical_partial_ord_impl, clippy::nonminimal_bool)] +#![allow(clippy::non_canonical_partial_ord_impl)] fn main() { let x = true; - if x == true { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x == false { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if true == x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if false == x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x != true { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x != false { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if true != x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if false != x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x < true { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if false < x { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x > false { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if true > x { - //~^ bool_comparison - "yes" - } else { - "no" - }; + let _ = if x == true { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x == false { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if true == x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if false == x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x != true { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x != false { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if true != x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if false != x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x < true { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if false < x { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x > false { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if true > x { "yes" } else { "no" }; + //~^ bool_comparison + let y = true; - if x < y { - //~^ bool_comparison - "yes" - } else { - "no" - }; - if x > y { - //~^ bool_comparison - "yes" - } else { - "no" - }; + let _ = if x < y { "yes" } else { "no" }; + //~^ bool_comparison + let _ = if x > y { "yes" } else { "no" }; + //~^ bool_comparison } -#[allow(dead_code)] fn issue3703() { struct Foo; impl PartialEq<bool> for Foo { @@ -127,26 +71,6 @@ fn issue3703() { if false < Foo {} } -#[allow(dead_code)] -fn issue4983() { - let a = true; - let b = false; - - if a == !b {}; - //~^ bool_comparison - if !a == b {}; - //~^ bool_comparison - if a == b {}; - if !a == !b {}; - - if b == !a {}; - //~^ bool_comparison - if !b == a {}; - //~^ bool_comparison - if b == a {}; - if !b == !a {}; -} - macro_rules! m { ($func:ident) => { $func() @@ -157,7 +81,6 @@ fn func() -> bool { true } -#[allow(dead_code)] fn issue3973() { // ok, don't lint on `cfg` invocation if false == cfg!(feature = "debugging") {} @@ -196,6 +119,34 @@ fn issue9907() { //~^ bool_comparison // This is not part of the issue, but an unexpected found when fixing the issue, // the provided span was inside of macro rather than the macro callsite. - let _ = ((1 < 2) == !m!(func)) as usize; + let _ = ((1 < 2) > m!(func)) as usize; //~^ bool_comparison } + +#[allow(clippy::nonminimal_bool)] +fn issue15367() { + let a = true; + let b = false; + + // these cases are handled by `nonminimal_bool`, so don't double-lint + if a == !b {}; + if !a == b {}; + if b == !a {}; + if !b == a {}; +} + +fn issue15497() { + fn func() -> bool { + true + } + + fn foo(x: bool) -> bool { + x > m!(func) + //~^ bool_comparison + } + + fn bar(x: bool) -> bool { + x < m!(func) + //~^ bool_comparison + } +} diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index ddbb9ff78ed..98881a2d20f 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -1,155 +1,143 @@ error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:7:8 + --> tests/ui/bool_comparison.rs:7:16 | -LL | if x == true { - | ^^^^^^^^^ help: try simplifying it as shown: `x` +LL | let _ = if x == true { "yes" } else { "no" }; + | ^^^^^^^^^ help: try: `x` | = note: `-D clippy::bool-comparison` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:13:8 + --> tests/ui/bool_comparison.rs:9:16 | -LL | if x == false { - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` +LL | let _ = if x == false { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try: `!x` error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:19:8 + --> tests/ui/bool_comparison.rs:11:16 | -LL | if true == x { - | ^^^^^^^^^ help: try simplifying it as shown: `x` +LL | let _ = if true == x { "yes" } else { "no" }; + | ^^^^^^^^^ help: try: `x` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:25:8 + --> tests/ui/bool_comparison.rs:13:16 | -LL | if false == x { - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` +LL | let _ = if false == x { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try: `!x` error: inequality checks against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:31:8 + --> tests/ui/bool_comparison.rs:15:16 | -LL | if x != true { - | ^^^^^^^^^ help: try simplifying it as shown: `!x` +LL | let _ = if x != true { "yes" } else { "no" }; + | ^^^^^^^^^ help: try: `!x` error: inequality checks against false are unnecessary - --> tests/ui/bool_comparison.rs:37:8 + --> tests/ui/bool_comparison.rs:17:16 | -LL | if x != false { - | ^^^^^^^^^^ help: try simplifying it as shown: `x` +LL | let _ = if x != false { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try: `x` error: inequality checks against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:43:8 + --> tests/ui/bool_comparison.rs:19:16 | -LL | if true != x { - | ^^^^^^^^^ help: try simplifying it as shown: `!x` +LL | let _ = if true != x { "yes" } else { "no" }; + | ^^^^^^^^^ help: try: `!x` error: inequality checks against false are unnecessary - --> tests/ui/bool_comparison.rs:49:8 + --> tests/ui/bool_comparison.rs:21:16 | -LL | if false != x { - | ^^^^^^^^^^ help: try simplifying it as shown: `x` +LL | let _ = if false != x { "yes" } else { "no" }; + | ^^^^^^^^^^ help: try: `x` error: less than comparison against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:55:8 + --> tests/ui/bool_comparison.rs:23:16 | -LL | if x < true { - | ^^^^^^^^ help: try simplifying it as shown: `!x` +LL | let _ = if x < true { "yes" } else { "no" }; + | ^^^^^^^^ help: try: `!x` error: greater than checks against false are unnecessary - --> tests/ui/bool_comparison.rs:61:8 + --> tests/ui/bool_comparison.rs:25:16 | -LL | if false < x { - | ^^^^^^^^^ help: try simplifying it as shown: `x` +LL | let _ = if false < x { "yes" } else { "no" }; + | ^^^^^^^^^ help: try: `x` error: greater than checks against false are unnecessary - --> tests/ui/bool_comparison.rs:67:8 + --> tests/ui/bool_comparison.rs:27:16 | -LL | if x > false { - | ^^^^^^^^^ help: try simplifying it as shown: `x` +LL | let _ = if x > false { "yes" } else { "no" }; + | ^^^^^^^^^ help: try: `x` error: less than comparison against true can be replaced by a negation - --> tests/ui/bool_comparison.rs:73:8 + --> tests/ui/bool_comparison.rs:29:16 | -LL | if true > x { - | ^^^^^^^^ help: try simplifying it as shown: `!x` +LL | let _ = if true > x { "yes" } else { "no" }; + | ^^^^^^^^ help: try: `!x` error: order comparisons between booleans can be simplified - --> tests/ui/bool_comparison.rs:80:8 + --> tests/ui/bool_comparison.rs:33:16 | -LL | if x < y { - | ^^^^^ help: try simplifying it as shown: `!x & y` +LL | let _ = if x < y { "yes" } else { "no" }; + | ^^^^^ help: try: `!x & y` error: order comparisons between booleans can be simplified - --> tests/ui/bool_comparison.rs:86:8 + --> tests/ui/bool_comparison.rs:35:16 | -LL | if x > y { - | ^^^^^ help: try simplifying it as shown: `x & !y` - -error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:135:8 - | -LL | if a == !b {}; - | ^^^^^^^ help: try simplifying it as shown: `a != b` - -error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:137:8 - | -LL | if !a == b {}; - | ^^^^^^^ help: try simplifying it as shown: `a != b` - -error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:142:8 - | -LL | if b == !a {}; - | ^^^^^^^ help: try simplifying it as shown: `b != a` - -error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:144:8 - | -LL | if !b == a {}; - | ^^^^^^^ help: try simplifying it as shown: `b != a` +LL | let _ = if x > y { "yes" } else { "no" }; + | ^^^^^ help: try: `x & !y` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:169:8 + --> tests/ui/bool_comparison.rs:92:8 | LL | if false == m!(func) {} - | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` + | ^^^^^^^^^^^^^^^^^ help: try: `!m!(func)` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:171:8 + --> tests/ui/bool_comparison.rs:94:8 | LL | if m!(func) == false {} - | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` + | ^^^^^^^^^^^^^^^^^ help: try: `!m!(func)` error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:173:8 + --> tests/ui/bool_comparison.rs:96:8 | LL | if true == m!(func) {} - | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` + | ^^^^^^^^^^^^^^^^ help: try: `m!(func)` error: equality checks against true are unnecessary - --> tests/ui/bool_comparison.rs:175:8 + --> tests/ui/bool_comparison.rs:98:8 | LL | if m!(func) == true {} - | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `m!(func)` + | ^^^^^^^^^^^^^^^^ help: try: `m!(func)` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:193:14 + --> tests/ui/bool_comparison.rs:116:14 | LL | let _ = ((1 < 2) == false) as usize; - | ^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `1 >= 2` + | ^^^^^^^^^^^^^^^^ help: try: `1 >= 2` error: equality checks against false can be replaced by a negation - --> tests/ui/bool_comparison.rs:195:14 + --> tests/ui/bool_comparison.rs:118:14 | LL | let _ = (false == m!(func)) as usize; - | ^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `!m!(func)` + | ^^^^^^^^^^^^^^^^^ help: try: `!m!(func)` -error: this comparison might be written more concisely - --> tests/ui/bool_comparison.rs:199:14 +error: order comparisons between booleans can be simplified + --> tests/ui/bool_comparison.rs:122:14 + | +LL | let _ = ((1 < 2) > m!(func)) as usize; + | ^^^^^^^^^^^^^^^^^^ help: try: `(1 < 2) & !m!(func)` + +error: order comparisons between booleans can be simplified + --> tests/ui/bool_comparison.rs:144:9 + | +LL | x > m!(func) + | ^^^^^^^^^^^^ help: try: `x & !m!(func)` + +error: order comparisons between booleans can be simplified + --> tests/ui/bool_comparison.rs:149:9 | -LL | let _ = ((1 < 2) == !m!(func)) as usize; - | ^^^^^^^^^^^^^^^^^^^^ help: try simplifying it as shown: `(1 < 2) != m!(func)` +LL | x < m!(func) + | ^^^^^^^^^^^^ help: try: `!x & m!(func)` -error: aborting due to 25 previous errors +error: aborting due to 23 previous errors diff --git a/tests/ui/borrow_as_ptr.fixed b/tests/ui/borrow_as_ptr.fixed index 3ba2eea59f0..bfe826508f3 100644 --- a/tests/ui/borrow_as_ptr.fixed +++ b/tests/ui/borrow_as_ptr.fixed @@ -1,6 +1,9 @@ +//@aux-build:proc_macros.rs #![warn(clippy::borrow_as_ptr)] #![allow(clippy::useless_vec)] +extern crate proc_macros; + fn a() -> i32 { 0 } @@ -47,3 +50,18 @@ fn implicit_cast() { // Do not lint references to temporaries core::ptr::eq(&0i32, &1i32); } + +fn issue_15141() { + let a = String::new(); + // Don't lint cast to dyn trait pointers + let b = &a as *const dyn std::any::Any; +} + +fn issue15389() { + proc_macros::with_span! { + span + let var = 0u32; + // Don't lint in proc-macros + let _ = &var as *const u32; + }; +} diff --git a/tests/ui/borrow_as_ptr.rs b/tests/ui/borrow_as_ptr.rs index 8cdd0512da5..ce248f157c6 100644 --- a/tests/ui/borrow_as_ptr.rs +++ b/tests/ui/borrow_as_ptr.rs @@ -1,6 +1,9 @@ +//@aux-build:proc_macros.rs #![warn(clippy::borrow_as_ptr)] #![allow(clippy::useless_vec)] +extern crate proc_macros; + fn a() -> i32 { 0 } @@ -47,3 +50,18 @@ fn implicit_cast() { // Do not lint references to temporaries core::ptr::eq(&0i32, &1i32); } + +fn issue_15141() { + let a = String::new(); + // Don't lint cast to dyn trait pointers + let b = &a as *const dyn std::any::Any; +} + +fn issue15389() { + proc_macros::with_span! { + span + let var = 0u32; + // Don't lint in proc-macros + let _ = &var as *const u32; + }; +} diff --git a/tests/ui/borrow_as_ptr.stderr b/tests/ui/borrow_as_ptr.stderr index b1fcce49403..b371b477a50 100644 --- a/tests/ui/borrow_as_ptr.stderr +++ b/tests/ui/borrow_as_ptr.stderr @@ -1,5 +1,5 @@ error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:11:14 + --> tests/ui/borrow_as_ptr.rs:14:14 | LL | let _p = &val as *const i32; | ^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of!(val)` @@ -8,25 +8,25 @@ LL | let _p = &val as *const i32; = help: to override `-D warnings` add `#[allow(clippy::borrow_as_ptr)]` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:19:18 + --> tests/ui/borrow_as_ptr.rs:22:18 | LL | let _p_mut = &mut val_mut as *mut i32; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(val_mut)` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:23:16 + --> tests/ui/borrow_as_ptr.rs:26:16 | LL | let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::ptr::addr_of_mut!(x[1])` error: borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:29:17 + --> tests/ui/borrow_as_ptr.rs:32:17 | LL | let _raw = (&mut x[1] as *mut i32).wrapping_offset(-1); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `&raw mut x[1]` error: implicit borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:35:25 + --> tests/ui/borrow_as_ptr.rs:38:25 | LL | let p: *const i32 = &val; | ^^^^ @@ -37,7 +37,7 @@ LL | let p: *const i32 = &raw const val; | +++++++++ error: implicit borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:39:23 + --> tests/ui/borrow_as_ptr.rs:42:23 | LL | let p: *mut i32 = &mut val; | ^^^^^^^^ @@ -48,7 +48,7 @@ LL | let p: *mut i32 = &raw mut val; | +++ error: implicit borrow as raw pointer - --> tests/ui/borrow_as_ptr.rs:44:19 + --> tests/ui/borrow_as_ptr.rs:47:19 | LL | core::ptr::eq(&val, &1); | ^^^^ diff --git a/tests/ui/borrow_deref_ref.fixed b/tests/ui/borrow_deref_ref.fixed index 765dd75fceb..6d06fcc3037 100644 --- a/tests/ui/borrow_deref_ref.fixed +++ b/tests/ui/borrow_deref_ref.fixed @@ -124,3 +124,50 @@ mod issue_11346 { //~^ borrow_deref_ref } } + +fn issue_14934() { + let x: &'static str = "x"; + let y = "y".to_string(); + { + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*x; // Do not lint + *x = &*y; + } + { + let mut x = x; + //~^ borrow_deref_ref + x = &*y; + } + { + #[expect(clippy::toplevel_ref_arg, clippy::needless_borrow)] + let ref x = x; + //~^ borrow_deref_ref + } + { + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = std::convert::identity(x); + //~^ borrow_deref_ref + *x = &*y; + } + { + #[derive(Clone)] + struct S(&'static str); + let s = S("foo"); + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*s.0; // Do not lint + *x = "bar"; + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = s.clone().0; + //~^ borrow_deref_ref + *x = "bar"; + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*std::convert::identity(&s).0; + *x = "bar"; + } + { + let y = &1; + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = { y }; + //~^ borrow_deref_ref + } +} diff --git a/tests/ui/borrow_deref_ref.rs b/tests/ui/borrow_deref_ref.rs index 8ee66bfa881..b43f4c93bf2 100644 --- a/tests/ui/borrow_deref_ref.rs +++ b/tests/ui/borrow_deref_ref.rs @@ -124,3 +124,50 @@ mod issue_11346 { //~^ borrow_deref_ref } } + +fn issue_14934() { + let x: &'static str = "x"; + let y = "y".to_string(); + { + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*x; // Do not lint + *x = &*y; + } + { + let mut x = &*x; + //~^ borrow_deref_ref + x = &*y; + } + { + #[expect(clippy::toplevel_ref_arg, clippy::needless_borrow)] + let ref x = &*x; + //~^ borrow_deref_ref + } + { + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*std::convert::identity(x); + //~^ borrow_deref_ref + *x = &*y; + } + { + #[derive(Clone)] + struct S(&'static str); + let s = S("foo"); + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*s.0; // Do not lint + *x = "bar"; + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*s.clone().0; + //~^ borrow_deref_ref + *x = "bar"; + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = &*std::convert::identity(&s).0; + *x = "bar"; + } + { + let y = &1; + #[expect(clippy::toplevel_ref_arg)] + let ref mut x = { &*y }; + //~^ borrow_deref_ref + } +} diff --git a/tests/ui/borrow_deref_ref.stderr b/tests/ui/borrow_deref_ref.stderr index 3d55da25b9b..3a1f968b4be 100644 --- a/tests/ui/borrow_deref_ref.stderr +++ b/tests/ui/borrow_deref_ref.stderr @@ -25,5 +25,35 @@ error: deref on an immutable reference LL | (&*s).foo(); | ^^^^^ help: if you would like to reborrow, try removing `&*`: `s` -error: aborting due to 4 previous errors +error: deref on an immutable reference + --> tests/ui/borrow_deref_ref.rs:137:21 + | +LL | let mut x = &*x; + | ^^^ help: if you would like to reborrow, try removing `&*`: `x` + +error: deref on an immutable reference + --> tests/ui/borrow_deref_ref.rs:143:21 + | +LL | let ref x = &*x; + | ^^^ help: if you would like to reborrow, try removing `&*`: `x` + +error: deref on an immutable reference + --> tests/ui/borrow_deref_ref.rs:148:25 + | +LL | let ref mut x = &*std::convert::identity(x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `std::convert::identity(x)` + +error: deref on an immutable reference + --> tests/ui/borrow_deref_ref.rs:160:25 + | +LL | let ref mut x = &*s.clone().0; + | ^^^^^^^^^^^^^ help: if you would like to reborrow, try removing `&*`: `s.clone().0` + +error: deref on an immutable reference + --> tests/ui/borrow_deref_ref.rs:170:27 + | +LL | let ref mut x = { &*y }; + | ^^^ help: if you would like to reborrow, try removing `&*`: `y` + +error: aborting due to 9 previous errors diff --git a/tests/ui/borrow_interior_mutable_const.rs b/tests/ui/borrow_interior_mutable_const.rs index 0f439f78915..674450a73ad 100644 --- a/tests/ui/borrow_interior_mutable_const.rs +++ b/tests/ui/borrow_interior_mutable_const.rs @@ -218,4 +218,20 @@ fn main() { let _ = &S::VALUE.1; //~ borrow_interior_mutable_const let _ = &S::VALUE.2; } + { + pub struct Foo<T, const N: usize>(pub Entry<N>, pub T); + + pub struct Entry<const N: usize>(pub Cell<[u32; N]>); + + impl<const N: usize> Entry<N> { + const INIT: Self = Self(Cell::new([42; N])); + } + + impl<T, const N: usize> Foo<T, N> { + pub fn make_foo(v: T) -> Self { + // Used to ICE due to incorrect instantiation. + Foo(Entry::INIT, v) + } + } + } } diff --git a/tests/ui/box_default.fixed b/tests/ui/box_default.fixed index 80000f5de4f..ed00494433b 100644 --- a/tests/ui/box_default.fixed +++ b/tests/ui/box_default.fixed @@ -126,7 +126,7 @@ fn issue_10381() { impl Bar for Foo {} fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> { - if i % 2 == 0 { + if i.is_multiple_of(2) { Some(Box::new(Foo::default())) } else { None diff --git a/tests/ui/box_default.rs b/tests/ui/box_default.rs index 4681016d7cd..801d92f5c29 100644 --- a/tests/ui/box_default.rs +++ b/tests/ui/box_default.rs @@ -126,7 +126,7 @@ fn issue_10381() { impl Bar for Foo {} fn maybe_get_bar(i: u32) -> Option<Box<dyn Bar>> { - if i % 2 == 0 { + if i.is_multiple_of(2) { Some(Box::new(Foo::default())) } else { None diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.rs b/tests/ui/branches_sharing_code/shared_at_bottom.rs index 06472a4f5d5..fa322dc28a7 100644 --- a/tests/ui/branches_sharing_code/shared_at_bottom.rs +++ b/tests/ui/branches_sharing_code/shared_at_bottom.rs @@ -239,3 +239,64 @@ fn fp_if_let_issue7054() { } fn main() {} + +mod issue14873 { + fn foo() -> i32 { + todo!() + } + + macro_rules! qux { + ($a:ident, $b:ident, $condition:expr) => { + if $condition { + "." + } else { + "" + }; + $a = foo(); + $b = foo(); + }; + } + + fn share_on_bottom() { + let mut a = 0; + let mut b = 0; + if false { + qux!(a, b, a == b); + } else { + qux!(a, b, a != b); + }; + + if false { + qux!(a, b, a == b); + let y = 1; + } else { + qux!(a, b, a != b); + let y = 1; + //~^ branches_sharing_code + } + } +} + +fn issue15004() { + let a = 12u32; + let b = 13u32; + let mut c = 8u32; + + let mut result = if b > a { + c += 1; + 0 + } else { + c += 2; + 0 + //~^ branches_sharing_code + }; + + result = if b > a { + c += 1; + 1 + } else { + c += 2; + 1 + //~^ branches_sharing_code + }; +} diff --git a/tests/ui/branches_sharing_code/shared_at_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_bottom.stderr index 648a99c65ed..1c470fb0da5 100644 --- a/tests/ui/branches_sharing_code/shared_at_bottom.stderr +++ b/tests/ui/branches_sharing_code/shared_at_bottom.stderr @@ -157,5 +157,50 @@ LL ~ if x == 17 { b = 1; a = 0x99; } else { } LL + a = 0x99; | -error: aborting due to 9 previous errors +error: all if blocks contain the same code at the end + --> tests/ui/branches_sharing_code/shared_at_bottom.rs:274:9 + | +LL | / let y = 1; +LL | | +LL | | } + | |_________^ + | + = warning: some moved values might need to be renamed to avoid wrong references +help: consider moving these statements after the if + | +LL ~ } +LL + let y = 1; + | + +error: all if blocks contain the same code at the end + --> tests/ui/branches_sharing_code/shared_at_bottom.rs:290:5 + | +LL | / 0 +LL | | +LL | | }; + | |_____^ + | + = note: the end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving these statements after the if + | +LL ~ } +LL ~ 0; + | + +error: all if blocks contain the same code at the end + --> tests/ui/branches_sharing_code/shared_at_bottom.rs:299:5 + | +LL | / 1 +LL | | +LL | | }; + | |_____^ + | + = note: the end suggestion probably needs some adjustments to use the expression result correctly +help: consider moving these statements after the if + | +LL ~ } +LL ~ 1; + | + +error: aborting due to 12 previous errors diff --git a/tests/ui/branches_sharing_code/shared_at_top.rs b/tests/ui/branches_sharing_code/shared_at_top.rs index 694c67d4c85..dcd77679fc6 100644 --- a/tests/ui/branches_sharing_code/shared_at_top.rs +++ b/tests/ui/branches_sharing_code/shared_at_top.rs @@ -124,3 +124,34 @@ fn pf_local_with_inferred_type_issue7053() { } fn main() {} + +mod issue14873 { + fn foo() -> i32 { + todo!() + } + + macro_rules! qux { + ($a:ident, $b:ident, $condition:expr) => { + let $a: i32 = foo(); + let $b: i32 = foo(); + if $condition { "." } else { "" } + }; + } + + fn share_on_top() { + if false { + qux!(a, b, a == b); + } else { + qux!(a, b, a != b); + }; + + if false { + //~^ branches_sharing_code + let x = 1; + qux!(a, b, a == b); + } else { + let x = 1; + qux!(a, b, a != b); + } + } +} diff --git a/tests/ui/branches_sharing_code/shared_at_top.stderr b/tests/ui/branches_sharing_code/shared_at_top.stderr index d28e9c7af29..30efb98b3f5 100644 --- a/tests/ui/branches_sharing_code/shared_at_top.stderr +++ b/tests/ui/branches_sharing_code/shared_at_top.stderr @@ -125,5 +125,20 @@ note: the lint level is defined here LL | #![deny(clippy::branches_sharing_code, clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: all if blocks contain the same code at the start + --> tests/ui/branches_sharing_code/shared_at_top.rs:148:9 + | +LL | / if false { +LL | | +LL | | let x = 1; + | |______________________^ + | + = warning: some moved values might need to be renamed to avoid wrong references +help: consider moving these statements before the if + | +LL ~ let x = 1; +LL + if false { + | + +error: aborting due to 8 previous errors diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs index 75334f70f1f..e848f0601e3 100644 --- a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs +++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs @@ -128,3 +128,42 @@ fn added_note_for_expression_use() -> u32 { } fn main() {} + +mod issue14873 { + fn foo() -> i32 { + todo!() + } + + macro_rules! qux { + ($a:ident, $b:ident, $condition:expr) => { + let mut $a: i32 = foo(); + let mut $b: i32 = foo(); + if $condition { + "." + } else { + "" + }; + $a = foo(); + $b = foo(); + }; + } + + fn share_on_top_and_bottom() { + if false { + qux!(a, b, a == b); + } else { + qux!(a, b, a != b); + }; + + if false { + //~^ branches_sharing_code + let x = 1; + qux!(a, b, a == b); + let y = 1; + } else { + let x = 1; + qux!(a, b, a != b); + let y = 1; + } + } +} diff --git a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr index 2200ab45089..40f3453edb9 100644 --- a/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr +++ b/tests/ui/branches_sharing_code/shared_at_top_and_bottom.stderr @@ -159,5 +159,31 @@ LL ~ } LL + x * 4 | -error: aborting due to 5 previous errors +error: all if blocks contain the same code at both the start and the end + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:158:9 + | +LL | / if false { +LL | | +LL | | let x = 1; + | |______________________^ + | +note: this code is shared at the end + --> tests/ui/branches_sharing_code/shared_at_top_and_bottom.rs:166:9 + | +LL | / let y = 1; +LL | | } + | |_________^ + = warning: some moved values might need to be renamed to avoid wrong references +help: consider moving these statements before the if + | +LL ~ let x = 1; +LL + if false { + | +help: consider moving these statements after the if + | +LL ~ } +LL + let y = 1; + | + +error: aborting due to 6 previous errors diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 5773ffddb91..ef667f5598a 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -1,6 +1,5 @@ //! Test casts for alignment issues -#![feature(rustc_private)] #![feature(core_intrinsics)] #![warn(clippy::cast_ptr_alignment)] #![allow( @@ -10,8 +9,6 @@ clippy::borrow_as_ptr )] -extern crate libc; - fn main() { /* These should be warned against */ diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index 6d9a81f0ecf..ee4c3e9a77e 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,5 +1,5 @@ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes) - --> tests/ui/cast_alignment.rs:19:5 + --> tests/ui/cast_alignment.rs:16:5 | LL | (&1u8 as *const u8) as *const u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,19 +8,19 @@ LL | (&1u8 as *const u8) as *const u16; = help: to override `-D warnings` add `#[allow(clippy::cast_ptr_alignment)]` error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes) - --> tests/ui/cast_alignment.rs:22:5 + --> tests/ui/cast_alignment.rs:19:5 | LL | (&mut 1u8 as *mut u8) as *mut u16; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes) - --> tests/ui/cast_alignment.rs:26:5 + --> tests/ui/cast_alignment.rs:23:5 | LL | (&1u8 as *const u8).cast::<u16>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes) - --> tests/ui/cast_alignment.rs:29:5 + --> tests/ui/cast_alignment.rs:26:5 | LL | (&mut 1u8 as *mut u8).cast::<u16>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/cast_lossless_integer_unfixable.rs b/tests/ui/cast_lossless_integer_unfixable.rs new file mode 100644 index 00000000000..db9cbbb5b66 --- /dev/null +++ b/tests/ui/cast_lossless_integer_unfixable.rs @@ -0,0 +1,17 @@ +//@check-pass +#![warn(clippy::cast_lossless)] + +fn issue15348() { + macro_rules! zero { + ($int:ty) => {{ + let data: [u8; 3] = [0, 0, 0]; + data[0] as $int + }}; + } + + let _ = zero!(u8); + let _ = zero!(u16); + let _ = zero!(u32); + let _ = zero!(u64); + let _ = zero!(u128); +} diff --git a/tests/ui/cast_raw_slice_pointer_cast.fixed b/tests/ui/cast_raw_slice_pointer_cast.fixed index bddcb0ebf64..3c1cf884595 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.fixed +++ b/tests/ui/cast_raw_slice_pointer_cast.fixed @@ -1,30 +1,53 @@ #![warn(clippy::cast_slice_from_raw_parts)] -#[allow(unused_imports, unused_unsafe)] +const fn require_raw_slice_ptr<T>(_: *const [T]) {} + fn main() { let mut vec = vec![0u8; 1]; let ptr: *const u8 = vec.as_ptr(); let mptr = vec.as_mut_ptr(); - let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts(ptr, 1) }; + let _: *const [u8] = unsafe { std::ptr::slice_from_raw_parts(ptr, 1) }; //~^ cast_slice_from_raw_parts - let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts_mut(mptr, 1) }; + let _: *const [u8] = unsafe { std::ptr::slice_from_raw_parts_mut(mptr, 1) }; //~^ cast_slice_from_raw_parts - let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, 1); //~^ cast_slice_from_raw_parts { use core::slice; - let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, 1); //~^ cast_slice_from_raw_parts use slice as one; - let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, 1); //~^ cast_slice_from_raw_parts } { use std::slice; - let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, 1); //~^ cast_slice_from_raw_parts use slice as one; - let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + let _: *const [u8] = std::ptr::slice_from_raw_parts(ptr, 1); //~^ cast_slice_from_raw_parts } + + // implicit cast + { + let _: *const [u8] = unsafe { std::ptr::slice_from_raw_parts(ptr, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { std::ptr::slice_from_raw_parts_mut(mptr, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { std::ptr::slice_from_raw_parts(ptr, 1) }); + //~^ cast_slice_from_raw_parts + } + + // implicit cast in const context + const { + const PTR: *const u8 = std::ptr::null(); + const MPTR: *mut u8 = std::ptr::null_mut(); + let _: *const [u8] = unsafe { std::ptr::slice_from_raw_parts(PTR, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { std::ptr::slice_from_raw_parts_mut(MPTR, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { std::ptr::slice_from_raw_parts(PTR, 1) }); + //~^ cast_slice_from_raw_parts + }; } diff --git a/tests/ui/cast_raw_slice_pointer_cast.rs b/tests/ui/cast_raw_slice_pointer_cast.rs index 0a1eb276d5e..8f57b1f9619 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.rs +++ b/tests/ui/cast_raw_slice_pointer_cast.rs @@ -1,6 +1,7 @@ #![warn(clippy::cast_slice_from_raw_parts)] -#[allow(unused_imports, unused_unsafe)] +const fn require_raw_slice_ptr<T>(_: *const [T]) {} + fn main() { let mut vec = vec![0u8; 1]; let ptr: *const u8 = vec.as_ptr(); @@ -27,4 +28,26 @@ fn main() { let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; //~^ cast_slice_from_raw_parts } + + // implicit cast + { + let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { std::slice::from_raw_parts(ptr, 1) }); + //~^ cast_slice_from_raw_parts + } + + // implicit cast in const context + const { + const PTR: *const u8 = std::ptr::null(); + const MPTR: *mut u8 = std::ptr::null_mut(); + let _: *const [u8] = unsafe { std::slice::from_raw_parts(PTR, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { std::slice::from_raw_parts_mut(MPTR, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { std::slice::from_raw_parts(PTR, 1) }); + //~^ cast_slice_from_raw_parts + }; } diff --git a/tests/ui/cast_raw_slice_pointer_cast.stderr b/tests/ui/cast_raw_slice_pointer_cast.stderr index 60794a988db..328dbafbafe 100644 --- a/tests/ui/cast_raw_slice_pointer_cast.stderr +++ b/tests/ui/cast_raw_slice_pointer_cast.stderr @@ -1,47 +1,83 @@ error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:8:35 + --> tests/ui/cast_raw_slice_pointer_cast.rs:9:35 | LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) as *const [u8] }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts(ptr, 1)` | = note: `-D clippy::cast-slice-from-raw-parts` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::cast_slice_from_raw_parts)]` error: casting the result of `from_raw_parts_mut` to *mut [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:10:35 + --> tests/ui/cast_raw_slice_pointer_cast.rs:11:35 | LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) as *mut [u8] }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts_mut(mptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts_mut(mptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:12:26 + --> tests/ui/cast_raw_slice_pointer_cast.rs:13:26 | LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) } as *const [u8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:16:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:17:30 | LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:19:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:20:30 | LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:24:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:25:30 | LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts(ptr, 1)` error: casting the result of `from_raw_parts` to *const [u8] - --> tests/ui/cast_raw_slice_pointer_cast.rs:27:30 + --> tests/ui/cast_raw_slice_pointer_cast.rs:28:30 | LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `std::ptr::slice_from_raw_parts(ptr, 1)` -error: aborting due to 7 previous errors +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast.rs:34:39 + | +LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(ptr, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `std::ptr::slice_from_raw_parts(ptr, 1)` + +error: implicitly casting the result of `from_raw_parts_mut` to `*mut [u8]` + --> tests/ui/cast_raw_slice_pointer_cast.rs:36:37 + | +LL | let _: *mut [u8] = unsafe { std::slice::from_raw_parts_mut(mptr, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `std::ptr::slice_from_raw_parts_mut(mptr, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast.rs:38:40 + | +LL | require_raw_slice_ptr(unsafe { std::slice::from_raw_parts(ptr, 1) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `std::ptr::slice_from_raw_parts(ptr, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast.rs:46:39 + | +LL | let _: *const [u8] = unsafe { std::slice::from_raw_parts(PTR, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `std::ptr::slice_from_raw_parts(PTR, 1)` + +error: implicitly casting the result of `from_raw_parts_mut` to `*mut [u8]` + --> tests/ui/cast_raw_slice_pointer_cast.rs:48:37 + | +LL | let _: *mut [u8] = unsafe { std::slice::from_raw_parts_mut(MPTR, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `std::ptr::slice_from_raw_parts_mut(MPTR, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast.rs:50:40 + | +LL | require_raw_slice_ptr(unsafe { std::slice::from_raw_parts(PTR, 1) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `std::ptr::slice_from_raw_parts(PTR, 1)` + +error: aborting due to 13 previous errors diff --git a/tests/ui/cast_raw_slice_pointer_cast_no_std.fixed b/tests/ui/cast_raw_slice_pointer_cast_no_std.fixed new file mode 100644 index 00000000000..f71fb8d863c --- /dev/null +++ b/tests/ui/cast_raw_slice_pointer_cast_no_std.fixed @@ -0,0 +1,55 @@ +#![warn(clippy::cast_slice_from_raw_parts)] +#![no_std] +#![crate_type = "lib"] + +const fn require_raw_slice_ptr<T>(_: *const [T]) {} + +fn main() { + let mut arr = [0u8; 1]; + let ptr: *const u8 = arr.as_ptr(); + let mptr = arr.as_mut_ptr(); + let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts(ptr, 1) }; + //~^ cast_slice_from_raw_parts + let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts_mut(mptr, 1) }; + //~^ cast_slice_from_raw_parts + let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts + { + use core::slice; + let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts + use slice as one; + let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts + } + { + use core::slice; + let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts + use slice as one; + let _: *const [u8] = core::ptr::slice_from_raw_parts(ptr, 1); + //~^ cast_slice_from_raw_parts + } + + // implicit cast + { + let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts(ptr, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { core::ptr::slice_from_raw_parts_mut(mptr, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { core::ptr::slice_from_raw_parts(ptr, 1) }); + //~^ cast_slice_from_raw_parts + } + + // implicit cast in const context + const { + const PTR: *const u8 = core::ptr::null(); + const MPTR: *mut u8 = core::ptr::null_mut(); + let _: *const [u8] = unsafe { core::ptr::slice_from_raw_parts(PTR, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { core::ptr::slice_from_raw_parts_mut(MPTR, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { core::ptr::slice_from_raw_parts(PTR, 1) }); + //~^ cast_slice_from_raw_parts + }; +} diff --git a/tests/ui/cast_raw_slice_pointer_cast_no_std.rs b/tests/ui/cast_raw_slice_pointer_cast_no_std.rs new file mode 100644 index 00000000000..743e44c97dc --- /dev/null +++ b/tests/ui/cast_raw_slice_pointer_cast_no_std.rs @@ -0,0 +1,55 @@ +#![warn(clippy::cast_slice_from_raw_parts)] +#![no_std] +#![crate_type = "lib"] + +const fn require_raw_slice_ptr<T>(_: *const [T]) {} + +fn main() { + let mut arr = [0u8; 1]; + let ptr: *const u8 = arr.as_ptr(); + let mptr = arr.as_mut_ptr(); + let _: *const [u8] = unsafe { core::slice::from_raw_parts(ptr, 1) as *const [u8] }; + //~^ cast_slice_from_raw_parts + let _: *const [u8] = unsafe { core::slice::from_raw_parts_mut(mptr, 1) as *mut [u8] }; + //~^ cast_slice_from_raw_parts + let _: *const [u8] = unsafe { core::slice::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts + { + use core::slice; + let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts + use slice as one; + let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts + } + { + use core::slice; + let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts + use slice as one; + let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; + //~^ cast_slice_from_raw_parts + } + + // implicit cast + { + let _: *const [u8] = unsafe { core::slice::from_raw_parts(ptr, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(mptr, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { core::slice::from_raw_parts(ptr, 1) }); + //~^ cast_slice_from_raw_parts + } + + // implicit cast in const context + const { + const PTR: *const u8 = core::ptr::null(); + const MPTR: *mut u8 = core::ptr::null_mut(); + let _: *const [u8] = unsafe { core::slice::from_raw_parts(PTR, 1) }; + //~^ cast_slice_from_raw_parts + let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(MPTR, 1) }; + //~^ cast_slice_from_raw_parts + require_raw_slice_ptr(unsafe { core::slice::from_raw_parts(PTR, 1) }); + //~^ cast_slice_from_raw_parts + }; +} diff --git a/tests/ui/cast_raw_slice_pointer_cast_no_std.stderr b/tests/ui/cast_raw_slice_pointer_cast_no_std.stderr new file mode 100644 index 00000000000..5488fbcfa1c --- /dev/null +++ b/tests/ui/cast_raw_slice_pointer_cast_no_std.stderr @@ -0,0 +1,83 @@ +error: casting the result of `from_raw_parts` to *const [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:11:35 + | +LL | let _: *const [u8] = unsafe { core::slice::from_raw_parts(ptr, 1) as *const [u8] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + | + = note: `-D clippy::cast-slice-from-raw-parts` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::cast_slice_from_raw_parts)]` + +error: casting the result of `from_raw_parts_mut` to *mut [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:13:35 + | +LL | let _: *const [u8] = unsafe { core::slice::from_raw_parts_mut(mptr, 1) as *mut [u8] }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts_mut(mptr, 1)` + +error: casting the result of `from_raw_parts` to *const [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:15:26 + | +LL | let _: *const [u8] = unsafe { core::slice::from_raw_parts(ptr, 1) } as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: casting the result of `from_raw_parts` to *const [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:19:30 + | +LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: casting the result of `from_raw_parts` to *const [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:22:30 + | +LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: casting the result of `from_raw_parts` to *const [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:27:30 + | +LL | let _: *const [u8] = unsafe { slice::from_raw_parts(ptr, 1) } as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: casting the result of `from_raw_parts` to *const [u8] + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:30:30 + | +LL | let _: *const [u8] = unsafe { one::from_raw_parts(ptr, 1) } as *const [u8]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:36:39 + | +LL | let _: *const [u8] = unsafe { core::slice::from_raw_parts(ptr, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: implicitly casting the result of `from_raw_parts_mut` to `*mut [u8]` + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:38:37 + | +LL | let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(mptr, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts_mut(mptr, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:40:40 + | +LL | require_raw_slice_ptr(unsafe { core::slice::from_raw_parts(ptr, 1) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts(ptr, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:48:39 + | +LL | let _: *const [u8] = unsafe { core::slice::from_raw_parts(PTR, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts(PTR, 1)` + +error: implicitly casting the result of `from_raw_parts_mut` to `*mut [u8]` + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:50:37 + | +LL | let _: *mut [u8] = unsafe { core::slice::from_raw_parts_mut(MPTR, 1) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts_mut(MPTR, 1)` + +error: implicitly casting the result of `from_raw_parts` to `*const [u8]` + --> tests/ui/cast_raw_slice_pointer_cast_no_std.rs:52:40 + | +LL | require_raw_slice_ptr(unsafe { core::slice::from_raw_parts(PTR, 1) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace_with: `core::ptr::slice_from_raw_parts(PTR, 1)` + +error: aborting due to 13 previous errors + diff --git a/tests/ui/cast_size.32bit.stderr b/tests/ui/cast_size.32bit.stderr index cb1620e36a2..5811cb3607b 100644 --- a/tests/ui/cast_size.32bit.stderr +++ b/tests/ui/cast_size.32bit.stderr @@ -177,6 +177,14 @@ error: casting `usize` to `f64` causes a loss of precision on targets with 64-bi LL | 9_999_999_999_999_999usize as f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: casting `usize` to `u16` may truncate the value + --> tests/ui/cast_size.rs:71:20 + | +LL | const N: u16 = M as u16; + | ^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... + error: literal out of range for `usize` --> tests/ui/cast_size.rs:63:5 | @@ -186,5 +194,5 @@ LL | 9_999_999_999_999_999usize as f64; = note: the literal `9_999_999_999_999_999usize` does not fit into the type `usize` whose range is `0..=4294967295` = note: `#[deny(overflowing_literals)]` on by default -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/cast_size.64bit.stderr b/tests/ui/cast_size.64bit.stderr index b6000a52abb..ba1419583ae 100644 --- a/tests/ui/cast_size.64bit.stderr +++ b/tests/ui/cast_size.64bit.stderr @@ -177,5 +177,13 @@ error: casting `usize` to `f64` causes a loss of precision on targets with 64-bi LL | 9_999_999_999_999_999usize as f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 18 previous errors +error: casting `usize` to `u16` may truncate the value + --> tests/ui/cast_size.rs:71:20 + | +LL | const N: u16 = M as u16; + | ^^^^^^^^ + | + = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... + +error: aborting due to 19 previous errors diff --git a/tests/ui/cast_size.rs b/tests/ui/cast_size.rs index e5bef2a99d5..ecc58669419 100644 --- a/tests/ui/cast_size.rs +++ b/tests/ui/cast_size.rs @@ -65,3 +65,9 @@ fn main() { //~[32bit]^^ ERROR: literal out of range for `usize` // 999_999_999_999_999_999_999_999_999_999u128 as f128; } + +fn issue15163() { + const M: usize = 100; + const N: u16 = M as u16; + //~^ cast_possible_truncation +} diff --git a/tests/ui/char_lit_as_u8_suggestions.fixed b/tests/ui/char_lit_as_u8.fixed index 64aacedfd36..64aacedfd36 100644 --- a/tests/ui/char_lit_as_u8_suggestions.fixed +++ b/tests/ui/char_lit_as_u8.fixed diff --git a/tests/ui/char_lit_as_u8.rs b/tests/ui/char_lit_as_u8.rs index c8774c7f309..a8f39e27605 100644 --- a/tests/ui/char_lit_as_u8.rs +++ b/tests/ui/char_lit_as_u8.rs @@ -1,7 +1,12 @@ #![warn(clippy::char_lit_as_u8)] fn main() { - // no suggestion, since a byte literal won't work. - let _ = '❤' as u8; + let _ = 'a' as u8; + //~^ char_lit_as_u8 + let _ = '\n' as u8; + //~^ char_lit_as_u8 + let _ = '\0' as u8; + //~^ char_lit_as_u8 + let _ = '\x01' as u8; //~^ char_lit_as_u8 } diff --git a/tests/ui/char_lit_as_u8.stderr b/tests/ui/char_lit_as_u8.stderr index ec02f1341c0..9bcded7b0ff 100644 --- a/tests/ui/char_lit_as_u8.stderr +++ b/tests/ui/char_lit_as_u8.stderr @@ -1,12 +1,36 @@ error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8.rs:5:13 + --> tests/ui/char_lit_as_u8.rs:4:13 | -LL | let _ = '❤' as u8; - | ^^^^^^^^^ +LL | let _ = 'a' as u8; + | ^^^^^^^^^ help: use a byte literal instead: `b'a'` | = note: `char` is four bytes wide, but `u8` is a single byte = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::char_lit_as_u8)]` -error: aborting due to 1 previous error +error: casting a character literal to `u8` truncates + --> tests/ui/char_lit_as_u8.rs:6:13 + | +LL | let _ = '\n' as u8; + | ^^^^^^^^^^ help: use a byte literal instead: `b'\n'` + | + = note: `char` is four bytes wide, but `u8` is a single byte + +error: casting a character literal to `u8` truncates + --> tests/ui/char_lit_as_u8.rs:8:13 + | +LL | let _ = '\0' as u8; + | ^^^^^^^^^^ help: use a byte literal instead: `b'\0'` + | + = note: `char` is four bytes wide, but `u8` is a single byte + +error: casting a character literal to `u8` truncates + --> tests/ui/char_lit_as_u8.rs:10:13 + | +LL | let _ = '\x01' as u8; + | ^^^^^^^^^^^^ help: use a byte literal instead: `b'\x01'` + | + = note: `char` is four bytes wide, but `u8` is a single byte + +error: aborting due to 4 previous errors diff --git a/tests/ui/char_lit_as_u8_suggestions.rs b/tests/ui/char_lit_as_u8_suggestions.rs deleted file mode 100644 index a8f39e27605..00000000000 --- a/tests/ui/char_lit_as_u8_suggestions.rs +++ /dev/null @@ -1,12 +0,0 @@ -#![warn(clippy::char_lit_as_u8)] - -fn main() { - let _ = 'a' as u8; - //~^ char_lit_as_u8 - let _ = '\n' as u8; - //~^ char_lit_as_u8 - let _ = '\0' as u8; - //~^ char_lit_as_u8 - let _ = '\x01' as u8; - //~^ char_lit_as_u8 -} diff --git a/tests/ui/char_lit_as_u8_suggestions.stderr b/tests/ui/char_lit_as_u8_suggestions.stderr deleted file mode 100644 index 158dfd6bed2..00000000000 --- a/tests/ui/char_lit_as_u8_suggestions.stderr +++ /dev/null @@ -1,36 +0,0 @@ -error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:4:13 - | -LL | let _ = 'a' as u8; - | ^^^^^^^^^ help: use a byte literal instead: `b'a'` - | - = note: `char` is four bytes wide, but `u8` is a single byte - = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::char_lit_as_u8)]` - -error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:6:13 - | -LL | let _ = '\n' as u8; - | ^^^^^^^^^^ help: use a byte literal instead: `b'\n'` - | - = note: `char` is four bytes wide, but `u8` is a single byte - -error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:8:13 - | -LL | let _ = '\0' as u8; - | ^^^^^^^^^^ help: use a byte literal instead: `b'\0'` - | - = note: `char` is four bytes wide, but `u8` is a single byte - -error: casting a character literal to `u8` truncates - --> tests/ui/char_lit_as_u8_suggestions.rs:10:13 - | -LL | let _ = '\x01' as u8; - | ^^^^^^^^^^^^ help: use a byte literal instead: `b'\x01'` - | - = note: `char` is four bytes wide, but `u8` is a single byte - -error: aborting due to 4 previous errors - diff --git a/tests/ui/char_lit_as_u8_unfixable.rs b/tests/ui/char_lit_as_u8_unfixable.rs new file mode 100644 index 00000000000..e5c094f158e --- /dev/null +++ b/tests/ui/char_lit_as_u8_unfixable.rs @@ -0,0 +1,8 @@ +//@no-rustfix +#![warn(clippy::char_lit_as_u8)] + +fn main() { + // no suggestion, since a byte literal won't work. + let _ = '❤' as u8; + //~^ char_lit_as_u8 +} diff --git a/tests/ui/char_lit_as_u8_unfixable.stderr b/tests/ui/char_lit_as_u8_unfixable.stderr new file mode 100644 index 00000000000..49e555ae638 --- /dev/null +++ b/tests/ui/char_lit_as_u8_unfixable.stderr @@ -0,0 +1,12 @@ +error: casting a character literal to `u8` truncates + --> tests/ui/char_lit_as_u8_unfixable.rs:6:13 + | +LL | let _ = '❤' as u8; + | ^^^^^^^^^ + | + = note: `char` is four bytes wide, but `u8` is a single byte + = note: `-D clippy::char-lit-as-u8` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::char_lit_as_u8)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/checked_conversions.fixed b/tests/ui/checked_conversions.fixed index 279a5b6e1ff..6175275ef04 100644 --- a/tests/ui/checked_conversions.fixed +++ b/tests/ui/checked_conversions.fixed @@ -95,7 +95,7 @@ pub const fn issue_8898(i: u32) -> bool { #[clippy::msrv = "1.33"] fn msrv_1_33() { let value: i64 = 33; - let _ = value <= (u32::MAX as i64) && value >= 0; + let _ = value <= (u32::max_value() as i64) && value >= 0; } #[clippy::msrv = "1.34"] diff --git a/tests/ui/checked_conversions.rs b/tests/ui/checked_conversions.rs index c339bc674bb..9ed0e8f660d 100644 --- a/tests/ui/checked_conversions.rs +++ b/tests/ui/checked_conversions.rs @@ -95,13 +95,13 @@ pub const fn issue_8898(i: u32) -> bool { #[clippy::msrv = "1.33"] fn msrv_1_33() { let value: i64 = 33; - let _ = value <= (u32::MAX as i64) && value >= 0; + let _ = value <= (u32::max_value() as i64) && value >= 0; } #[clippy::msrv = "1.34"] fn msrv_1_34() { let value: i64 = 34; - let _ = value <= (u32::MAX as i64) && value >= 0; + let _ = value <= (u32::max_value() as i64) && value >= 0; //~^ checked_conversions } diff --git a/tests/ui/checked_conversions.stderr b/tests/ui/checked_conversions.stderr index 3841b9d5a4d..624876dacb2 100644 --- a/tests/ui/checked_conversions.stderr +++ b/tests/ui/checked_conversions.stderr @@ -100,8 +100,8 @@ LL | let _ = value <= u16::MAX as u32 && value as i32 == 5; error: checked cast can be simplified --> tests/ui/checked_conversions.rs:104:13 | -LL | let _ = value <= (u32::MAX as i64) && value >= 0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` +LL | let _ = value <= (u32::max_value() as i64) && value >= 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()` error: aborting due to 17 previous errors diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index a4bf0099244..939b509d85c 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -328,9 +328,9 @@ error: creating a shared reference to mutable static LL | if X.is_some() { | ^^^^^^^^^^^ shared reference to mutable static | - = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/static-mut-references.html> + = note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/static-mut-references.html> = note: shared references to mutable statics are dangerous; it's undefined behavior if the static is mutated or if a mutable reference is created for it while the shared reference lives - = note: `#[deny(static_mut_refs)]` on by default + = note: `#[deny(static_mut_refs)]` (part of `#[deny(rust_2024_compatibility)]`) on by default error: aborting due to 36 previous errors diff --git a/tests/ui/cmp_null.fixed b/tests/ui/cmp_null.fixed index 140ddb10aeb..04b8ec50160 100644 --- a/tests/ui/cmp_null.fixed +++ b/tests/ui/cmp_null.fixed @@ -33,3 +33,9 @@ fn main() { let _ = (x as *const ()).is_null(); //~^ cmp_null } + +fn issue15010() { + let f: *mut i32 = std::ptr::null_mut(); + debug_assert!(!f.is_null()); + //~^ cmp_null +} diff --git a/tests/ui/cmp_null.rs b/tests/ui/cmp_null.rs index 16ed17765da..6f7762e6ae8 100644 --- a/tests/ui/cmp_null.rs +++ b/tests/ui/cmp_null.rs @@ -33,3 +33,9 @@ fn main() { let _ = x as *const () == ptr::null(); //~^ cmp_null } + +fn issue15010() { + let f: *mut i32 = std::ptr::null_mut(); + debug_assert!(f != std::ptr::null_mut()); + //~^ cmp_null +} diff --git a/tests/ui/cmp_null.stderr b/tests/ui/cmp_null.stderr index 6821846d046..8a75b050111 100644 --- a/tests/ui/cmp_null.stderr +++ b/tests/ui/cmp_null.stderr @@ -31,5 +31,11 @@ error: comparing with null is better expressed by the `.is_null()` method LL | let _ = x as *const () == ptr::null(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(x as *const ()).is_null()` -error: aborting due to 5 previous errors +error: comparing with null is better expressed by the `.is_null()` method + --> tests/ui/cmp_null.rs:39:19 + | +LL | debug_assert!(f != std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!f.is_null()` + +error: aborting due to 6 previous errors diff --git a/tests/ui/coerce_container_to_any.fixed b/tests/ui/coerce_container_to_any.fixed index ae9d3ef9656..b5b3f15b4de 100644 --- a/tests/ui/coerce_container_to_any.fixed +++ b/tests/ui/coerce_container_to_any.fixed @@ -3,7 +3,7 @@ use std::any::Any; fn main() { - let x: Box<dyn Any> = Box::new(()); + let mut x: Box<dyn Any> = Box::new(()); let ref_x = &x; f(&*x); @@ -15,12 +15,23 @@ fn main() { let _: &dyn Any = &*x; //~^ coerce_container_to_any + let _: &dyn Any = &*x; + //~^ coerce_container_to_any + + let _: &mut dyn Any = &mut *x; + //~^ coerce_container_to_any + f(&42); f(&Box::new(())); f(&Box::new(Box::new(()))); + let ref_x = &x; f(&**ref_x); f(&*x); let _: &dyn Any = &*x; + + // https://github.com/rust-lang/rust-clippy/issues/15045 + #[allow(clippy::needless_borrow)] + (&x).downcast_ref::<()>().unwrap(); } fn f(_: &dyn Any) {} diff --git a/tests/ui/coerce_container_to_any.rs b/tests/ui/coerce_container_to_any.rs index 9948bd48e0d..4d6527bb552 100644 --- a/tests/ui/coerce_container_to_any.rs +++ b/tests/ui/coerce_container_to_any.rs @@ -3,7 +3,7 @@ use std::any::Any; fn main() { - let x: Box<dyn Any> = Box::new(()); + let mut x: Box<dyn Any> = Box::new(()); let ref_x = &x; f(&x); @@ -15,12 +15,23 @@ fn main() { let _: &dyn Any = &x; //~^ coerce_container_to_any + let _: &dyn Any = &mut x; + //~^ coerce_container_to_any + + let _: &mut dyn Any = &mut x; + //~^ coerce_container_to_any + f(&42); f(&Box::new(())); f(&Box::new(Box::new(()))); + let ref_x = &x; f(&**ref_x); f(&*x); let _: &dyn Any = &*x; + + // https://github.com/rust-lang/rust-clippy/issues/15045 + #[allow(clippy::needless_borrow)] + (&x).downcast_ref::<()>().unwrap(); } fn f(_: &dyn Any) {} diff --git a/tests/ui/coerce_container_to_any.stderr b/tests/ui/coerce_container_to_any.stderr index 00ab77e0ce0..26389c9186e 100644 --- a/tests/ui/coerce_container_to_any.stderr +++ b/tests/ui/coerce_container_to_any.stderr @@ -19,5 +19,17 @@ error: coercing `&std::boxed::Box<dyn std::any::Any>` to `&dyn Any` LL | let _: &dyn Any = &x; | ^^ help: consider dereferencing: `&*x` -error: aborting due to 3 previous errors +error: coercing `&mut std::boxed::Box<dyn std::any::Any>` to `&dyn Any` + --> tests/ui/coerce_container_to_any.rs:18:23 + | +LL | let _: &dyn Any = &mut x; + | ^^^^^^ help: consider dereferencing: `&*x` + +error: coercing `&mut std::boxed::Box<dyn std::any::Any>` to `&mut dyn Any` + --> tests/ui/coerce_container_to_any.rs:21:27 + | +LL | let _: &mut dyn Any = &mut x; + | ^^^^^^ help: consider dereferencing: `&mut *x` + +error: aborting due to 5 previous errors diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index 9f530ad670a..3d709fe9b8e 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -86,3 +86,43 @@ fn issue_7318() { }else if false {} //~^^^ collapsible_else_if } + +fn issue14799() { + use std::ops::ControlFlow; + + let c: ControlFlow<_, ()> = ControlFlow::Break(Some(42)); + if let ControlFlow::Break(Some(_)) = c { + todo!(); + } else { + #[cfg(target_os = "freebsd")] + todo!(); + + if let ControlFlow::Break(None) = c { + todo!(); + } else { + todo!(); + } + } +} + +fn in_parens() { + let x = "hello"; + let y = "world"; + + if x == "hello" { + print!("Hello "); + } else if y == "world" { println!("world") } else { println!("!") } + //~^^^ collapsible_else_if +} + +fn in_brackets() { + let x = "hello"; + let y = "world"; + + // There is no lint when the inner `if` is in a block. + if x == "hello" { + print!("Hello "); + } else { + { if y == "world" { println!("world") } else { println!("!") } } + } +} diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 2c646cd1d4d..51868e03908 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -102,3 +102,45 @@ fn issue_7318() { } //~^^^ collapsible_else_if } + +fn issue14799() { + use std::ops::ControlFlow; + + let c: ControlFlow<_, ()> = ControlFlow::Break(Some(42)); + if let ControlFlow::Break(Some(_)) = c { + todo!(); + } else { + #[cfg(target_os = "freebsd")] + todo!(); + + if let ControlFlow::Break(None) = c { + todo!(); + } else { + todo!(); + } + } +} + +fn in_parens() { + let x = "hello"; + let y = "world"; + + if x == "hello" { + print!("Hello "); + } else { + (if y == "world" { println!("world") } else { println!("!") }) + } + //~^^^ collapsible_else_if +} + +fn in_brackets() { + let x = "hello"; + let y = "world"; + + // There is no lint when the inner `if` is in a block. + if x == "hello" { + print!("Hello "); + } else { + { if y == "world" { println!("world") } else { println!("!") } } + } +} diff --git a/tests/ui/collapsible_else_if.stderr b/tests/ui/collapsible_else_if.stderr index 7d80894cadb..1a7bcec7fd5 100644 --- a/tests/ui/collapsible_else_if.stderr +++ b/tests/ui/collapsible_else_if.stderr @@ -150,5 +150,14 @@ LL | | if false {} LL | | } | |_____^ help: collapse nested if block: `if false {}` -error: aborting due to 8 previous errors +error: this `else { if .. }` block can be collapsed + --> tests/ui/collapsible_else_if.rs:130:12 + | +LL | } else { + | ____________^ +LL | | (if y == "world" { println!("world") } else { println!("!") }) +LL | | } + | |_____^ help: collapse nested if block: `if y == "world" { println!("world") } else { println!("!") }` + +error: aborting due to 9 previous errors diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index b553182a445..78354c2d7cf 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -154,3 +154,30 @@ fn issue14722() { None }; } + +fn issue14799() { + if true { + #[cfg(target_os = "freebsd")] + todo!(); + + if true {} + }; +} + +fn in_parens() { + if true + && true { + println!("In parens, linted"); + } + //~^^^^^ collapsible_if +} + +fn in_brackets() { + if true { + { + if true { + println!("In brackets, not linted"); + } + } + } +} diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index f5998457ca6..5d9afa10956 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -164,3 +164,31 @@ fn issue14722() { None }; } + +fn issue14799() { + if true { + #[cfg(target_os = "freebsd")] + todo!(); + + if true {} + }; +} + +fn in_parens() { + if true { + (if true { + println!("In parens, linted"); + }) + } + //~^^^^^ collapsible_if +} + +fn in_brackets() { + if true { + { + if true { + println!("In brackets, not linted"); + } + } + } +} diff --git a/tests/ui/collapsible_if.stderr b/tests/ui/collapsible_if.stderr index 32c6b019403..a685cc2e929 100644 --- a/tests/ui/collapsible_if.stderr +++ b/tests/ui/collapsible_if.stderr @@ -190,5 +190,23 @@ LL | // This is a comment, do not collapse code to it LL ~ ; 3 | -error: aborting due to 11 previous errors +error: this `if` statement can be collapsed + --> tests/ui/collapsible_if.rs:178:5 + | +LL | / if true { +LL | | (if true { +LL | | println!("In parens, linted"); +LL | | }) +LL | | } + | |_____^ + | +help: collapse nested if block + | +LL ~ if true +LL ~ && true { +LL | println!("In parens, linted"); +LL ~ } + | + +error: aborting due to 12 previous errors diff --git a/tests/ui/const_is_empty.rs b/tests/ui/const_is_empty.rs index 8bb4f0e5d97..63c6342a323 100644 --- a/tests/ui/const_is_empty.rs +++ b/tests/ui/const_is_empty.rs @@ -196,6 +196,7 @@ fn issue_13106() { const { assert!(EMPTY_STR.is_empty()); + //~^ const_is_empty } const { diff --git a/tests/ui/const_is_empty.stderr b/tests/ui/const_is_empty.stderr index 2ba189058e8..9a42518698e 100644 --- a/tests/ui/const_is_empty.stderr +++ b/tests/ui/const_is_empty.stderr @@ -158,10 +158,16 @@ LL | let _ = val.is_empty(); | ^^^^^^^^^^^^^^ error: this expression always evaluates to true - --> tests/ui/const_is_empty.rs:202:9 + --> tests/ui/const_is_empty.rs:198:17 + | +LL | assert!(EMPTY_STR.is_empty()); + | ^^^^^^^^^^^^^^^^^^^^ + +error: this expression always evaluates to true + --> tests/ui/const_is_empty.rs:203:9 | LL | EMPTY_STR.is_empty(); | ^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 27 previous errors +error: aborting due to 28 previous errors diff --git a/tests/ui/crashes/ice-6255.rs b/tests/ui/crashes/ice-6255.rs index ef1e01f80ef..5f31696c791 100644 --- a/tests/ui/crashes/ice-6255.rs +++ b/tests/ui/crashes/ice-6255.rs @@ -9,7 +9,7 @@ macro_rules! define_other_core { } fn main() { - core::panic!(); + core::panic!(); //~ ERROR: `core` is ambiguous } define_other_core!(); diff --git a/tests/ui/crashes/ice-6255.stderr b/tests/ui/crashes/ice-6255.stderr index 738e9d1bd5c..420e4af936f 100644 --- a/tests/ui/crashes/ice-6255.stderr +++ b/tests/ui/crashes/ice-6255.stderr @@ -9,5 +9,25 @@ LL | define_other_core!(); | = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 1 previous error +error[E0659]: `core` is ambiguous + --> tests/ui/crashes/ice-6255.rs:12:5 + | +LL | core::panic!(); + | ^^^^ ambiguous name + | + = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution + = note: `core` could refer to a built-in crate +note: `core` could also refer to the crate imported here + --> tests/ui/crashes/ice-6255.rs:6:9 + | +LL | extern crate std as core; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | define_other_core!(); + | -------------------- in this macro invocation + = help: use `crate::core` to refer to this crate unambiguously + = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0659`. diff --git a/tests/ui/crashes/ice-9463.rs b/tests/ui/crashes/ice-9463.rs index 93808e0f892..cfa6cdac6fa 100644 --- a/tests/ui/crashes/ice-9463.rs +++ b/tests/ui/crashes/ice-9463.rs @@ -1,8 +1,7 @@ -#![deny(arithmetic_overflow)] +//@check-pass + fn main() { let _x = -1_i32 >> -1; - //~^ ERROR: this arithmetic operation will overflow + #[expect(overflowing_literals)] let _y = 1u32 >> 10000000000000u32; - //~^ ERROR: this arithmetic operation will overflow - //~| ERROR: literal out of range } diff --git a/tests/ui/crashes/ice-9463.stderr b/tests/ui/crashes/ice-9463.stderr deleted file mode 100644 index 9a3a5e444ad..00000000000 --- a/tests/ui/crashes/ice-9463.stderr +++ /dev/null @@ -1,29 +0,0 @@ -error: this arithmetic operation will overflow - --> tests/ui/crashes/ice-9463.rs:3:14 - | -LL | let _x = -1_i32 >> -1; - | ^^^^^^^^^^^^ attempt to shift right by `-1_i32`, which would overflow - | -note: the lint level is defined here - --> tests/ui/crashes/ice-9463.rs:1:9 - | -LL | #![deny(arithmetic_overflow)] - | ^^^^^^^^^^^^^^^^^^^ - -error: this arithmetic operation will overflow - --> tests/ui/crashes/ice-9463.rs:5:14 - | -LL | let _y = 1u32 >> 10000000000000u32; - | ^^^^^^^^^^^^^^^^^^^^^^^^^ attempt to shift right by `1316134912_u32`, which would overflow - -error: literal out of range for `u32` - --> tests/ui/crashes/ice-9463.rs:5:22 - | -LL | let _y = 1u32 >> 10000000000000u32; - | ^^^^^^^^^^^^^^^^^ - | - = note: the literal `10000000000000u32` does not fit into the type `u32` whose range is `0..=4294967295` - = note: `#[deny(overflowing_literals)]` on by default - -error: aborting due to 3 previous errors - diff --git a/tests/ui/crashes/ice-96721.stderr b/tests/ui/crashes/ice-96721.stderr index f0778a4b32b..23f7300178e 100644 --- a/tests/ui/crashes/ice-96721.stderr +++ b/tests/ui/crashes/ice-96721.stderr @@ -3,6 +3,8 @@ error: malformed `path` attribute input | LL | #[path = foo!()] | ^^^^^^^^^^^^^^^^ help: must be of the form: `#[path = "file"]` + | + = note: for more information, visit <https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute> error: aborting due to 1 previous error diff --git a/tests/ui/create_dir.fixed b/tests/ui/create_dir.fixed index 4a5b1b77be6..d4b8f8b4d07 100644 --- a/tests/ui/create_dir.fixed +++ b/tests/ui/create_dir.fixed @@ -7,12 +7,31 @@ fn create_dir() {} fn main() { // Should be warned - create_dir_all("foo"); + std::fs::create_dir_all("foo"); //~^ create_dir - create_dir_all("bar").unwrap(); + std::fs::create_dir_all("bar").unwrap(); //~^ create_dir // Shouldn't be warned create_dir(); std::fs::create_dir_all("foobar"); } + +mod issue14994 { + fn with_no_prefix() { + use std::fs::create_dir; + std::fs::create_dir_all("some/dir").unwrap(); + //~^ create_dir + } + + fn with_fs_prefix() { + use std::fs; + fs::create_dir_all("/some/dir").unwrap(); + //~^ create_dir + } + + fn with_full_prefix() { + std::fs::create_dir_all("/some/dir").unwrap(); + //~^ create_dir + } +} diff --git a/tests/ui/create_dir.rs b/tests/ui/create_dir.rs index bf185ba3a7c..21e0bdba03b 100644 --- a/tests/ui/create_dir.rs +++ b/tests/ui/create_dir.rs @@ -16,3 +16,22 @@ fn main() { create_dir(); std::fs::create_dir_all("foobar"); } + +mod issue14994 { + fn with_no_prefix() { + use std::fs::create_dir; + create_dir("some/dir").unwrap(); + //~^ create_dir + } + + fn with_fs_prefix() { + use std::fs; + fs::create_dir("/some/dir").unwrap(); + //~^ create_dir + } + + fn with_full_prefix() { + std::fs::create_dir("/some/dir").unwrap(); + //~^ create_dir + } +} diff --git a/tests/ui/create_dir.stderr b/tests/ui/create_dir.stderr index 51d6ac686e0..e3ca0e7255c 100644 --- a/tests/ui/create_dir.stderr +++ b/tests/ui/create_dir.stderr @@ -8,9 +8,8 @@ LL | std::fs::create_dir("foo"); = help: to override `-D warnings` add `#[allow(clippy::create_dir)]` help: consider calling `std::fs::create_dir_all` instead | -LL - std::fs::create_dir("foo"); -LL + create_dir_all("foo"); - | +LL | std::fs::create_dir_all("foo"); + | ++++ error: calling `std::fs::create_dir` where there may be a better way --> tests/ui/create_dir.rs:12:5 @@ -20,9 +19,41 @@ LL | std::fs::create_dir("bar").unwrap(); | help: consider calling `std::fs::create_dir_all` instead | -LL - std::fs::create_dir("bar").unwrap(); -LL + create_dir_all("bar").unwrap(); +LL | std::fs::create_dir_all("bar").unwrap(); + | ++++ + +error: calling `std::fs::create_dir` where there may be a better way + --> tests/ui/create_dir.rs:23:9 + | +LL | create_dir("some/dir").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider calling `std::fs::create_dir_all` instead + | +LL | std::fs::create_dir_all("some/dir").unwrap(); + | +++++++++ ++++ + +error: calling `std::fs::create_dir` where there may be a better way + --> tests/ui/create_dir.rs:29:9 + | +LL | fs::create_dir("/some/dir").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider calling `std::fs::create_dir_all` instead + | +LL | fs::create_dir_all("/some/dir").unwrap(); + | ++++ + +error: calling `std::fs::create_dir` where there may be a better way + --> tests/ui/create_dir.rs:34:9 + | +LL | std::fs::create_dir("/some/dir").unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider calling `std::fs::create_dir_all` instead | +LL | std::fs::create_dir_all("/some/dir").unwrap(); + | ++++ -error: aborting due to 2 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/def_id_nocore.rs b/tests/ui/def_id_nocore.rs index 40f40f7ea09..5c13d862276 100644 --- a/tests/ui/def_id_nocore.rs +++ b/tests/ui/def_id_nocore.rs @@ -7,8 +7,14 @@ #[link(name = "c")] unsafe extern "C" {} +#[lang = "pointee_sized"] +pub trait PointeeSized {} + +#[lang = "meta_sized"] +pub trait MetaSized: PointeeSized {} + #[lang = "sized"] -pub trait Sized {} +pub trait Sized: MetaSized {} #[lang = "copy"] pub trait Copy {} #[lang = "freeze"] diff --git a/tests/ui/def_id_nocore.stderr b/tests/ui/def_id_nocore.stderr index 2718217313f..175dd075408 100644 --- a/tests/ui/def_id_nocore.stderr +++ b/tests/ui/def_id_nocore.stderr @@ -1,5 +1,5 @@ error: methods called `as_*` usually take `self` by reference or `self` by mutable reference - --> tests/ui/def_id_nocore.rs:27:19 + --> tests/ui/def_id_nocore.rs:33:19 | LL | pub fn as_ref(self) -> &'static str { | ^^^^ diff --git a/tests/ui/deprecated.rs b/tests/ui/deprecated.rs index 6b69bdd29ce..9743a83fb93 100644 --- a/tests/ui/deprecated.rs +++ b/tests/ui/deprecated.rs @@ -12,6 +12,7 @@ #![warn(clippy::regex_macro)] //~ ERROR: lint `clippy::regex_macro` #![warn(clippy::replace_consts)] //~ ERROR: lint `clippy::replace_consts` #![warn(clippy::should_assert_eq)] //~ ERROR: lint `clippy::should_assert_eq` +#![warn(clippy::string_to_string)] //~ ERROR: lint `clippy::string_to_string` #![warn(clippy::unsafe_vector_initialization)] //~ ERROR: lint `clippy::unsafe_vector_initialization` #![warn(clippy::unstable_as_mut_slice)] //~ ERROR: lint `clippy::unstable_as_mut_slice` #![warn(clippy::unstable_as_slice)] //~ ERROR: lint `clippy::unstable_as_slice` diff --git a/tests/ui/deprecated.stderr b/tests/ui/deprecated.stderr index 07e59d33d60..cd225da611c 100644 --- a/tests/ui/deprecated.stderr +++ b/tests/ui/deprecated.stderr @@ -61,35 +61,41 @@ error: lint `clippy::should_assert_eq` has been removed: `assert!(a == b)` can n LL | #![warn(clippy::should_assert_eq)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error: lint `clippy::unsafe_vector_initialization` has been removed: the suggested alternative could be substantially slower +error: lint `clippy::string_to_string` has been removed: `clippy:implicit_clone` covers those cases --> tests/ui/deprecated.rs:15:9 | +LL | #![warn(clippy::string_to_string)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: lint `clippy::unsafe_vector_initialization` has been removed: the suggested alternative could be substantially slower + --> tests/ui/deprecated.rs:16:9 + | LL | #![warn(clippy::unsafe_vector_initialization)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::unstable_as_mut_slice` has been removed: `Vec::as_mut_slice` is now stable - --> tests/ui/deprecated.rs:16:9 + --> tests/ui/deprecated.rs:17:9 | LL | #![warn(clippy::unstable_as_mut_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::unstable_as_slice` has been removed: `Vec::as_slice` is now stable - --> tests/ui/deprecated.rs:17:9 + --> tests/ui/deprecated.rs:18:9 | LL | #![warn(clippy::unstable_as_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::unused_collect` has been removed: `Iterator::collect` is now marked as `#[must_use]` - --> tests/ui/deprecated.rs:18:9 + --> tests/ui/deprecated.rs:19:9 | LL | #![warn(clippy::unused_collect)] | ^^^^^^^^^^^^^^^^^^^^^^ error: lint `clippy::wrong_pub_self_convention` has been removed: `clippy::wrong_self_convention` now covers this case via the `avoid-breaking-exported-api` config - --> tests/ui/deprecated.rs:19:9 + --> tests/ui/deprecated.rs:20:9 | LL | #![warn(clippy::wrong_pub_self_convention)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/deref_addrof.fixed b/tests/ui/deref_addrof.fixed index 35dbd790e89..ffe7f7d1440 100644 --- a/tests/ui/deref_addrof.fixed +++ b/tests/ui/deref_addrof.fixed @@ -1,11 +1,11 @@ -//@aux-build:proc_macros.rs - -#![allow(clippy::return_self_not_must_use, clippy::useless_vec)] +#![allow( + dangerous_implicit_autorefs, + clippy::explicit_auto_deref, + clippy::return_self_not_must_use, + clippy::useless_vec +)] #![warn(clippy::deref_addrof)] -extern crate proc_macros; -use proc_macros::inline_macros; - fn get_number() -> usize { 10 } @@ -56,19 +56,75 @@ fn main() { //~^ deref_addrof // do NOT lint for array as semantic differences with/out `*&`. let _arr = *&[0, 1, 2, 3, 4]; + + // Do not lint when text comes from macro + macro_rules! mac { + (dr) => { + *&0 + }; + (dr $e:expr) => { + *&$e + }; + (r $e:expr) => { + &$e + }; + } + let b = mac!(dr); + let b = mac!(dr a); + let b = *mac!(r a); } -#[derive(Copy, Clone)] -pub struct S; -#[inline_macros] -impl S { - pub fn f(&self) -> &Self { - inline!($(@expr self)) - //~^ deref_addrof +fn issue14386() { + use std::mem::ManuallyDrop; + + #[derive(Copy, Clone)] + struct Data { + num: u64, } - #[allow(unused_mut)] // mut will be unused, once the macro is fixed - pub fn f_mut(mut self) -> Self { - inline!($(@expr self)) + + #[derive(Clone, Copy)] + struct M { + md: ManuallyDrop<[u8; 4]>, + } + + union DataWithPadding<'lt> { + data: ManuallyDrop<Data>, + prim: ManuallyDrop<u64>, + padding: [u8; size_of::<Data>()], + tup: (ManuallyDrop<Data>, ()), + indirect: M, + indirect_arr: [M; 2], + indirect_ref: &'lt mut M, + } + + let mut a = DataWithPadding { + padding: [0; size_of::<DataWithPadding>()], + }; + unsafe { + a.padding = [1; size_of::<DataWithPadding>()]; //~^ deref_addrof + a.tup.1 = (); + //~^ deref_addrof + *a.prim = 0; + //~^ deref_addrof + + (*a.data).num = 42; + //~^ deref_addrof + (*a.indirect.md)[3] = 1; + //~^ deref_addrof + (*a.indirect_arr[1].md)[3] = 1; + //~^ deref_addrof + (*a.indirect_ref.md)[3] = 1; + //~^ deref_addrof + + // Check that raw pointers are properly considered as well + *a.prim = 0; + //~^ deref_addrof + (*a.data).num = 42; + //~^ deref_addrof + + // Do not lint, as the dereference happens later, we cannot + // just remove `&mut` + (*&mut a.tup).0.num = 42; } } diff --git a/tests/ui/deref_addrof.rs b/tests/ui/deref_addrof.rs index 96d1b92ef7b..bc253716aff 100644 --- a/tests/ui/deref_addrof.rs +++ b/tests/ui/deref_addrof.rs @@ -1,11 +1,11 @@ -//@aux-build:proc_macros.rs - -#![allow(clippy::return_self_not_must_use, clippy::useless_vec)] +#![allow( + dangerous_implicit_autorefs, + clippy::explicit_auto_deref, + clippy::return_self_not_must_use, + clippy::useless_vec +)] #![warn(clippy::deref_addrof)] -extern crate proc_macros; -use proc_macros::inline_macros; - fn get_number() -> usize { 10 } @@ -56,19 +56,75 @@ fn main() { //~^ deref_addrof // do NOT lint for array as semantic differences with/out `*&`. let _arr = *&[0, 1, 2, 3, 4]; + + // Do not lint when text comes from macro + macro_rules! mac { + (dr) => { + *&0 + }; + (dr $e:expr) => { + *&$e + }; + (r $e:expr) => { + &$e + }; + } + let b = mac!(dr); + let b = mac!(dr a); + let b = *mac!(r a); } -#[derive(Copy, Clone)] -pub struct S; -#[inline_macros] -impl S { - pub fn f(&self) -> &Self { - inline!(*& $(@expr self)) - //~^ deref_addrof +fn issue14386() { + use std::mem::ManuallyDrop; + + #[derive(Copy, Clone)] + struct Data { + num: u64, } - #[allow(unused_mut)] // mut will be unused, once the macro is fixed - pub fn f_mut(mut self) -> Self { - inline!(*&mut $(@expr self)) + + #[derive(Clone, Copy)] + struct M { + md: ManuallyDrop<[u8; 4]>, + } + + union DataWithPadding<'lt> { + data: ManuallyDrop<Data>, + prim: ManuallyDrop<u64>, + padding: [u8; size_of::<Data>()], + tup: (ManuallyDrop<Data>, ()), + indirect: M, + indirect_arr: [M; 2], + indirect_ref: &'lt mut M, + } + + let mut a = DataWithPadding { + padding: [0; size_of::<DataWithPadding>()], + }; + unsafe { + (*&mut a.padding) = [1; size_of::<DataWithPadding>()]; //~^ deref_addrof + (*&mut a.tup).1 = (); + //~^ deref_addrof + **&mut a.prim = 0; + //~^ deref_addrof + + (*&mut a.data).num = 42; + //~^ deref_addrof + (*&mut a.indirect.md)[3] = 1; + //~^ deref_addrof + (*&mut a.indirect_arr[1].md)[3] = 1; + //~^ deref_addrof + (*&mut a.indirect_ref.md)[3] = 1; + //~^ deref_addrof + + // Check that raw pointers are properly considered as well + **&raw mut a.prim = 0; + //~^ deref_addrof + (*&raw mut a.data).num = 42; + //~^ deref_addrof + + // Do not lint, as the dereference happens later, we cannot + // just remove `&mut` + (*&mut a.tup).0.num = 42; } } diff --git a/tests/ui/deref_addrof.stderr b/tests/ui/deref_addrof.stderr index 81414b625b2..65dd904a8f7 100644 --- a/tests/ui/deref_addrof.stderr +++ b/tests/ui/deref_addrof.stderr @@ -56,20 +56,58 @@ LL | let _repeat = *&[0; 64]; | ^^^^^^^^^ help: try: `[0; 64]` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:66:17 + --> tests/ui/deref_addrof.rs:104:9 | -LL | inline!(*& $(@expr self)) - | ^^^^^^^^^^^^^^^^ help: try: `$(@expr self)` +LL | (*&mut a.padding) = [1; size_of::<DataWithPadding>()]; + | ^^^^^^^^^^^^^^^^^ help: try: `a.padding` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:106:9 + | +LL | (*&mut a.tup).1 = (); + | ^^^^^^^^^^^^^ help: try: `a.tup` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:108:10 | - = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | **&mut a.prim = 0; + | ^^^^^^^^^^^^ help: try: `a.prim` error: immediately dereferencing a reference - --> tests/ui/deref_addrof.rs:71:17 + --> tests/ui/deref_addrof.rs:111:9 | -LL | inline!(*&mut $(@expr self)) - | ^^^^^^^^^^^^^^^^^^^ help: try: `$(@expr self)` +LL | (*&mut a.data).num = 42; + | ^^^^^^^^^^^^^^ help: try: `(*a.data)` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:113:9 + | +LL | (*&mut a.indirect.md)[3] = 1; + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `(*a.indirect.md)` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:115:9 + | +LL | (*&mut a.indirect_arr[1].md)[3] = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*a.indirect_arr[1].md)` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:117:9 + | +LL | (*&mut a.indirect_ref.md)[3] = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*a.indirect_ref.md)` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:121:10 + | +LL | **&raw mut a.prim = 0; + | ^^^^^^^^^^^^^^^^ help: try: `a.prim` + +error: immediately dereferencing a reference + --> tests/ui/deref_addrof.rs:123:9 | - = note: this error originates in the macro `__inline_mac_impl` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | (*&raw mut a.data).num = 42; + | ^^^^^^^^^^^^^^^^^^ help: try: `(*a.data)` -error: aborting due to 11 previous errors +error: aborting due to 18 previous errors diff --git a/tests/ui/derivable_impls.fixed b/tests/ui/derivable_impls.fixed index 65bfded3883..9f9e4e253c3 100644 --- a/tests/ui/derivable_impls.fixed +++ b/tests/ui/derivable_impls.fixed @@ -1,4 +1,6 @@ #![allow(dead_code)] +#![feature(const_trait_impl)] +#![feature(const_default)] use std::collections::HashMap; @@ -326,4 +328,40 @@ mod issue11368 { } } +mod issue15493 { + #[derive(Copy, Clone)] + #[repr(transparent)] + struct Foo(u64); + + impl const Default for Foo { + fn default() -> Self { + Self(0) + } + } + + #[derive(Copy, Clone)] + enum Bar { + A, + B, + } + + impl const Default for Bar { + fn default() -> Self { + Bar::A + } + } +} + +mod issue15536 { + #[derive(Copy, Clone)] + #[derive(Default)] + enum Bar { + #[default] + A, + B, + } + + +} + fn main() {} diff --git a/tests/ui/derivable_impls.rs b/tests/ui/derivable_impls.rs index 4826c5497b4..74a793b9a70 100644 --- a/tests/ui/derivable_impls.rs +++ b/tests/ui/derivable_impls.rs @@ -1,4 +1,6 @@ #![allow(dead_code)] +#![feature(const_trait_impl)] +#![feature(const_default)] use std::collections::HashMap; @@ -396,4 +398,43 @@ mod issue11368 { } } +mod issue15493 { + #[derive(Copy, Clone)] + #[repr(transparent)] + struct Foo(u64); + + impl const Default for Foo { + fn default() -> Self { + Self(0) + } + } + + #[derive(Copy, Clone)] + enum Bar { + A, + B, + } + + impl const Default for Bar { + fn default() -> Self { + Bar::A + } + } +} + +mod issue15536 { + #[derive(Copy, Clone)] + enum Bar { + A, + B, + } + + impl Default for Bar { + //~^ derivable_impls + fn default() -> Self { + Self::A + } + } +} + fn main() {} diff --git a/tests/ui/derivable_impls.stderr b/tests/ui/derivable_impls.stderr index 0f73ad55a85..cd46414cb4a 100644 --- a/tests/ui/derivable_impls.stderr +++ b/tests/ui/derivable_impls.stderr @@ -1,5 +1,5 @@ error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:20:1 + --> tests/ui/derivable_impls.rs:22:1 | LL | / impl std::default::Default for FooDefault<'_> { LL | | @@ -18,7 +18,7 @@ LL ~ struct FooDefault<'a> { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:42:1 + --> tests/ui/derivable_impls.rs:44:1 | LL | / impl std::default::Default for TupleDefault { LL | | @@ -35,7 +35,7 @@ LL ~ struct TupleDefault(bool, i32, u64); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:95:1 + --> tests/ui/derivable_impls.rs:97:1 | LL | / impl Default for StrDefault<'_> { LL | | @@ -52,7 +52,7 @@ LL ~ struct StrDefault<'a>(&'a str); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:122:1 + --> tests/ui/derivable_impls.rs:124:1 | LL | / impl Default for Y { LL | | @@ -69,7 +69,7 @@ LL ~ struct Y(u32); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:162:1 + --> tests/ui/derivable_impls.rs:164:1 | LL | / impl Default for WithoutSelfCurly { LL | | @@ -86,7 +86,7 @@ LL ~ struct WithoutSelfCurly { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:171:1 + --> tests/ui/derivable_impls.rs:173:1 | LL | / impl Default for WithoutSelfParan { LL | | @@ -103,7 +103,7 @@ LL ~ struct WithoutSelfParan(bool); | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:194:1 + --> tests/ui/derivable_impls.rs:196:1 | LL | / impl Default for DirectDefaultDefaultCall { LL | | @@ -119,7 +119,7 @@ LL ~ pub struct DirectDefaultDefaultCall { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:206:1 + --> tests/ui/derivable_impls.rs:208:1 | LL | / impl Default for EquivalentToDefaultDefaultCallVec { LL | | @@ -135,7 +135,7 @@ LL ~ pub struct EquivalentToDefaultDefaultCallVec { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:234:1 + --> tests/ui/derivable_impls.rs:236:1 | LL | / impl Default for EquivalentToDefaultDefaultCallLocal { LL | | @@ -151,7 +151,7 @@ LL ~ pub struct EquivalentToDefaultDefaultCallLocal { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:274:1 + --> tests/ui/derivable_impls.rs:276:1 | LL | / impl Default for RepeatDefault1 { LL | | @@ -168,7 +168,7 @@ LL ~ pub struct RepeatDefault1 { | error: this `impl` can be derived - --> tests/ui/derivable_impls.rs:309:1 + --> tests/ui/derivable_impls.rs:311:1 | LL | / impl Default for SimpleEnum { LL | | @@ -187,5 +187,28 @@ LL ~ #[default] LL ~ Bar, | -error: aborting due to 11 previous errors +error: this `impl` can be derived + --> tests/ui/derivable_impls.rs:432:5 + | +LL | / impl Default for Bar { +LL | | +LL | | fn default() -> Self { +LL | | Self::A +LL | | } +LL | | } + | |_____^ + | +help: replace the manual implementation with a derive attribute and mark the default variant + | +LL ~ #[derive(Default)] +LL ~ enum Bar { +LL ~ #[default] +LL ~ A, +LL | B, +LL | } +LL | +LL ~ + | + +error: aborting due to 12 previous errors diff --git a/tests/ui/derivable_impls_derive_const.fixed b/tests/ui/derivable_impls_derive_const.fixed new file mode 100644 index 00000000000..f0d8d2d2409 --- /dev/null +++ b/tests/ui/derivable_impls_derive_const.fixed @@ -0,0 +1,25 @@ +#![allow(dead_code)] +#![feature(const_trait_impl)] +#![feature(const_default)] +#![feature(derive_const)] + +mod issue15493 { + #[derive(Copy, Clone)] + #[repr(transparent)] + #[derive_const(Default)] + struct Foo(u64); + + + + #[derive(Copy, Clone)] + #[derive_const(Default)] + enum Bar { + #[default] + A, + B, + } + + +} + +fn main() {} diff --git a/tests/ui/derivable_impls_derive_const.rs b/tests/ui/derivable_impls_derive_const.rs new file mode 100644 index 00000000000..7d70db1c097 --- /dev/null +++ b/tests/ui/derivable_impls_derive_const.rs @@ -0,0 +1,32 @@ +#![allow(dead_code)] +#![feature(const_trait_impl)] +#![feature(const_default)] +#![feature(derive_const)] + +mod issue15493 { + #[derive(Copy, Clone)] + #[repr(transparent)] + struct Foo(u64); + + impl const Default for Foo { + //~^ derivable_impls + fn default() -> Self { + Self(0) + } + } + + #[derive(Copy, Clone)] + enum Bar { + A, + B, + } + + impl const Default for Bar { + //~^ derivable_impls + fn default() -> Self { + Bar::A + } + } +} + +fn main() {} diff --git a/tests/ui/derivable_impls_derive_const.stderr b/tests/ui/derivable_impls_derive_const.stderr new file mode 100644 index 00000000000..196bac185dd --- /dev/null +++ b/tests/ui/derivable_impls_derive_const.stderr @@ -0,0 +1,46 @@ +error: this `impl` can be derived + --> tests/ui/derivable_impls_derive_const.rs:11:5 + | +LL | / impl const Default for Foo { +LL | | +LL | | fn default() -> Self { +LL | | Self(0) +LL | | } +LL | | } + | |_____^ + | + = note: `-D clippy::derivable-impls` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::derivable_impls)]` +help: replace the manual implementation with a derive attribute + | +LL ~ #[derive_const(Default)] +LL ~ struct Foo(u64); +LL | +LL ~ + | + +error: this `impl` can be derived + --> tests/ui/derivable_impls_derive_const.rs:24:5 + | +LL | / impl const Default for Bar { +LL | | +LL | | fn default() -> Self { +LL | | Bar::A +LL | | } +LL | | } + | |_____^ + | +help: replace the manual implementation with a derive attribute and mark the default variant + | +LL ~ #[derive_const(Default)] +LL ~ enum Bar { +LL ~ #[default] +LL ~ A, +LL | B, +LL | } +LL | +LL ~ + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/disallowed_script_idents.rs b/tests/ui/disallowed_script_idents.rs index 08fd1d9669e..dae380045ae 100644 --- a/tests/ui/disallowed_script_idents.rs +++ b/tests/ui/disallowed_script_idents.rs @@ -15,3 +15,17 @@ fn main() { let カウンタ = 10; //~^ disallowed_script_idents } + +fn issue15116() { + const ÄÖÜ: u8 = 0; + const _ÄÖÜ: u8 = 0; + const Ä_ÖÜ: u8 = 0; + const ÄÖ_Ü: u8 = 0; + const ÄÖÜ_: u8 = 0; + let äöüß = 1; + let _äöüß = 1; + let ä_öüß = 1; + let äö_üß = 1; + let äöü_ß = 1; + let äöüß_ = 1; +} diff --git a/tests/ui/doc/doc-fixable.fixed b/tests/ui/doc/doc-fixable.fixed index 8cf20d8b1a1..423a73734da 100644 --- a/tests/ui/doc/doc-fixable.fixed +++ b/tests/ui/doc/doc-fixable.fixed @@ -74,7 +74,7 @@ fn test_units() { /// GitHub GitLab /// IPv4 IPv6 /// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript -/// WebAssembly +/// PowerPC WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml @@ -83,7 +83,7 @@ fn test_units() { /// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport /// TensorFlow /// TrueType -/// iOS macOS FreeBSD NetBSD OpenBSD +/// iOS macOS FreeBSD NetBSD OpenBSD NixOS /// TeX LaTeX BibTeX BibLaTeX /// MinGW /// CamelCase (see also #2395) diff --git a/tests/ui/doc/doc-fixable.rs b/tests/ui/doc/doc-fixable.rs index 5b6f2bd8330..8deffb4210e 100644 --- a/tests/ui/doc/doc-fixable.rs +++ b/tests/ui/doc/doc-fixable.rs @@ -74,7 +74,7 @@ fn test_units() { /// GitHub GitLab /// IPv4 IPv6 /// ClojureScript CoffeeScript JavaScript PostScript PureScript TypeScript -/// WebAssembly +/// PowerPC WebAssembly /// NaN NaNs /// OAuth GraphQL /// OCaml @@ -83,7 +83,7 @@ fn test_units() { /// WebGL WebGL2 WebGPU WebRTC WebSocket WebTransport /// TensorFlow /// TrueType -/// iOS macOS FreeBSD NetBSD OpenBSD +/// iOS macOS FreeBSD NetBSD OpenBSD NixOS /// TeX LaTeX BibTeX BibLaTeX /// MinGW /// CamelCase (see also #2395) diff --git a/tests/ui/doc/doc_nested_refdef_list_item.fixed b/tests/ui/doc/doc_nested_refdef_list_item.fixed index 065f4486e39..5c57c58fbc0 100644 --- a/tests/ui/doc/doc_nested_refdef_list_item.fixed +++ b/tests/ui/doc/doc_nested_refdef_list_item.fixed @@ -72,8 +72,6 @@ pub struct NotEmptyTight; /// ## Heading /// -/// - [x][] - Done -//~^ ERROR: link reference defined in list item -/// - [ ][] - Not Done -//~^ ERROR: link reference defined in list item +/// - [x] - Done +/// - [ ] - Not Done pub struct GithubCheckboxes; diff --git a/tests/ui/doc/doc_nested_refdef_list_item.rs b/tests/ui/doc/doc_nested_refdef_list_item.rs index c7eab50c8b3..06b6ba49e19 100644 --- a/tests/ui/doc/doc_nested_refdef_list_item.rs +++ b/tests/ui/doc/doc_nested_refdef_list_item.rs @@ -73,7 +73,5 @@ pub struct NotEmptyTight; /// ## Heading /// /// - [x] - Done -//~^ ERROR: link reference defined in list item /// - [ ] - Not Done -//~^ ERROR: link reference defined in list item pub struct GithubCheckboxes; diff --git a/tests/ui/doc/doc_nested_refdef_list_item.stderr b/tests/ui/doc/doc_nested_refdef_list_item.stderr index 5a815dabf4d..27314c7e968 100644 --- a/tests/ui/doc/doc_nested_refdef_list_item.stderr +++ b/tests/ui/doc/doc_nested_refdef_list_item.stderr @@ -144,29 +144,5 @@ help: for an intra-doc link, add `[]` between the label and the colon LL | /// - [link][]: def "title" | ++ -error: link reference defined in list item - --> tests/ui/doc/doc_nested_refdef_list_item.rs:75:7 - | -LL | /// - [x] - Done - | ^^^ - | - = help: link definitions are not shown in rendered documentation -help: for an intra-doc link, add `[]` between the label and the colon - | -LL | /// - [x][] - Done - | ++ - -error: link reference defined in list item - --> tests/ui/doc/doc_nested_refdef_list_item.rs:77:7 - | -LL | /// - [ ] - Not Done - | ^^^ - | - = help: link definitions are not shown in rendered documentation -help: for an intra-doc link, add `[]` between the label and the colon - | -LL | /// - [ ][] - Not Done - | ++ - -error: aborting due to 14 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/doc/needless_doctest_main.rs b/tests/ui/doc/needless_doctest_main.rs index 633a435ca5e..8c3217624d4 100644 --- a/tests/ui/doc/needless_doctest_main.rs +++ b/tests/ui/doc/needless_doctest_main.rs @@ -1,5 +1,3 @@ -//@ check-pass - #![warn(clippy::needless_doctest_main)] //! issue 10491: //! ```rust,no_test @@ -19,4 +17,114 @@ /// ``` fn foo() {} +#[rustfmt::skip] +/// Description +/// ```rust +/// fn main() { +//~^ error: needless `fn main` in doctest +/// let a = 0; +/// } +/// ``` +fn mulpipulpi() {} + +#[rustfmt::skip] +/// With a `#[no_main]` +/// ```rust +/// #[no_main] +/// fn a() { +/// let _ = 0; +/// } +/// ``` +fn pulpimulpi() {} + +// Without a `#[no_main]` attribute +/// ```rust +/// fn a() { +/// let _ = 0; +/// } +/// ``` +fn plumilupi() {} + +#[rustfmt::skip] +/// Additional function, shouldn't trigger +/// ```rust +/// fn additional_function() { +/// let _ = 0; +/// // Thus `fn main` is actually relevant! +/// } +/// fn main() { +/// let _ = 0; +/// } +/// ``` +fn mlupipupi() {} + +#[rustfmt::skip] +/// Additional function AFTER main, shouldn't trigger +/// ```rust +/// fn main() { +/// let _ = 0; +/// } +/// fn additional_function() { +/// let _ = 0; +/// // Thus `fn main` is actually relevant! +/// } +/// ``` +fn lumpimupli() {} + +#[rustfmt::skip] +/// Ignore code block, should not lint at all +/// ```rust, ignore +/// fn main() { +//~^ error: needless `fn main` in doctest +/// // Hi! +/// let _ = 0; +/// } +/// ``` +fn mpulpilumi() {} + +#[rustfmt::skip] +/// Spaces in weird positions (including an \u{A0} after `main`) +/// ```rust +/// fn main (){ +//~^ error: needless `fn main` in doctest +/// let _ = 0; +/// } +/// ``` +fn plumpiplupi() {} + +/// 4 Functions, this should not lint because there are several function +/// +/// ```rust +/// fn a() {let _ = 0; } +/// fn b() {let _ = 0; } +/// fn main() { let _ = 0; } +/// fn d() { let _ = 0; } +/// ``` +fn pulmipulmip() {} + +/// 3 Functions but main is first, should also not lint +/// +///```rust +/// fn main() { let _ = 0; } +/// fn b() { let _ = 0; } +/// fn c() { let _ = 0; } +/// ``` +fn pmuplimulip() {} + fn main() {} + +fn issue8244() -> Result<(), ()> { + //! ```compile_fail + //! fn test() -> Result< {} + //! ``` + Ok(()) +} + +/// # Examples +/// +/// ``` +/// use std::error::Error; +/// fn main() -> Result<(), Box<dyn Error>/* > */ { +/// } +/// ``` +fn issue15041() {} diff --git a/tests/ui/doc/needless_doctest_main.stderr b/tests/ui/doc/needless_doctest_main.stderr new file mode 100644 index 00000000000..dd5474ccb85 --- /dev/null +++ b/tests/ui/doc/needless_doctest_main.stderr @@ -0,0 +1,36 @@ +error: needless `fn main` in doctest + --> tests/ui/doc/needless_doctest_main.rs:23:5 + | +LL | /// fn main() { + | _____^ +LL | | +LL | | /// let a = 0; +LL | | /// } + | |_____^ + | + = note: `-D clippy::needless-doctest-main` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_doctest_main)]` + +error: needless `fn main` in doctest + --> tests/ui/doc/needless_doctest_main.rs:77:5 + | +LL | /// fn main() { + | _____^ +LL | | +LL | | /// // Hi! +LL | | /// let _ = 0; +LL | | /// } + | |_____^ + +error: needless `fn main` in doctest + --> tests/ui/doc/needless_doctest_main.rs:88:5 + | +LL | /// fn main (){ + | _____^ +LL | | +LL | | /// let _ = 0; +LL | | /// } + | |_____^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/doc_broken_link.rs b/tests/ui/doc_broken_link.rs new file mode 100644 index 00000000000..7d9c0ef13b3 --- /dev/null +++ b/tests/ui/doc_broken_link.rs @@ -0,0 +1,72 @@ +#![warn(clippy::doc_broken_link)] + +fn main() {} + +pub struct FakeType {} + +/// This might be considered a link false positive +/// and should be ignored by this lint rule: +/// Example of referencing some code with brackets [FakeType]. +pub fn doc_ignore_link_false_positive_1() {} + +/// This might be considered a link false positive +/// and should be ignored by this lint rule: +/// [`FakeType`]. Continue text after brackets, +/// then (something in +/// parenthesis). +pub fn doc_ignore_link_false_positive_2() {} + +/// Test valid link, whole link single line. +/// [doc valid link](https://test.fake/doc_valid_link) +pub fn doc_valid_link() {} + +/// Test valid link, whole link single line but it has special chars such as brackets and +/// parenthesis. [doc invalid link url invalid char](https://test.fake/doc_valid_link_url_invalid_char?foo[bar]=1&bar(foo)=2) +pub fn doc_valid_link_url_invalid_char() {} + +/// Test valid link, text tag broken across multiple lines. +/// [doc valid link broken +/// text](https://test.fake/doc_valid_link_broken_text) +pub fn doc_valid_link_broken_text() {} + +/// Test valid link, url tag broken across multiple lines, but +/// the whole url part in a single line. +/// [doc valid link broken url tag two lines first](https://test.fake/doc_valid_link_broken_url_tag_two_lines_first +/// ) +pub fn doc_valid_link_broken_url_tag_two_lines_first() {} + +/// Test valid link, url tag broken across multiple lines, but +/// the whole url part in a single line. +/// [doc valid link broken url tag two lines second]( +/// https://test.fake/doc_valid_link_broken_url_tag_two_lines_second) +pub fn doc_valid_link_broken_url_tag_two_lines_second() {} + +/// Test valid link, url tag broken across multiple lines, but +/// the whole url part in a single line, but the closing pharentesis +/// in a third line. +/// [doc valid link broken url tag three lines]( +/// https://test.fake/doc_valid_link_broken_url_tag_three_lines +/// ) +pub fn doc_valid_link_broken_url_tag_three_lines() {} + +/// Test invalid link, url part broken across multiple lines. +/// [doc invalid link broken url scheme part](https:// +/// test.fake/doc_invalid_link_broken_url_scheme_part) +//~^^ ERROR: possible broken doc link: broken across multiple lines +pub fn doc_invalid_link_broken_url_scheme_part() {} + +/// Test invalid link, url part broken across multiple lines. +/// [doc invalid link broken url host part](https://test +/// .fake/doc_invalid_link_broken_url_host_part) +//~^^ ERROR: possible broken doc link: broken across multiple lines +pub fn doc_invalid_link_broken_url_host_part() {} + +/// Test invalid link, for multiple urls in the same block of comment. +/// There is a [fist link - invalid](https://test +/// .fake) then it continues +//~^^ ERROR: possible broken doc link: broken across multiple lines +/// with a [second link - valid](https://test.fake/doc_valid_link) and another [third link - invalid](https://test +/// .fake). It ends with another +//~^^ ERROR: possible broken doc link: broken across multiple lines +/// line of comment. +pub fn doc_multiple_invalid_link_broken_url() {} diff --git a/tests/ui/doc_broken_link.stderr b/tests/ui/doc_broken_link.stderr new file mode 100644 index 00000000000..179ed97635e --- /dev/null +++ b/tests/ui/doc_broken_link.stderr @@ -0,0 +1,29 @@ +error: possible broken doc link: broken across multiple lines + --> tests/ui/doc_broken_link.rs:53:5 + | +LL | /// [doc invalid link broken url scheme part](https:// + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::doc-broken-link` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::doc_broken_link)]` + +error: possible broken doc link: broken across multiple lines + --> tests/ui/doc_broken_link.rs:59:5 + | +LL | /// [doc invalid link broken url host part](https://test + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible broken doc link: broken across multiple lines + --> tests/ui/doc_broken_link.rs:65:16 + | +LL | /// There is a [fist link - invalid](https://test + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: possible broken doc link: broken across multiple lines + --> tests/ui/doc_broken_link.rs:68:80 + | +LL | /// with a [second link - valid](https://test.fake/doc_valid_link) and another [third link - invalid](https://test + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/double_ended_iterator_last.fixed b/tests/ui/double_ended_iterator_last.fixed index be31ee5fb48..180a513d0f8 100644 --- a/tests/ui/double_ended_iterator_last.fixed +++ b/tests/ui/double_ended_iterator_last.fixed @@ -81,6 +81,11 @@ fn issue_14139() { let (subindex, _) = (index.by_ref().take(3), 42); let _ = subindex.last(); let _ = index.next(); + + let mut index = [true, true, false, false, false, true].iter(); + let subindex = (index.by_ref().take(3), 42); + let _ = subindex.0.last(); + let _ = index.next(); } fn drop_order() { @@ -108,6 +113,12 @@ fn drop_order() { let mut v = DropDeIterator(v.into_iter()); println!("Last element is {}", v.next_back().unwrap().0); //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let v = vec![S("four"), S("five"), S("six")]; + let mut v = (DropDeIterator(v.into_iter()), 42); + println!("Last element is {}", v.0.next_back().unwrap().0); + //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + println!("Done"); } diff --git a/tests/ui/double_ended_iterator_last.rs b/tests/ui/double_ended_iterator_last.rs index 30864e15bce..3dd72cfeaac 100644 --- a/tests/ui/double_ended_iterator_last.rs +++ b/tests/ui/double_ended_iterator_last.rs @@ -81,6 +81,11 @@ fn issue_14139() { let (subindex, _) = (index.by_ref().take(3), 42); let _ = subindex.last(); let _ = index.next(); + + let mut index = [true, true, false, false, false, true].iter(); + let subindex = (index.by_ref().take(3), 42); + let _ = subindex.0.last(); + let _ = index.next(); } fn drop_order() { @@ -108,6 +113,12 @@ fn drop_order() { let v = DropDeIterator(v.into_iter()); println!("Last element is {}", v.last().unwrap().0); //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + + let v = vec![S("four"), S("five"), S("six")]; + let v = (DropDeIterator(v.into_iter()), 42); + println!("Last element is {}", v.0.last().unwrap().0); + //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` + println!("Done"); } diff --git a/tests/ui/double_ended_iterator_last.stderr b/tests/ui/double_ended_iterator_last.stderr index 72a6ead47a9..0f0056be376 100644 --- a/tests/ui/double_ended_iterator_last.stderr +++ b/tests/ui/double_ended_iterator_last.stderr @@ -18,7 +18,7 @@ LL | let _ = DeIterator.last(); | help: try: `next_back()` error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator - --> tests/ui/double_ended_iterator_last.rs:109:36 + --> tests/ui/double_ended_iterator_last.rs:114:36 | LL | println!("Last element is {}", v.last().unwrap().0); | ^^^^^^^^ @@ -30,5 +30,18 @@ LL ~ let mut v = DropDeIterator(v.into_iter()); LL ~ println!("Last element is {}", v.next_back().unwrap().0); | -error: aborting due to 3 previous errors +error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator + --> tests/ui/double_ended_iterator_last.rs:119:36 + | +LL | println!("Last element is {}", v.0.last().unwrap().0); + | ^^^^^^^^^^ + | + = note: this change will alter drop order which may be undesirable +help: try + | +LL ~ let mut v = (DropDeIterator(v.into_iter()), 42); +LL ~ println!("Last element is {}", v.0.next_back().unwrap().0); + | + +error: aborting due to 4 previous errors diff --git a/tests/ui/double_ended_iterator_last_unfixable.rs b/tests/ui/double_ended_iterator_last_unfixable.rs deleted file mode 100644 index 73f62ac1246..00000000000 --- a/tests/ui/double_ended_iterator_last_unfixable.rs +++ /dev/null @@ -1,39 +0,0 @@ -//@no-rustfix: requires manual changes -#![warn(clippy::double_ended_iterator_last)] - -// Should not be linted because applying the lint would move the original iterator. This can only be -// linted if the iterator is used thereafter. -fn main() { - let mut index = [true, true, false, false, false, true].iter(); - let subindex = (index.by_ref().take(3), 42); - let _ = subindex.0.last(); - let _ = index.next(); -} - -fn drop_order() { - struct DropDeIterator(std::vec::IntoIter<S>); - impl Iterator for DropDeIterator { - type Item = S; - fn next(&mut self) -> Option<Self::Item> { - self.0.next() - } - } - impl DoubleEndedIterator for DropDeIterator { - fn next_back(&mut self) -> Option<Self::Item> { - self.0.next_back() - } - } - - struct S(&'static str); - impl std::ops::Drop for S { - fn drop(&mut self) { - println!("Dropping {}", self.0); - } - } - - let v = vec![S("one"), S("two"), S("three")]; - let v = (DropDeIterator(v.into_iter()), 42); - println!("Last element is {}", v.0.last().unwrap().0); - //~^ ERROR: called `Iterator::last` on a `DoubleEndedIterator` - println!("Done"); -} diff --git a/tests/ui/double_ended_iterator_last_unfixable.stderr b/tests/ui/double_ended_iterator_last_unfixable.stderr deleted file mode 100644 index e330a22a354..00000000000 --- a/tests/ui/double_ended_iterator_last_unfixable.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error: called `Iterator::last` on a `DoubleEndedIterator`; this will needlessly iterate the entire iterator - --> tests/ui/double_ended_iterator_last_unfixable.rs:36:36 - | -LL | println!("Last element is {}", v.0.last().unwrap().0); - | ^^^^------ - | | - | help: try: `next_back()` - | - = note: this change will alter drop order which may be undesirable -note: this must be made mutable to use `.next_back()` - --> tests/ui/double_ended_iterator_last_unfixable.rs:36:36 - | -LL | println!("Last element is {}", v.0.last().unwrap().0); - | ^^^ - = note: `-D clippy::double-ended-iterator-last` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::double_ended_iterator_last)]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/duplicated_attributes.rs b/tests/ui/duplicated_attributes.rs index 3ca91d6f182..9a671499505 100644 --- a/tests/ui/duplicated_attributes.rs +++ b/tests/ui/duplicated_attributes.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macro_attr.rs +#![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] //~ ERROR: duplicated attribute #![feature(rustc_attrs)] -#![warn(clippy::duplicated_attributes)] #![cfg(any(unix, windows))] #![allow(dead_code)] #![allow(dead_code)] //~ ERROR: duplicated attribute diff --git a/tests/ui/duplicated_attributes.stderr b/tests/ui/duplicated_attributes.stderr index 0903617a8d1..922939d60dd 100644 --- a/tests/ui/duplicated_attributes.stderr +++ b/tests/ui/duplicated_attributes.stderr @@ -1,4 +1,23 @@ error: duplicated attribute + --> tests/ui/duplicated_attributes.rs:2:40 + | +LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first defined here + --> tests/ui/duplicated_attributes.rs:2:9 + | +LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: remove this attribute + --> tests/ui/duplicated_attributes.rs:2:40 + | +LL | #![warn(clippy::duplicated_attributes, clippy::duplicated_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: `-D clippy::duplicated-attributes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]` + +error: duplicated attribute --> tests/ui/duplicated_attributes.rs:6:10 | LL | #![allow(dead_code)] @@ -14,8 +33,6 @@ help: remove this attribute | LL | #![allow(dead_code)] | ^^^^^^^^^ - = note: `-D clippy::duplicated-attributes` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]` error: duplicated attribute --> tests/ui/duplicated_attributes.rs:14:9 @@ -34,5 +51,5 @@ help: remove this attribute LL | #[allow(dead_code)] | ^^^^^^^^^ -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/empty_line_after/outer_attribute.1.fixed b/tests/ui/empty_line_after/outer_attribute.1.fixed index 36d80a2c95b..e36e3c2aea6 100644 --- a/tests/ui/empty_line_after/outer_attribute.1.fixed +++ b/tests/ui/empty_line_after/outer_attribute.1.fixed @@ -105,4 +105,13 @@ second line ")] pub struct Args; +mod issue_14980 { + //~v empty_line_after_outer_attr + #[repr(align(536870912))] + enum Aligned { + Zero = 0, + One = 1, + } +} + fn main() {} diff --git a/tests/ui/empty_line_after/outer_attribute.2.fixed b/tests/ui/empty_line_after/outer_attribute.2.fixed index 0e8e4129e85..b0908fc7214 100644 --- a/tests/ui/empty_line_after/outer_attribute.2.fixed +++ b/tests/ui/empty_line_after/outer_attribute.2.fixed @@ -108,4 +108,13 @@ second line ")] pub struct Args; +mod issue_14980 { + //~v empty_line_after_outer_attr + #[repr(align(536870912))] + enum Aligned { + Zero = 0, + One = 1, + } +} + fn main() {} diff --git a/tests/ui/empty_line_after/outer_attribute.rs b/tests/ui/empty_line_after/outer_attribute.rs index 1295088ac00..4ae113c68f5 100644 --- a/tests/ui/empty_line_after/outer_attribute.rs +++ b/tests/ui/empty_line_after/outer_attribute.rs @@ -116,4 +116,14 @@ second line ")] pub struct Args; +mod issue_14980 { + //~v empty_line_after_outer_attr + #[repr(align(536870912))] + + enum Aligned { + Zero = 0, + One = 1, + } +} + fn main() {} diff --git a/tests/ui/empty_line_after/outer_attribute.stderr b/tests/ui/empty_line_after/outer_attribute.stderr index 519ba6e6761..331bc7c8856 100644 --- a/tests/ui/empty_line_after/outer_attribute.stderr +++ b/tests/ui/empty_line_after/outer_attribute.stderr @@ -111,5 +111,16 @@ LL | pub fn isolated_comment() {} | = help: if the empty lines are unintentional, remove them -error: aborting due to 9 previous errors +error: empty line after outer attribute + --> tests/ui/empty_line_after/outer_attribute.rs:121:5 + | +LL | / #[repr(align(536870912))] +LL | | + | |_^ +LL | enum Aligned { + | ------------ the attribute applies to this enum + | + = help: if the empty line is unintentional, remove it + +error: aborting due to 10 previous errors diff --git a/tests/ui/empty_loop_intrinsic.rs b/tests/ui/empty_loop_intrinsic.rs new file mode 100644 index 00000000000..a550e560965 --- /dev/null +++ b/tests/ui/empty_loop_intrinsic.rs @@ -0,0 +1,13 @@ +//@check-pass + +#![warn(clippy::empty_loop)] +#![feature(intrinsics)] +#![feature(rustc_attrs)] + +// From issue #15200 +#[rustc_intrinsic] +#[rustc_nounwind] +/// # Safety +pub const unsafe fn simd_insert<T, U>(x: T, idx: u32, val: U) -> T; + +fn main() {} diff --git a/tests/ui/empty_structs_with_brackets.fixed b/tests/ui/empty_structs_with_brackets.fixed index 419cf2354f8..22386245ffe 100644 --- a/tests/ui/empty_structs_with_brackets.fixed +++ b/tests/ui/empty_structs_with_brackets.fixed @@ -32,3 +32,17 @@ macro_rules! empty_struct { empty_struct!(FromMacro); fn main() {} + +mod issue15349 { + trait Bar<T> {} + impl<T> Bar<T> for [u8; 7] {} + + struct Foo<const N: usize>; + //~^ empty_structs_with_brackets + impl<const N: usize> Foo<N> + where + [u8; N]: Bar<[(); N]>, + { + fn foo() {} + } +} diff --git a/tests/ui/empty_structs_with_brackets.rs b/tests/ui/empty_structs_with_brackets.rs index 90c415c1220..5cb54b66134 100644 --- a/tests/ui/empty_structs_with_brackets.rs +++ b/tests/ui/empty_structs_with_brackets.rs @@ -32,3 +32,17 @@ macro_rules! empty_struct { empty_struct!(FromMacro); fn main() {} + +mod issue15349 { + trait Bar<T> {} + impl<T> Bar<T> for [u8; 7] {} + + struct Foo<const N: usize> {} + //~^ empty_structs_with_brackets + impl<const N: usize> Foo<N> + where + [u8; N]: Bar<[(); N]>, + { + fn foo() {} + } +} diff --git a/tests/ui/empty_structs_with_brackets.stderr b/tests/ui/empty_structs_with_brackets.stderr index 86ef43aa960..f662bb9423e 100644 --- a/tests/ui/empty_structs_with_brackets.stderr +++ b/tests/ui/empty_structs_with_brackets.stderr @@ -16,5 +16,13 @@ LL | struct MyEmptyTupleStruct(); // should trigger lint | = help: remove the brackets -error: aborting due to 2 previous errors +error: found empty brackets on struct declaration + --> tests/ui/empty_structs_with_brackets.rs:40:31 + | +LL | struct Foo<const N: usize> {} + | ^^^ + | + = help: remove the brackets + +error: aborting due to 3 previous errors diff --git a/tests/ui/entry_unfixable.stderr b/tests/ui/entry_unfixable.stderr index 0197d2ab4cf..f92f472512f 100644 --- a/tests/ui/entry_unfixable.stderr +++ b/tests/ui/entry_unfixable.stderr @@ -10,6 +10,7 @@ LL | | false LL | | } | |_____________^ | + = help: consider using the `Entry` API: https://doc.rust-lang.org/std/collections/struct.HashMap.html#entry-api = note: `-D clippy::map-entry` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::map_entry)]` @@ -24,6 +25,8 @@ LL | | } else { LL | | hm.insert(key, true); LL | | } | |_____^ + | + = help: consider using the `Entry` API: https://doc.rust-lang.org/std/collections/struct.HashMap.html#entry-api error: usage of `contains_key` followed by `insert` on a `HashMap` --> tests/ui/entry_unfixable.rs:80:13 @@ -36,6 +39,8 @@ LL | | let interner = INTERNER.lock().unwrap(); LL | | return Err(interner.resolve(name).unwrap().to_owned()); LL | | } | |_____________^ + | + = help: consider using the `Entry` API: https://doc.rust-lang.org/std/collections/struct.HashMap.html#entry-api error: aborting due to 3 previous errors diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 0ba631fda05..3d2b41b8fb8 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -1,3 +1,6 @@ +// we have some HELP annotations -- don't complain about them not being present everywhere +//@require-annotations-for-level: ERROR + #![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)] #![allow(unused)] #![allow( @@ -543,3 +546,47 @@ mod issue_13073 { //~^ redundant_closure } } + +fn issue_14789() { + _ = Some(1u8).map( + #[expect(clippy::redundant_closure)] + |a| foo(a), + ); + + _ = Some("foo").map( + #[expect(clippy::redundant_closure_for_method_calls)] + |s| s.to_owned(), + ); + + let _: Vec<u8> = None.map_or_else( + #[expect(clippy::redundant_closure)] + || vec![], + std::convert::identity, + ); +} + +fn issue8817() { + fn f(_: u32) -> u32 { + todo!() + } + let g = |_: u32| -> u32 { todo!() }; + struct S(u32); + enum MyError { + A(S), + } + + Some(5) + .map(f) + //~^ redundant_closure + //~| HELP: replace the closure with the function itself + .map(g) + //~^ redundant_closure + //~| HELP: replace the closure with the function itself + .map(S) + //~^ redundant_closure + //~| HELP: replace the closure with the tuple struct itself + .map(MyError::A) + //~^ redundant_closure + //~| HELP: replace the closure with the tuple variant itself + .unwrap(); // just for nicer formatting +} diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 4d8b29d450c..79d1103410d 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -1,3 +1,6 @@ +// we have some HELP annotations -- don't complain about them not being present everywhere +//@require-annotations-for-level: ERROR + #![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)] #![allow(unused)] #![allow( @@ -543,3 +546,47 @@ mod issue_13073 { //~^ redundant_closure } } + +fn issue_14789() { + _ = Some(1u8).map( + #[expect(clippy::redundant_closure)] + |a| foo(a), + ); + + _ = Some("foo").map( + #[expect(clippy::redundant_closure_for_method_calls)] + |s| s.to_owned(), + ); + + let _: Vec<u8> = None.map_or_else( + #[expect(clippy::redundant_closure)] + || vec![], + std::convert::identity, + ); +} + +fn issue8817() { + fn f(_: u32) -> u32 { + todo!() + } + let g = |_: u32| -> u32 { todo!() }; + struct S(u32); + enum MyError { + A(S), + } + + Some(5) + .map(|n| f(n)) + //~^ redundant_closure + //~| HELP: replace the closure with the function itself + .map(|n| g(n)) + //~^ redundant_closure + //~| HELP: replace the closure with the function itself + .map(|n| S(n)) + //~^ redundant_closure + //~| HELP: replace the closure with the tuple struct itself + .map(|n| MyError::A(n)) + //~^ redundant_closure + //~| HELP: replace the closure with the tuple variant itself + .unwrap(); // just for nicer formatting +} diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 8bc08add2fa..aa32ed1a38e 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> tests/ui/eta.rs:31:27 + --> tests/ui/eta.rs:34:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -8,31 +8,31 @@ LL | let a = Some(1u8).map(|a| foo(a)); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure)]` error: redundant closure - --> tests/ui/eta.rs:36:40 + --> tests/ui/eta.rs:39:40 | LL | let _: Option<Vec<u8>> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> tests/ui/eta.rs:39:35 + --> tests/ui/eta.rs:42:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` error: redundant closure - --> tests/ui/eta.rs:42:26 + --> tests/ui/eta.rs:45:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> tests/ui/eta.rs:51:27 + --> tests/ui/eta.rs:54:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> tests/ui/eta.rs:104:51 + --> tests/ui/eta.rs:107:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -41,178 +41,202 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = help: to override `-D warnings` add `#[allow(clippy::redundant_closure_for_method_calls)]` error: redundant closure - --> tests/ui/eta.rs:106:51 + --> tests/ui/eta.rs:109:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> tests/ui/eta.rs:109:42 + --> tests/ui/eta.rs:112:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> tests/ui/eta.rs:114:29 + --> tests/ui/eta.rs:117:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> tests/ui/eta.rs:116:27 + --> tests/ui/eta.rs:119:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> tests/ui/eta.rs:119:65 + --> tests/ui/eta.rs:122:65 | LL | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> tests/ui/eta.rs:136:23 + --> tests/ui/eta.rs:139:23 | LL | let _ = x.map(|x| x.parse::<i16>()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `str::parse::<i16>` error: redundant closure - --> tests/ui/eta.rs:189:22 + --> tests/ui/eta.rs:192:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> tests/ui/eta.rs:197:27 + --> tests/ui/eta.rs:200:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> tests/ui/eta.rs:203:27 + --> tests/ui/eta.rs:206:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> tests/ui/eta.rs:236:28 + --> tests/ui/eta.rs:239:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> tests/ui/eta.rs:238:28 + --> tests/ui/eta.rs:241:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> tests/ui/eta.rs:240:28 + --> tests/ui/eta.rs:243:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> tests/ui/eta.rs:248:21 + --> tests/ui/eta.rs:251:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> tests/ui/eta.rs:253:21 + --> tests/ui/eta.rs:256:21 | LL | Some(1).map(|n| in_loop(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `in_loop` error: redundant closure - --> tests/ui/eta.rs:347:18 + --> tests/ui/eta.rs:350:18 | LL | takes_fn_mut(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> tests/ui/eta.rs:351:19 + --> tests/ui/eta.rs:354:19 | LL | takes_fn_once(|| f()); | ^^^^^^ help: replace the closure with the function itself: `&mut f` error: redundant closure - --> tests/ui/eta.rs:356:26 + --> tests/ui/eta.rs:359:26 | LL | move || takes_fn_mut(|| f_used_once()) | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut f_used_once` error: redundant closure - --> tests/ui/eta.rs:369:19 + --> tests/ui/eta.rs:372:19 | LL | array_opt.map(|a| a.as_slice()); | ^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8; 3]>::as_slice` error: redundant closure - --> tests/ui/eta.rs:373:19 + --> tests/ui/eta.rs:376:19 | LL | slice_opt.map(|s| s.len()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `<[u8]>::len` error: redundant closure - --> tests/ui/eta.rs:377:17 + --> tests/ui/eta.rs:380:17 | LL | ptr_opt.map(|p| p.is_null()); | ^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<*const usize>::is_null` error: redundant closure - --> tests/ui/eta.rs:382:17 + --> tests/ui/eta.rs:385:17 | LL | dyn_opt.map(|d| d.method_on_dyn()); | ^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `<dyn TestTrait>::method_on_dyn` error: redundant closure - --> tests/ui/eta.rs:443:19 + --> tests/ui/eta.rs:446:19 | LL | let _ = f(&0, |x, y| f2(x, y)); | ^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `f2` error: redundant closure - --> tests/ui/eta.rs:472:22 + --> tests/ui/eta.rs:475:22 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `Test::method` error: redundant closure - --> tests/ui/eta.rs:477:22 + --> tests/ui/eta.rs:480:22 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `super::Outer::method` error: redundant closure - --> tests/ui/eta.rs:491:18 + --> tests/ui/eta.rs:494:18 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `test_mod::Test::method` error: redundant closure - --> tests/ui/eta.rs:499:30 + --> tests/ui/eta.rs:502:30 | LL | test.map(|t| t.method()) | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `crate::issue_10854::d::Test::method` error: redundant closure - --> tests/ui/eta.rs:519:38 + --> tests/ui/eta.rs:522:38 | LL | let x = Box::new(|| None.map(|x| f(x))); | ^^^^^^^^ help: replace the closure with the function itself: `&f` error: redundant closure - --> tests/ui/eta.rs:524:38 + --> tests/ui/eta.rs:527:38 | LL | let x = Box::new(|| None.map(|x| f(x))); | ^^^^^^^^ help: replace the closure with the function itself: `f` error: redundant closure - --> tests/ui/eta.rs:542:35 + --> tests/ui/eta.rs:545:35 | LL | let _field = bind.or_else(|| get_default()).unwrap(); | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `get_default` -error: aborting due to 35 previous errors +error: redundant closure + --> tests/ui/eta.rs:588:14 + | +LL | .map(|n| MyError::A(n)) + | ^^^^^^^^^^^^^^^^^ help: replace the closure with the tuple variant itself: `MyError::A` + +error: redundant closure + --> tests/ui/eta.rs:585:14 + | +LL | .map(|n| S(n)) + | ^^^^^^^^ help: replace the closure with the tuple struct itself: `S` + +error: redundant closure + --> tests/ui/eta.rs:582:14 + | +LL | .map(|n| g(n)) + | ^^^^^^^^ help: replace the closure with the function itself: `g` + +error: redundant closure + --> tests/ui/eta.rs:579:14 + | +LL | .map(|n| f(n)) + | ^^^^^^^^ help: replace the closure with the function itself: `f` + +error: aborting due to 39 previous errors diff --git a/tests/ui/exhaustive_items.fixed b/tests/ui/exhaustive_items.fixed index 79c74aeefbd..3b2f33dbd2c 100644 --- a/tests/ui/exhaustive_items.fixed +++ b/tests/ui/exhaustive_items.fixed @@ -1,3 +1,4 @@ +#![feature(default_field_values)] #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)] #![allow(unused)] @@ -90,3 +91,9 @@ pub mod structs { pub bar: String, } } + +pub mod issue14992 { + pub struct A { + pub a: isize = 42, + } +} diff --git a/tests/ui/exhaustive_items.rs b/tests/ui/exhaustive_items.rs index 4e851f4c492..b0a6a717076 100644 --- a/tests/ui/exhaustive_items.rs +++ b/tests/ui/exhaustive_items.rs @@ -1,3 +1,4 @@ +#![feature(default_field_values)] #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)] #![allow(unused)] @@ -87,3 +88,9 @@ pub mod structs { pub bar: String, } } + +pub mod issue14992 { + pub struct A { + pub a: isize = 42, + } +} diff --git a/tests/ui/exhaustive_items.stderr b/tests/ui/exhaustive_items.stderr index c92c8a9efaa..55928fa458d 100644 --- a/tests/ui/exhaustive_items.stderr +++ b/tests/ui/exhaustive_items.stderr @@ -1,5 +1,5 @@ error: exported enums should not be exhaustive - --> tests/ui/exhaustive_items.rs:9:5 + --> tests/ui/exhaustive_items.rs:10:5 | LL | / pub enum Exhaustive { LL | | @@ -11,7 +11,7 @@ LL | | } | |_____^ | note: the lint level is defined here - --> tests/ui/exhaustive_items.rs:1:9 + --> tests/ui/exhaustive_items.rs:2:9 | LL | #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -22,7 +22,7 @@ LL ~ pub enum Exhaustive { | error: exported enums should not be exhaustive - --> tests/ui/exhaustive_items.rs:19:5 + --> tests/ui/exhaustive_items.rs:20:5 | LL | / pub enum ExhaustiveWithAttrs { LL | | @@ -40,7 +40,7 @@ LL ~ pub enum ExhaustiveWithAttrs { | error: exported structs should not be exhaustive - --> tests/ui/exhaustive_items.rs:55:5 + --> tests/ui/exhaustive_items.rs:56:5 | LL | / pub struct Exhaustive { LL | | @@ -50,7 +50,7 @@ LL | | } | |_____^ | note: the lint level is defined here - --> tests/ui/exhaustive_items.rs:1:35 + --> tests/ui/exhaustive_items.rs:2:35 | LL | #![deny(clippy::exhaustive_enums, clippy::exhaustive_structs)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/exit1_compile_flag_test.rs b/tests/ui/exit1_compile_flag_test.rs new file mode 100644 index 00000000000..9f83ed32533 --- /dev/null +++ b/tests/ui/exit1_compile_flag_test.rs @@ -0,0 +1,17 @@ +//@compile-flags: --test +#![warn(clippy::exit)] + +fn not_main() { + if true { + std::process::exit(4); + //~^ exit + } +} + +fn main() { + if true { + std::process::exit(2); + }; + not_main(); + std::process::exit(1); +} diff --git a/tests/ui/exit1_compile_flag_test.stderr b/tests/ui/exit1_compile_flag_test.stderr new file mode 100644 index 00000000000..6e33c39f0d7 --- /dev/null +++ b/tests/ui/exit1_compile_flag_test.stderr @@ -0,0 +1,11 @@ +error: usage of `process::exit` + --> tests/ui/exit1_compile_flag_test.rs:6:9 + | +LL | std::process::exit(4); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::exit` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::exit)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/exit2_compile_flag_test.rs b/tests/ui/exit2_compile_flag_test.rs new file mode 100644 index 00000000000..0b994ebc56c --- /dev/null +++ b/tests/ui/exit2_compile_flag_test.rs @@ -0,0 +1,15 @@ +//@compile-flags: --test +#![warn(clippy::exit)] + +fn also_not_main() { + std::process::exit(3); + //~^ exit +} + +fn main() { + if true { + std::process::exit(2); + }; + also_not_main(); + std::process::exit(1); +} diff --git a/tests/ui/exit2_compile_flag_test.stderr b/tests/ui/exit2_compile_flag_test.stderr new file mode 100644 index 00000000000..51eb26e9c2a --- /dev/null +++ b/tests/ui/exit2_compile_flag_test.stderr @@ -0,0 +1,11 @@ +error: usage of `process::exit` + --> tests/ui/exit2_compile_flag_test.rs:5:5 + | +LL | std::process::exit(3); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::exit` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::exit)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/exit3_compile_flag_test.rs b/tests/ui/exit3_compile_flag_test.rs new file mode 100644 index 00000000000..f8131ead2da --- /dev/null +++ b/tests/ui/exit3_compile_flag_test.rs @@ -0,0 +1,11 @@ +//@ check-pass +//@compile-flags: --test + +#![warn(clippy::exit)] + +fn main() { + if true { + std::process::exit(2); + }; + std::process::exit(1); +} diff --git a/tests/ui/exit4.rs b/tests/ui/exit4.rs new file mode 100644 index 00000000000..821a26fd78b --- /dev/null +++ b/tests/ui/exit4.rs @@ -0,0 +1,8 @@ +//@ check-pass +//@compile-flags: --test + +#![warn(clippy::exit)] + +fn main() { + std::process::exit(0) +} diff --git a/tests/ui/expect.rs b/tests/ui/expect.rs index 8f7379f0021..1ab01ecfcfe 100644 --- a/tests/ui/expect.rs +++ b/tests/ui/expect.rs @@ -16,7 +16,26 @@ fn expect_result() { //~^ expect_used } +#[allow(clippy::ok_expect)] +#[allow(clippy::err_expect)] +fn issue_15247() { + let x: Result<u8, u8> = Err(0); + x.ok().expect("Huh"); + //~^ expect_used + + { x.ok() }.expect("..."); + //~^ expect_used + + let y: Result<u8, u8> = Ok(0); + y.err().expect("Huh"); + //~^ expect_used + + { y.err() }.expect("..."); + //~^ expect_used +} + fn main() { expect_option(); expect_result(); + issue_15247(); } diff --git a/tests/ui/expect.stderr b/tests/ui/expect.stderr index 70cf3072003..353fb776531 100644 --- a/tests/ui/expect.stderr +++ b/tests/ui/expect.stderr @@ -24,5 +24,37 @@ LL | let _ = res.expect_err(""); | = note: if this value is an `Ok`, it will panic -error: aborting due to 3 previous errors +error: used `expect()` on an `Option` value + --> tests/ui/expect.rs:23:5 + | +LL | x.ok().expect("Huh"); + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `expect()` on an `Option` value + --> tests/ui/expect.rs:26:5 + | +LL | { x.ok() }.expect("..."); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `expect()` on an `Option` value + --> tests/ui/expect.rs:30:5 + | +LL | y.err().expect("Huh"); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: used `expect()` on an `Option` value + --> tests/ui/expect.rs:33:5 + | +LL | { y.err() }.expect("..."); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if this value is `None`, it will panic + +error: aborting due to 7 previous errors diff --git a/tests/ui/expect_fun_call.fixed b/tests/ui/expect_fun_call.fixed index 73eaebf773c..b923521afde 100644 --- a/tests/ui/expect_fun_call.fixed +++ b/tests/ui/expect_fun_call.fixed @@ -90,17 +90,30 @@ fn main() { "foo" } - Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) }); + const fn const_evaluable() -> &'static str { + "foo" + } + + Some("foo").unwrap_or_else(|| panic!("{}", get_string())); //~^ expect_fun_call - Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) }); + Some("foo").unwrap_or_else(|| panic!("{}", get_string())); //~^ expect_fun_call - Some("foo").unwrap_or_else(|| { panic!("{}", get_string()) }); + Some("foo").unwrap_or_else(|| panic!("{}", get_string())); //~^ expect_fun_call - Some("foo").unwrap_or_else(|| { panic!("{}", get_static_str()) }); + Some("foo").unwrap_or_else(|| panic!("{}", get_static_str())); //~^ expect_fun_call - Some("foo").unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) }); + Some("foo").unwrap_or_else(|| panic!("{}", get_non_static_str(&0))); + //~^ expect_fun_call + + Some("foo").unwrap_or_else(|| panic!("{}", const_evaluable())); //~^ expect_fun_call + + const { + Some("foo").expect(const_evaluable()); + } + + Some("foo").expect(const { const_evaluable() }); } //Issue #3839 @@ -122,4 +135,15 @@ fn main() { let format_capture_and_value: Option<i32> = None; format_capture_and_value.unwrap_or_else(|| panic!("{error_code}, {}", 1)); //~^ expect_fun_call + + // Issue #15056 + let a = false; + Some(5).expect(if a { "a" } else { "b" }); + + let return_in_expect: Option<i32> = None; + return_in_expect.expect(if true { + "Error" + } else { + return; + }); } diff --git a/tests/ui/expect_fun_call.rs b/tests/ui/expect_fun_call.rs index ecebc9ebfb6..bc58d24bc81 100644 --- a/tests/ui/expect_fun_call.rs +++ b/tests/ui/expect_fun_call.rs @@ -90,6 +90,10 @@ fn main() { "foo" } + const fn const_evaluable() -> &'static str { + "foo" + } + Some("foo").expect(&get_string()); //~^ expect_fun_call Some("foo").expect(get_string().as_ref()); @@ -101,6 +105,15 @@ fn main() { //~^ expect_fun_call Some("foo").expect(get_non_static_str(&0)); //~^ expect_fun_call + + Some("foo").expect(const_evaluable()); + //~^ expect_fun_call + + const { + Some("foo").expect(const_evaluable()); + } + + Some("foo").expect(const { const_evaluable() }); } //Issue #3839 @@ -122,4 +135,15 @@ fn main() { let format_capture_and_value: Option<i32> = None; format_capture_and_value.expect(&format!("{error_code}, {}", 1)); //~^ expect_fun_call + + // Issue #15056 + let a = false; + Some(5).expect(if a { "a" } else { "b" }); + + let return_in_expect: Option<i32> = None; + return_in_expect.expect(if true { + "Error" + } else { + return; + }); } diff --git a/tests/ui/expect_fun_call.stderr b/tests/ui/expect_fun_call.stderr index 36713196cb9..0692ecb4862 100644 --- a/tests/ui/expect_fun_call.stderr +++ b/tests/ui/expect_fun_call.stderr @@ -38,58 +38,64 @@ LL | Some("foo").expect(format!("{} {}", 1, 2).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{} {}", 1, 2))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:93:21 + --> tests/ui/expect_fun_call.rs:97:21 | LL | Some("foo").expect(&get_string()); - | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", get_string()))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:95:21 + --> tests/ui/expect_fun_call.rs:99:21 | LL | Some("foo").expect(get_string().as_ref()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", get_string()))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:97:21 + --> tests/ui/expect_fun_call.rs:101:21 | LL | Some("foo").expect(get_string().as_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", get_string()))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:100:21 + --> tests/ui/expect_fun_call.rs:104:21 | LL | Some("foo").expect(get_static_str()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_static_str()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", get_static_str()))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:102:21 + --> tests/ui/expect_fun_call.rs:106:21 | LL | Some("foo").expect(get_non_static_str(&0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| { panic!("{}", get_non_static_str(&0).to_string()) })` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", get_non_static_str(&0)))` + +error: function call inside of `expect` + --> tests/ui/expect_fun_call.rs:109:21 + | +LL | Some("foo").expect(const_evaluable()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{}", const_evaluable()))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:107:16 + --> tests/ui/expect_fun_call.rs:120:16 | LL | Some(true).expect(&format!("key {}, {}", 1, 2)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("key {}, {}", 1, 2))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:114:17 + --> tests/ui/expect_fun_call.rs:127:17 | LL | opt_ref.expect(&format!("{:?}", opt_ref)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{:?}", opt_ref))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:119:20 + --> tests/ui/expect_fun_call.rs:132:20 | LL | format_capture.expect(&format!("{error_code}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}"))` error: function call inside of `expect` - --> tests/ui/expect_fun_call.rs:123:30 + --> tests/ui/expect_fun_call.rs:136:30 | LL | format_capture_and_value.expect(&format!("{error_code}, {}", 1)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| panic!("{error_code}, {}", 1))` -error: aborting due to 15 previous errors +error: aborting due to 16 previous errors diff --git a/tests/ui/explicit_iter_loop.fixed b/tests/ui/explicit_iter_loop.fixed index f246ec61800..bffa1c4cf40 100644 --- a/tests/ui/explicit_iter_loop.fixed +++ b/tests/ui/explicit_iter_loop.fixed @@ -77,11 +77,11 @@ fn main() { struct NoIntoIter(); impl NoIntoIter { - fn iter(&self) -> slice::Iter<u8> { + fn iter(&self) -> slice::Iter<'_, u8> { unimplemented!() } - fn iter_mut(&mut self) -> slice::IterMut<u8> { + fn iter_mut(&mut self) -> slice::IterMut<'_, u8> { unimplemented!() } } diff --git a/tests/ui/explicit_iter_loop.rs b/tests/ui/explicit_iter_loop.rs index 35f4fb7097d..6a5a3dd00ba 100644 --- a/tests/ui/explicit_iter_loop.rs +++ b/tests/ui/explicit_iter_loop.rs @@ -77,11 +77,11 @@ fn main() { struct NoIntoIter(); impl NoIntoIter { - fn iter(&self) -> slice::Iter<u8> { + fn iter(&self) -> slice::Iter<'_, u8> { unimplemented!() } - fn iter_mut(&mut self) -> slice::IterMut<u8> { + fn iter_mut(&mut self) -> slice::IterMut<'_, u8> { unimplemented!() } } diff --git a/tests/ui/filter_map_bool_then.fixed b/tests/ui/filter_map_bool_then.fixed index b3e112f19eb..d370b85a67e 100644 --- a/tests/ui/filter_map_bool_then.fixed +++ b/tests/ui/filter_map_bool_then.fixed @@ -89,3 +89,24 @@ fn issue11503() { let _: Vec<usize> = bools.iter().enumerate().filter(|&(i, b)| ****b).map(|(i, b)| i).collect(); //~^ filter_map_bool_then } + +fn issue15047() { + #[derive(Clone, Copy)] + enum MyEnum { + A, + B, + C, + } + + macro_rules! foo { + ($e:expr) => { + $e + 1 + }; + } + + let x = 1; + let _ = [(MyEnum::A, "foo", 1i32)] + .iter() + .filter(|&(t, s, i)| matches!(t, MyEnum::A if s.starts_with("bar"))).map(|(t, s, i)| foo!(x)); + //~^ filter_map_bool_then +} diff --git a/tests/ui/filter_map_bool_then.rs b/tests/ui/filter_map_bool_then.rs index d996b3cb3c5..12295cc2482 100644 --- a/tests/ui/filter_map_bool_then.rs +++ b/tests/ui/filter_map_bool_then.rs @@ -89,3 +89,24 @@ fn issue11503() { let _: Vec<usize> = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); //~^ filter_map_bool_then } + +fn issue15047() { + #[derive(Clone, Copy)] + enum MyEnum { + A, + B, + C, + } + + macro_rules! foo { + ($e:expr) => { + $e + 1 + }; + } + + let x = 1; + let _ = [(MyEnum::A, "foo", 1i32)] + .iter() + .filter_map(|(t, s, i)| matches!(t, MyEnum::A if s.starts_with("bar")).then(|| foo!(x))); + //~^ filter_map_bool_then +} diff --git a/tests/ui/filter_map_bool_then.stderr b/tests/ui/filter_map_bool_then.stderr index aeb1baeb35e..edf6c655939 100644 --- a/tests/ui/filter_map_bool_then.stderr +++ b/tests/ui/filter_map_bool_then.stderr @@ -61,5 +61,11 @@ error: usage of `bool::then` in `filter_map` LL | let _: Vec<usize> = bools.iter().enumerate().filter_map(|(i, b)| b.then(|| i)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(i, b)| ****b).map(|(i, b)| i)` -error: aborting due to 10 previous errors +error: usage of `bool::then` in `filter_map` + --> tests/ui/filter_map_bool_then.rs:110:10 + | +LL | .filter_map(|(t, s, i)| matches!(t, MyEnum::A if s.starts_with("bar")).then(|| foo!(x))); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `filter` then `map` instead: `filter(|&(t, s, i)| matches!(t, MyEnum::A if s.starts_with("bar"))).map(|(t, s, i)| foo!(x))` + +error: aborting due to 11 previous errors diff --git a/tests/ui/flat_map_identity.fixed b/tests/ui/flat_map_identity.fixed index f6206232612..06a3eee9d84 100644 --- a/tests/ui/flat_map_identity.fixed +++ b/tests/ui/flat_map_identity.fixed @@ -16,3 +16,16 @@ fn main() { let _ = iterator.flatten(); //~^ flat_map_identity } + +fn issue15198() { + let x = [[1, 2], [3, 4]]; + // don't lint: this is an `Iterator<Item = &[i32, i32]>` + // match ergonomics makes the binding patterns into references + // so that its type changes to `Iterator<Item = [&i32, &i32]>` + let _ = x.iter().flat_map(|[x, y]| [x, y]); + let _ = x.iter().flat_map(|x| [x[0]]); + + // no match ergonomics for `[i32, i32]` + let _ = x.iter().copied().flatten(); + //~^ flat_map_identity +} diff --git a/tests/ui/flat_map_identity.rs b/tests/ui/flat_map_identity.rs index c59e749474e..1cab7d559d8 100644 --- a/tests/ui/flat_map_identity.rs +++ b/tests/ui/flat_map_identity.rs @@ -16,3 +16,16 @@ fn main() { let _ = iterator.flat_map(|x| return x); //~^ flat_map_identity } + +fn issue15198() { + let x = [[1, 2], [3, 4]]; + // don't lint: this is an `Iterator<Item = &[i32, i32]>` + // match ergonomics makes the binding patterns into references + // so that its type changes to `Iterator<Item = [&i32, &i32]>` + let _ = x.iter().flat_map(|[x, y]| [x, y]); + let _ = x.iter().flat_map(|x| [x[0]]); + + // no match ergonomics for `[i32, i32]` + let _ = x.iter().copied().flat_map(|[x, y]| [x, y]); + //~^ flat_map_identity +} diff --git a/tests/ui/flat_map_identity.stderr b/tests/ui/flat_map_identity.stderr index 75137f5d9e5..18c863bf96d 100644 --- a/tests/ui/flat_map_identity.stderr +++ b/tests/ui/flat_map_identity.stderr @@ -19,5 +19,11 @@ error: use of `flat_map` with an identity function LL | let _ = iterator.flat_map(|x| return x); | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` -error: aborting due to 3 previous errors +error: use of `flat_map` with an identity function + --> tests/ui/flat_map_identity.rs:29:31 + | +LL | let _ = x.iter().copied().flat_map(|[x, y]| [x, y]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `flatten()` + +error: aborting due to 4 previous errors diff --git a/tests/ui/float_equality_without_abs.rs b/tests/ui/float_equality_without_abs.rs index a1548db6710..e1dd7902683 100644 --- a/tests/ui/float_equality_without_abs.rs +++ b/tests/ui/float_equality_without_abs.rs @@ -1,8 +1,8 @@ +#![feature(f128)] +#![feature(f16)] #![warn(clippy::float_equality_without_abs)] //@no-rustfix: suggestions cause type ambiguity -// FIXME(f16_f128): add tests for these types when abs is available - pub fn is_roughly_equal(a: f32, b: f32) -> bool { (a - b) < f32::EPSILON //~^ float_equality_without_abs @@ -44,10 +44,20 @@ pub fn main() { let _ = f32::EPSILON > 1.0 - 2.0; //~^ float_equality_without_abs + let _ = (a as f16 - b as f16) < f16::EPSILON; + //~^ float_equality_without_abs + + let _ = (a as f128 - b as f128) < f128::EPSILON; + //~^ float_equality_without_abs + // those are correct + let _ = (a as f16 - b as f16).abs() < f16::EPSILON; let _ = (a - b).abs() < f32::EPSILON; let _ = (a as f64 - b as f64).abs() < f64::EPSILON; + let _ = (a as f128 - b as f128).abs() < f128::EPSILON; + let _ = f16::EPSILON > (a as f16 - b as f16).abs(); let _ = f32::EPSILON > (a - b).abs(); let _ = f64::EPSILON > (a as f64 - b as f64).abs(); + let _ = f128::EPSILON > (a as f128 - b as f128).abs(); } diff --git a/tests/ui/float_equality_without_abs.stderr b/tests/ui/float_equality_without_abs.stderr index d4c89ce72ba..55a150dead5 100644 --- a/tests/ui/float_equality_without_abs.stderr +++ b/tests/ui/float_equality_without_abs.stderr @@ -89,5 +89,21 @@ LL | let _ = f32::EPSILON > 1.0 - 2.0; | | | help: add `.abs()`: `(1.0 - 2.0).abs()` -error: aborting due to 11 previous errors +error: float equality check without `.abs()` + --> tests/ui/float_equality_without_abs.rs:47:13 + | +LL | let _ = (a as f16 - b as f16) < f16::EPSILON; + | ---------------------^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a as f16 - b as f16).abs()` + +error: float equality check without `.abs()` + --> tests/ui/float_equality_without_abs.rs:50:13 + | +LL | let _ = (a as f128 - b as f128) < f128::EPSILON; + | -----------------------^^^^^^^^^^^^^^^^ + | | + | help: add `.abs()`: `(a as f128 - b as f128).abs()` + +error: aborting due to 13 previous errors diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed index 83aeddb2a1f..884bae00432 100644 --- a/tests/ui/floating_point_mul_add.fixed +++ b/tests/ui/floating_point_mul_add.fixed @@ -69,3 +69,47 @@ fn _issue11831() { let _ = a + b * c; } + +fn _issue14897() { + let x = 1.0; + let _ = x * 2.0 + 0.5; // should not suggest mul_add + let _ = 0.5 + x * 2.0; // should not suggest mul_add + let _ = 0.5 + x * 1.2; // should not suggest mul_add + let _ = 1.2 + x * 1.2; // should not suggest mul_add + + let x = -1.0; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = { 4.0 }; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = if 1 > 2 { 1.0 } else { 2.0 }; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = 2.4 + 1.2; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let f = || 4.0; + let x = f(); + let _ = 0.5 + f() * 1.2; // should not suggest mul_add + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = 0.1; + let y = x; + let z = y; + let _ = 0.5 + z * 1.2; // should not suggest mul_add + + let _ = 2.0f64.mul_add(x, 0.5); + //~^ suboptimal_flops + let _ = 2.0f64.mul_add(x, 0.5); + //~^ suboptimal_flops + + let _ = 2.0f64.mul_add(4.0, x); + //~^ suboptimal_flops + + let y: f64 = 1.0; + let _ = y.mul_add(2.0, 0.5); + //~^ suboptimal_flops + let _ = 1.0f64.mul_add(2.0, 0.5); + //~^ suboptimal_flops +} diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs index 039ee8d053f..9ceb2ec9606 100644 --- a/tests/ui/floating_point_mul_add.rs +++ b/tests/ui/floating_point_mul_add.rs @@ -69,3 +69,47 @@ fn _issue11831() { let _ = a + b * c; } + +fn _issue14897() { + let x = 1.0; + let _ = x * 2.0 + 0.5; // should not suggest mul_add + let _ = 0.5 + x * 2.0; // should not suggest mul_add + let _ = 0.5 + x * 1.2; // should not suggest mul_add + let _ = 1.2 + x * 1.2; // should not suggest mul_add + + let x = -1.0; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = { 4.0 }; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = if 1 > 2 { 1.0 } else { 2.0 }; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = 2.4 + 1.2; + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let f = || 4.0; + let x = f(); + let _ = 0.5 + f() * 1.2; // should not suggest mul_add + let _ = 0.5 + x * 1.2; // should not suggest mul_add + + let x = 0.1; + let y = x; + let z = y; + let _ = 0.5 + z * 1.2; // should not suggest mul_add + + let _ = 0.5 + 2.0 * x; + //~^ suboptimal_flops + let _ = 2.0 * x + 0.5; + //~^ suboptimal_flops + + let _ = x + 2.0 * 4.0; + //~^ suboptimal_flops + + let y: f64 = 1.0; + let _ = y * 2.0 + 0.5; + //~^ suboptimal_flops + let _ = 1.0 * 2.0 + 0.5; + //~^ suboptimal_flops +} diff --git a/tests/ui/floating_point_mul_add.stderr b/tests/ui/floating_point_mul_add.stderr index 6482127bcc0..dad65ddf2ec 100644 --- a/tests/ui/floating_point_mul_add.stderr +++ b/tests/ui/floating_point_mul_add.stderr @@ -79,5 +79,35 @@ error: multiply and add expressions can be calculated more efficiently and accur LL | let _ = a - (b * u as f64); | ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)` -error: aborting due to 13 previous errors +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:102:13 + | +LL | let _ = 0.5 + 2.0 * x; + | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(x, 0.5)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:104:13 + | +LL | let _ = 2.0 * x + 0.5; + | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(x, 0.5)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:107:13 + | +LL | let _ = x + 2.0 * 4.0; + | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, x)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:111:13 + | +LL | let _ = y * 2.0 + 0.5; + | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(2.0, 0.5)` + +error: multiply and add expressions can be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:113:13 + | +LL | let _ = 1.0 * 2.0 + 0.5; + | ^^^^^^^^^^^^^^^ help: consider using: `1.0f64.mul_add(2.0, 0.5)` + +error: aborting due to 18 previous errors diff --git a/tests/ui/four_forward_slashes_bare_cr.rs b/tests/ui/four_forward_slashes_bare_cr.rs new file mode 100644 index 00000000000..19123cd206e --- /dev/null +++ b/tests/ui/four_forward_slashes_bare_cr.rs @@ -0,0 +1,6 @@ +//@no-rustfix +#![warn(clippy::four_forward_slashes)] + +//~v four_forward_slashes +//// nondoc comment with bare CR: ' ' +fn main() {} diff --git a/tests/ui/four_forward_slashes_bare_cr.stderr b/tests/ui/four_forward_slashes_bare_cr.stderr new file mode 100644 index 00000000000..64e70b97db9 --- /dev/null +++ b/tests/ui/four_forward_slashes_bare_cr.stderr @@ -0,0 +1,14 @@ +error: this item has comments with 4 forward slashes (`////`). These look like doc comments, but they aren't + --> tests/ui/four_forward_slashes_bare_cr.rs:5:1 + | +LL | / //// nondoc comment with bare CR: '␍' +LL | | fn main() {} + | |_^ + | + = help: make this a doc comment by removing one `/` + = note: bare CR characters are not allowed in doc comments + = note: `-D clippy::four-forward-slashes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::four_forward_slashes)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/from_str_radix_10.fixed b/tests/ui/from_str_radix_10.fixed index 4b8fd778685..47d24167e56 100644 --- a/tests/ui/from_str_radix_10.fixed +++ b/tests/ui/from_str_radix_10.fixed @@ -74,3 +74,13 @@ fn issue_12731() { let _ = u32::from_str_radix("123", 10); } } + +fn fix_str_ref_check() { + #![allow(clippy::needless_borrow)] + let s = "1"; + let _ = s.parse::<u32>().unwrap(); + //~^ from_str_radix_10 + let s_ref = &s; + let _ = s_ref.parse::<u32>().unwrap(); + //~^ from_str_radix_10 +} diff --git a/tests/ui/from_str_radix_10.rs b/tests/ui/from_str_radix_10.rs index 89002b11a99..952e19b57a0 100644 --- a/tests/ui/from_str_radix_10.rs +++ b/tests/ui/from_str_radix_10.rs @@ -74,3 +74,13 @@ fn issue_12731() { let _ = u32::from_str_radix("123", 10); } } + +fn fix_str_ref_check() { + #![allow(clippy::needless_borrow)] + let s = "1"; + let _ = u32::from_str_radix(&s, 10).unwrap(); + //~^ from_str_radix_10 + let s_ref = &s; + let _ = u32::from_str_radix(&s_ref, 10).unwrap(); + //~^ from_str_radix_10 +} diff --git a/tests/ui/from_str_radix_10.stderr b/tests/ui/from_str_radix_10.stderr index c693e8f50ff..d4e6c3657f2 100644 --- a/tests/ui/from_str_radix_10.stderr +++ b/tests/ui/from_str_radix_10.stderr @@ -49,5 +49,17 @@ error: this call to `from_str_radix` can be replaced with a call to `str::parse` LL | i32::from_str_radix(&stringier, 10)?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `stringier.parse::<i32>()` -error: aborting due to 8 previous errors +error: this call to `from_str_radix` can be replaced with a call to `str::parse` + --> tests/ui/from_str_radix_10.rs:81:13 + | +LL | let _ = u32::from_str_radix(&s, 10).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s.parse::<u32>()` + +error: this call to `from_str_radix` can be replaced with a call to `str::parse` + --> tests/ui/from_str_radix_10.rs:84:13 + | +LL | let _ = u32::from_str_radix(&s_ref, 10).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `s_ref.parse::<u32>()` + +error: aborting due to 10 previous errors diff --git a/tests/ui/functions_maxlines.rs b/tests/ui/functions_maxlines.rs index e0990dadaaa..b0714552461 100644 --- a/tests/ui/functions_maxlines.rs +++ b/tests/ui/functions_maxlines.rs @@ -1,3 +1,4 @@ +#![allow(clippy::unused_unit, clippy::missing_safety_doc)] #![warn(clippy::too_many_lines)] fn good_lines() { @@ -55,7 +56,8 @@ fn good_lines() { println!("This is good."); } -fn bad_lines() { +#[allow(unused)] // the attr shouldn't get included in the highlight +pub async unsafe extern "Rust" fn bad_lines() -> () { //~^ too_many_lines println!("Dont get confused by braces: {{}}"); @@ -162,4 +164,115 @@ fn bad_lines() { println!("This is bad."); } +struct Foo; +impl Foo { + #[allow(unused)] // the attr shouldn't get included in the highlight + pub async unsafe extern "Rust" fn bad_lines() -> () { + //~^ too_many_lines + + println!("Dont get confused by braces: {{}}"); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + println!("This is bad."); + } +} + fn main() {} diff --git a/tests/ui/functions_maxlines.stderr b/tests/ui/functions_maxlines.stderr index f42a2b2a22a..4c3faf45c47 100644 --- a/tests/ui/functions_maxlines.stderr +++ b/tests/ui/functions_maxlines.stderr @@ -1,17 +1,17 @@ -error: this function has too many lines (102/100) - --> tests/ui/functions_maxlines.rs:58:1 +error: this function has too many lines (104/100) + --> tests/ui/functions_maxlines.rs:60:1 | -LL | / fn bad_lines() { -LL | | -LL | | -LL | | println!("Dont get confused by braces: {{}}"); -... | -LL | | println!("This is bad."); -LL | | } - | |_^ +LL | pub async unsafe extern "Rust" fn bad_lines() -> () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::too-many-lines` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::too_many_lines)]` -error: aborting due to 1 previous error +error: this function has too many lines (104/100) + --> tests/ui/functions_maxlines.rs:170:5 + | +LL | pub async unsafe extern "Rust" fn bad_lines() -> () { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors diff --git a/tests/ui/identity_op.fixed b/tests/ui/identity_op.fixed index a1b55602998..4e14e1a5e33 100644 --- a/tests/ui/identity_op.fixed +++ b/tests/ui/identity_op.fixed @@ -312,3 +312,49 @@ fn issue_13470() { let _: u64 = 1u64 + ((x as i32 + y as i32) as u64); //~^ identity_op } + +fn issue_14932() { + let _ = 0usize + &Default::default(); // no error + + 0usize + &Default::default(); // no error + + <usize as Default>::default(); + //~^ identity_op + + let _ = usize::default(); + //~^ identity_op + + let _n: usize = Default::default(); + //~^ identity_op +} + +// Expr's type can be inferred by the function's return type +fn issue_14932_2() -> usize { + Default::default() + //~^ identity_op +} + +trait Def { + fn def() -> Self; +} + +impl Def for usize { + fn def() -> Self { + 0 + } +} + +fn issue_14932_3() { + let _ = 0usize + &Def::def(); // no error + + 0usize + &Def::def(); // no error + + <usize as Def>::def(); + //~^ identity_op + + let _ = usize::def(); + //~^ identity_op + + let _n: usize = Def::def(); + //~^ identity_op +} diff --git a/tests/ui/identity_op.rs b/tests/ui/identity_op.rs index f603e1078e4..ebbef5723ff 100644 --- a/tests/ui/identity_op.rs +++ b/tests/ui/identity_op.rs @@ -312,3 +312,49 @@ fn issue_13470() { let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64); //~^ identity_op } + +fn issue_14932() { + let _ = 0usize + &Default::default(); // no error + + 0usize + &Default::default(); // no error + + 0usize + &<usize as Default>::default(); + //~^ identity_op + + let _ = 0usize + &usize::default(); + //~^ identity_op + + let _n: usize = 0usize + &Default::default(); + //~^ identity_op +} + +// Expr's type can be inferred by the function's return type +fn issue_14932_2() -> usize { + 0usize + &Default::default() + //~^ identity_op +} + +trait Def { + fn def() -> Self; +} + +impl Def for usize { + fn def() -> Self { + 0 + } +} + +fn issue_14932_3() { + let _ = 0usize + &Def::def(); // no error + + 0usize + &Def::def(); // no error + + 0usize + &<usize as Def>::def(); + //~^ identity_op + + let _ = 0usize + &usize::def(); + //~^ identity_op + + let _n: usize = 0usize + &Def::def(); + //~^ identity_op +} diff --git a/tests/ui/identity_op.stderr b/tests/ui/identity_op.stderr index 8f9c2b603c4..24fa5db08ce 100644 --- a/tests/ui/identity_op.stderr +++ b/tests/ui/identity_op.stderr @@ -379,5 +379,47 @@ error: this operation has no effect LL | let _: u64 = 1u64 + ((x as i32 + y as i32) as u64 + 0u64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `((x as i32 + y as i32) as u64)` -error: aborting due to 63 previous errors +error: this operation has no effect + --> tests/ui/identity_op.rs:321:5 + | +LL | 0usize + &<usize as Default>::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `<usize as Default>::default()` + +error: this operation has no effect + --> tests/ui/identity_op.rs:324:13 + | +LL | let _ = 0usize + &usize::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `usize::default()` + +error: this operation has no effect + --> tests/ui/identity_op.rs:327:21 + | +LL | let _n: usize = 0usize + &Default::default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `Default::default()` + +error: this operation has no effect + --> tests/ui/identity_op.rs:333:5 + | +LL | 0usize + &Default::default() + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `Default::default()` + +error: this operation has no effect + --> tests/ui/identity_op.rs:352:5 + | +LL | 0usize + &<usize as Def>::def(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `<usize as Def>::def()` + +error: this operation has no effect + --> tests/ui/identity_op.rs:355:13 + | +LL | let _ = 0usize + &usize::def(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `usize::def()` + +error: this operation has no effect + --> tests/ui/identity_op.rs:358:21 + | +LL | let _n: usize = 0usize + &Def::def(); + | ^^^^^^^^^^^^^^^^^^^^ help: consider reducing it to: `Def::def()` + +error: aborting due to 70 previous errors diff --git a/tests/ui/if_then_some_else_none.fixed b/tests/ui/if_then_some_else_none.fixed index f774608712d..d14a805b666 100644 --- a/tests/ui/if_then_some_else_none.fixed +++ b/tests/ui/if_then_some_else_none.fixed @@ -122,3 +122,46 @@ const fn issue12103(x: u32) -> Option<u32> { // Should not issue an error in `const` context if x > 42 { Some(150) } else { None } } + +mod issue15257 { + struct Range { + start: u8, + end: u8, + } + + fn can_be_safely_rewrite(rs: &[&Range]) -> Option<Vec<u8>> { + (rs.len() == 1 && rs[0].start == rs[0].end).then(|| vec![rs[0].start]) + } + + fn reborrow_as_ptr(i: *mut i32) -> Option<*const i32> { + let modulo = unsafe { *i % 2 }; + (modulo == 0).then_some(i) + } + + fn reborrow_as_fn_ptr(i: i32) { + fn do_something(fn_: Option<fn(i32)>) { + todo!() + } + + fn item_fn(i: i32) { + todo!() + } + + do_something((i % 2 == 0).then_some(item_fn)); + } + + fn reborrow_as_fn_unsafe(i: i32) { + fn do_something(fn_: Option<unsafe fn(i32)>) { + todo!() + } + + fn item_fn(i: i32) { + todo!() + } + + do_something((i % 2 == 0).then_some(item_fn)); + + let closure_fn = |i: i32| {}; + do_something((i % 2 == 0).then_some(closure_fn)); + } +} diff --git a/tests/ui/if_then_some_else_none.rs b/tests/ui/if_then_some_else_none.rs index 8b8ff0a6ea0..bb0072f3157 100644 --- a/tests/ui/if_then_some_else_none.rs +++ b/tests/ui/if_then_some_else_none.rs @@ -143,3 +143,71 @@ const fn issue12103(x: u32) -> Option<u32> { // Should not issue an error in `const` context if x > 42 { Some(150) } else { None } } + +mod issue15257 { + struct Range { + start: u8, + end: u8, + } + + fn can_be_safely_rewrite(rs: &[&Range]) -> Option<Vec<u8>> { + if rs.len() == 1 && rs[0].start == rs[0].end { + //~^ if_then_some_else_none + Some(vec![rs[0].start]) + } else { + None + } + } + + fn reborrow_as_ptr(i: *mut i32) -> Option<*const i32> { + let modulo = unsafe { *i % 2 }; + if modulo == 0 { + //~^ if_then_some_else_none + Some(i) + } else { + None + } + } + + fn reborrow_as_fn_ptr(i: i32) { + fn do_something(fn_: Option<fn(i32)>) { + todo!() + } + + fn item_fn(i: i32) { + todo!() + } + + do_something(if i % 2 == 0 { + //~^ if_then_some_else_none + Some(item_fn) + } else { + None + }); + } + + fn reborrow_as_fn_unsafe(i: i32) { + fn do_something(fn_: Option<unsafe fn(i32)>) { + todo!() + } + + fn item_fn(i: i32) { + todo!() + } + + do_something(if i % 2 == 0 { + //~^ if_then_some_else_none + Some(item_fn) + } else { + None + }); + + let closure_fn = |i: i32| {}; + do_something(if i % 2 == 0 { + //~^ if_then_some_else_none + Some(closure_fn) + } else { + None + }); + } +} diff --git a/tests/ui/if_then_some_else_none.stderr b/tests/ui/if_then_some_else_none.stderr index 71285574ef2..c2e624a0a73 100644 --- a/tests/ui/if_then_some_else_none.stderr +++ b/tests/ui/if_then_some_else_none.stderr @@ -58,5 +58,63 @@ error: this could be simplified with `bool::then` LL | if s == "1" { Some(true) } else { None } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(s == "1").then(|| true)` -error: aborting due to 6 previous errors +error: this could be simplified with `bool::then` + --> tests/ui/if_then_some_else_none.rs:154:9 + | +LL | / if rs.len() == 1 && rs[0].start == rs[0].end { +LL | | +LL | | Some(vec![rs[0].start]) +LL | | } else { +LL | | None +LL | | } + | |_________^ help: try: `(rs.len() == 1 && rs[0].start == rs[0].end).then(|| vec![rs[0].start])` + +error: this could be simplified with `bool::then_some` + --> tests/ui/if_then_some_else_none.rs:164:9 + | +LL | / if modulo == 0 { +LL | | +LL | | Some(i) +LL | | } else { +LL | | None +LL | | } + | |_________^ help: try: `(modulo == 0).then_some(i)` + +error: this could be simplified with `bool::then_some` + --> tests/ui/if_then_some_else_none.rs:181:22 + | +LL | do_something(if i % 2 == 0 { + | ______________________^ +LL | | +LL | | Some(item_fn) +LL | | } else { +LL | | None +LL | | }); + | |_________^ help: try: `(i % 2 == 0).then_some(item_fn)` + +error: this could be simplified with `bool::then_some` + --> tests/ui/if_then_some_else_none.rs:198:22 + | +LL | do_something(if i % 2 == 0 { + | ______________________^ +LL | | +LL | | Some(item_fn) +LL | | } else { +LL | | None +LL | | }); + | |_________^ help: try: `(i % 2 == 0).then_some(item_fn)` + +error: this could be simplified with `bool::then_some` + --> tests/ui/if_then_some_else_none.rs:206:22 + | +LL | do_something(if i % 2 == 0 { + | ______________________^ +LL | | +LL | | Some(closure_fn) +LL | | } else { +LL | | None +LL | | }); + | |_________^ help: try: `(i % 2 == 0).then_some(closure_fn)` + +error: aborting due to 11 previous errors diff --git a/tests/ui/if_then_some_else_none_unfixable.rs b/tests/ui/if_then_some_else_none_unfixable.rs new file mode 100644 index 00000000000..be04299a6ab --- /dev/null +++ b/tests/ui/if_then_some_else_none_unfixable.rs @@ -0,0 +1,35 @@ +#![warn(clippy::if_then_some_else_none)] +#![allow(clippy::manual_is_multiple_of)] + +mod issue15257 { + use std::pin::Pin; + + #[derive(Default)] + pub struct Foo {} + pub trait Bar {} + impl Bar for Foo {} + + fn pointer_unsized_coercion(i: u32) -> Option<Box<dyn Bar>> { + if i % 2 == 0 { + //~^ if_then_some_else_none + Some(Box::new(Foo::default())) + } else { + None + } + } + + fn reborrow_as_pin(i: Pin<&mut i32>) { + use std::ops::Rem; + + fn do_something(i: Option<&i32>) { + todo!() + } + + do_something(if i.rem(2) == 0 { + //~^ if_then_some_else_none + Some(&i) + } else { + None + }); + } +} diff --git a/tests/ui/if_then_some_else_none_unfixable.stderr b/tests/ui/if_then_some_else_none_unfixable.stderr new file mode 100644 index 00000000000..f77ce7910e7 --- /dev/null +++ b/tests/ui/if_then_some_else_none_unfixable.stderr @@ -0,0 +1,28 @@ +error: this could be simplified with `bool::then` + --> tests/ui/if_then_some_else_none_unfixable.rs:13:9 + | +LL | / if i % 2 == 0 { +LL | | +LL | | Some(Box::new(Foo::default())) +LL | | } else { +LL | | None +LL | | } + | |_________^ + | + = note: `-D clippy::if-then-some-else-none` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::if_then_some_else_none)]` + +error: this could be simplified with `bool::then` + --> tests/ui/if_then_some_else_none_unfixable.rs:28:22 + | +LL | do_something(if i.rem(2) == 0 { + | ______________________^ +LL | | +LL | | Some(&i) +LL | | } else { +LL | | None +LL | | }); + | |_________^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/implicit_clone.fixed b/tests/ui/implicit_clone.fixed index d60d1cb0ec0..267514c5f3d 100644 --- a/tests/ui/implicit_clone.fixed +++ b/tests/ui/implicit_clone.fixed @@ -135,4 +135,10 @@ fn main() { } let no_clone = &NoClone; let _ = no_clone.to_owned(); + + let s = String::from("foo"); + let _ = s.clone(); + //~^ implicit_clone + let _ = s.clone(); + //~^ implicit_clone } diff --git a/tests/ui/implicit_clone.rs b/tests/ui/implicit_clone.rs index b96828f28c8..fba954026e7 100644 --- a/tests/ui/implicit_clone.rs +++ b/tests/ui/implicit_clone.rs @@ -135,4 +135,10 @@ fn main() { } let no_clone = &NoClone; let _ = no_clone.to_owned(); + + let s = String::from("foo"); + let _ = s.to_owned(); + //~^ implicit_clone + let _ = s.to_string(); + //~^ implicit_clone } diff --git a/tests/ui/implicit_clone.stderr b/tests/ui/implicit_clone.stderr index 1eb6ff1fe42..4cca9b0d0c0 100644 --- a/tests/ui/implicit_clone.stderr +++ b/tests/ui/implicit_clone.stderr @@ -67,5 +67,17 @@ error: implicitly cloning a `PathBuf` by calling `to_path_buf` on its dereferenc LL | let _ = pathbuf_ref.to_path_buf(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(**pathbuf_ref).clone()` -error: aborting due to 11 previous errors +error: implicitly cloning a `String` by calling `to_owned` on its dereferenced type + --> tests/ui/implicit_clone.rs:140:13 + | +LL | let _ = s.to_owned(); + | ^^^^^^^^^^^^ help: consider using: `s.clone()` + +error: implicitly cloning a `String` by calling `to_string` on its dereferenced type + --> tests/ui/implicit_clone.rs:142:13 + | +LL | let _ = s.to_string(); + | ^^^^^^^^^^^^^ help: consider using: `s.clone()` + +error: aborting due to 13 previous errors diff --git a/tests/ui/incompatible_msrv.rs b/tests/ui/incompatible_msrv.rs index 99101b2bb8f..882f909e30c 100644 --- a/tests/ui/incompatible_msrv.rs +++ b/tests/ui/incompatible_msrv.rs @@ -1,8 +1,10 @@ #![warn(clippy::incompatible_msrv)] #![feature(custom_inner_attributes)] -#![feature(panic_internals)] +#![allow(stable_features, clippy::diverging_sub_expression)] +#![feature(strict_provenance)] // For use in test #![clippy::msrv = "1.3.0"] +use std::cell::Cell; use std::collections::HashMap; use std::collections::hash_map::Entry; use std::future::Future; @@ -13,6 +15,8 @@ fn foo() { let mut map: HashMap<&str, u32> = HashMap::new(); assert_eq!(map.entry("poneyland").key(), &"poneyland"); //~^ incompatible_msrv + //~| NOTE: `-D clippy::incompatible-msrv` implied by `-D warnings` + //~| HELP: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` if let Entry::Vacant(v) = map.entry("poneyland") { v.into_key(); @@ -23,6 +27,18 @@ fn foo() { //~^ incompatible_msrv } +#[clippy::msrv = "1.2.0"] +static NO_BODY_BAD_MSRV: Option<Duration> = None; +//~^ incompatible_msrv + +static NO_BODY_GOOD_MSRV: Option<Duration> = None; + +#[clippy::msrv = "1.2.0"] +fn bad_type_msrv() { + let _: Option<Duration> = None; + //~^ incompatible_msrv +} + #[test] fn test() { sleep(Duration::new(1, 0)); @@ -43,21 +59,22 @@ fn core_special_treatment(p: bool) { // But still lint code calling `core` functions directly if p { - core::panicking::panic("foo"); - //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + let _ = core::iter::once_with(|| 0); + //~^ incompatible_msrv } // Lint code calling `core` from non-`core` macros macro_rules! my_panic { ($msg:expr) => { - core::panicking::panic($msg) - }; //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + let _ = core::iter::once_with(|| $msg); + //~^ incompatible_msrv + }; } my_panic!("foo"); // Lint even when the macro comes from `core` and calls `core` functions - assert!(core::panicking::panic("out of luck")); - //~^ ERROR: is `1.3.0` but this item is stable since `1.6.0` + assert!(core::iter::once_with(|| 0).next().is_some()); + //~^ incompatible_msrv } #[clippy::msrv = "1.26.0"] @@ -70,7 +87,85 @@ fn lang_items() { #[clippy::msrv = "1.80.0"] fn issue14212() { let _ = std::iter::repeat_n((), 5); - //~^ ERROR: is `1.80.0` but this item is stable since `1.82.0` + //~^ incompatible_msrv +} + +#[clippy::msrv = "1.0.0"] +fn cstr_and_cstring_ok() { + let _: Option<&'static std::ffi::CStr> = None; + let _: Option<std::ffi::CString> = None; +} + +fn local_msrv_change_suggestion() { + let _ = std::iter::repeat_n((), 5); + //~^ incompatible_msrv + + #[cfg(any(test, not(test)))] + { + let _ = std::iter::repeat_n((), 5); + //~^ incompatible_msrv + //~| NOTE: you may want to conditionally increase the MSRV + + // Emit the additional note only once + let _ = std::iter::repeat_n((), 5); + //~^ incompatible_msrv + } +} + +#[clippy::msrv = "1.78.0"] +fn feature_enable_14425(ptr: *const u8) -> usize { + // Do not warn, because it is enabled through a feature even though + // it is stabilized only since Rust 1.84.0. + let r = ptr.addr(); + + // Warn about this which has been introduced in the same Rust version + // but is not allowed through a feature. + r.isqrt() + //~^ incompatible_msrv +} + +fn non_fn_items() { + let _ = std::io::ErrorKind::CrossesDevices; + //~^ incompatible_msrv +} + +#[clippy::msrv = "1.87.0"] +fn msrv_non_ok_in_const() { + { + let c = Cell::new(42); + _ = c.get(); + } + const { + let c = Cell::new(42); + _ = c.get(); + //~^ incompatible_msrv + } +} + +#[clippy::msrv = "1.88.0"] +fn msrv_ok_in_const() { + { + let c = Cell::new(42); + _ = c.get(); + } + const { + let c = Cell::new(42); + _ = c.get(); + } +} + +#[clippy::msrv = "1.86.0"] +fn enum_variant_not_ok() { + let _ = std::io::ErrorKind::InvalidFilename; + //~^ incompatible_msrv + let _ = const { std::io::ErrorKind::InvalidFilename }; + //~^ incompatible_msrv +} + +#[clippy::msrv = "1.87.0"] +fn enum_variant_ok() { + let _ = std::io::ErrorKind::InvalidFilename; + let _ = const { std::io::ErrorKind::InvalidFilename }; } fn main() {} diff --git a/tests/ui/incompatible_msrv.stderr b/tests/ui/incompatible_msrv.stderr index 5ea2bb9cc58..e42360d296f 100644 --- a/tests/ui/incompatible_msrv.stderr +++ b/tests/ui/incompatible_msrv.stderr @@ -1,5 +1,5 @@ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.10.0` - --> tests/ui/incompatible_msrv.rs:14:39 + --> tests/ui/incompatible_msrv.rs:16:39 | LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); | ^^^^^ @@ -8,45 +8,107 @@ LL | assert_eq!(map.entry("poneyland").key(), &"poneyland"); = help: to override `-D warnings` add `#[allow(clippy::incompatible_msrv)]` error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.12.0` - --> tests/ui/incompatible_msrv.rs:18:11 + --> tests/ui/incompatible_msrv.rs:22:11 | LL | v.into_key(); | ^^^^^^^^^^ error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.4.0` - --> tests/ui/incompatible_msrv.rs:22:5 + --> tests/ui/incompatible_msrv.rs:26:5 | LL | sleep(Duration::new(1, 0)); | ^^^^^ -error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` - --> tests/ui/incompatible_msrv.rs:46:9 +error: current MSRV (Minimum Supported Rust Version) is `1.2.0` but this item is stable since `1.3.0` + --> tests/ui/incompatible_msrv.rs:31:33 | -LL | core::panicking::panic("foo"); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | static NO_BODY_BAD_MSRV: Option<Duration> = None; + | ^^^^^^^^ -error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` - --> tests/ui/incompatible_msrv.rs:53:13 +error: current MSRV (Minimum Supported Rust Version) is `1.2.0` but this item is stable since `1.3.0` + --> tests/ui/incompatible_msrv.rs:38:19 | -LL | core::panicking::panic($msg) - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | let _: Option<Duration> = None; + | ^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` + --> tests/ui/incompatible_msrv.rs:62:17 + | +LL | let _ = core::iter::once_with(|| 0); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` + --> tests/ui/incompatible_msrv.rs:69:21 + | +LL | let _ = core::iter::once_with(|| $msg); + | ^^^^^^^^^^^^^^^^^^^^^ ... LL | my_panic!("foo"); | ---------------- in this macro invocation | = note: this error originates in the macro `my_panic` (in Nightly builds, run with -Z macro-backtrace for more info) -error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.6.0` - --> tests/ui/incompatible_msrv.rs:59:13 +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` + --> tests/ui/incompatible_msrv.rs:76:13 | -LL | assert!(core::panicking::panic("out of luck")); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | assert!(core::iter::once_with(|| 0).next().is_some()); + | ^^^^^^^^^^^^^^^^^^^^^ error: current MSRV (Minimum Supported Rust Version) is `1.80.0` but this item is stable since `1.82.0` - --> tests/ui/incompatible_msrv.rs:72:13 + --> tests/ui/incompatible_msrv.rs:89:13 + | +LL | let _ = std::iter::repeat_n((), 5); + | ^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.82.0` + --> tests/ui/incompatible_msrv.rs:100:13 | LL | let _ = std::iter::repeat_n((), 5); | ^^^^^^^^^^^^^^^^^^^ -error: aborting due to 7 previous errors +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.82.0` + --> tests/ui/incompatible_msrv.rs:105:17 + | +LL | let _ = std::iter::repeat_n((), 5); + | ^^^^^^^^^^^^^^^^^^^ + | + = note: you may want to conditionally increase the MSRV considered by Clippy using the `clippy::msrv` attribute + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.82.0` + --> tests/ui/incompatible_msrv.rs:110:17 + | +LL | let _ = std::iter::repeat_n((), 5); + | ^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.78.0` but this item is stable since `1.84.0` + --> tests/ui/incompatible_msrv.rs:123:7 + | +LL | r.isqrt() + | ^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.85.0` + --> tests/ui/incompatible_msrv.rs:128:13 + | +LL | let _ = std::io::ErrorKind::CrossesDevices; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.87.0` but this item is stable in a `const` context since `1.88.0` + --> tests/ui/incompatible_msrv.rs:140:15 + | +LL | _ = c.get(); + | ^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.86.0` but this item is stable since `1.87.0` + --> tests/ui/incompatible_msrv.rs:159:13 + | +LL | let _ = std::io::ErrorKind::InvalidFilename; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: current MSRV (Minimum Supported Rust Version) is `1.86.0` but this item is stable since `1.87.0` + --> tests/ui/incompatible_msrv.rs:161:21 + | +LL | let _ = const { std::io::ErrorKind::InvalidFilename }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 17 previous errors diff --git a/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed b/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed index 72edc539f04..edf6f014d3d 100644 --- a/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed +++ b/tests/ui/index_refutable_slice/slice_indexing_in_macro.fixed @@ -1,8 +1,5 @@ #![deny(clippy::index_refutable_slice)] -extern crate if_chain; -use if_chain::if_chain; - macro_rules! if_let_slice_macro { () => { // This would normally be linted @@ -18,12 +15,9 @@ fn main() { if_let_slice_macro!(); // Do lint this - if_chain! { - let slice: Option<&[u32]> = Some(&[1, 2, 3]); - if let Some([slice_0, ..]) = slice; + let slice: Option<&[u32]> = Some(&[1, 2, 3]); + if let Some([slice_0, ..]) = slice { //~^ ERROR: this binding can be a slice pattern to avoid indexing - then { - println!("{}", slice_0); - } + println!("{}", slice_0); } } diff --git a/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs b/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs index 7b474ba423b..76d4a2350f5 100644 --- a/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs +++ b/tests/ui/index_refutable_slice/slice_indexing_in_macro.rs @@ -1,8 +1,5 @@ #![deny(clippy::index_refutable_slice)] -extern crate if_chain; -use if_chain::if_chain; - macro_rules! if_let_slice_macro { () => { // This would normally be linted @@ -18,12 +15,9 @@ fn main() { if_let_slice_macro!(); // Do lint this - if_chain! { - let slice: Option<&[u32]> = Some(&[1, 2, 3]); - if let Some(slice) = slice; + let slice: Option<&[u32]> = Some(&[1, 2, 3]); + if let Some(slice) = slice { //~^ ERROR: this binding can be a slice pattern to avoid indexing - then { - println!("{}", slice[0]); - } + println!("{}", slice[0]); } } diff --git a/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr b/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr index 64741abb911..635e6d19aef 100644 --- a/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr +++ b/tests/ui/index_refutable_slice/slice_indexing_in_macro.stderr @@ -1,8 +1,8 @@ error: this binding can be a slice pattern to avoid indexing - --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:23:21 + --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:19:17 | -LL | if let Some(slice) = slice; - | ^^^^^ +LL | if let Some(slice) = slice { + | ^^^^^ | note: the lint level is defined here --> tests/ui/index_refutable_slice/slice_indexing_in_macro.rs:1:9 @@ -11,10 +11,9 @@ LL | #![deny(clippy::index_refutable_slice)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the binding and indexed access with a slice pattern | -LL ~ if let Some([slice_0, ..]) = slice; +LL ~ if let Some([slice_0, ..]) = slice { LL | -LL | then { -LL ~ println!("{}", slice_0); +LL ~ println!("{}", slice_0); | error: aborting due to 1 previous error diff --git a/tests/ui/indexing_slicing_index.rs b/tests/ui/indexing_slicing_index.rs index cfa1c2f7c75..2510a023acd 100644 --- a/tests/ui/indexing_slicing_index.rs +++ b/tests/ui/indexing_slicing_index.rs @@ -68,7 +68,6 @@ fn main() { // This should be linted, since `suppress-restriction-lint-in-const` default is false. const { &ARR[idx4()] }; //~^ ERROR: indexing may panic - //~| ERROR: evaluation of `main let y = &x; // Ok, referencing shouldn't affect this lint. See the issue 6021 diff --git a/tests/ui/indexing_slicing_index.stderr b/tests/ui/indexing_slicing_index.stderr index 50ee9b9edc7..c68e1d53a93 100644 --- a/tests/ui/indexing_slicing_index.stderr +++ b/tests/ui/indexing_slicing_index.stderr @@ -9,18 +9,6 @@ LL | const REF: &i32 = &ARR[idx()]; // This should be linted, since `suppress-re = note: `-D clippy::indexing-slicing` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` -error[E0080]: evaluation of `main::{constant#3}` failed - --> tests/ui/indexing_slicing_index.rs:69:14 - | -LL | const { &ARR[idx4()] }; - | ^^^^^^^^^^^ index out of bounds: the length is 2 but the index is 4 - -note: erroneous constant encountered - --> tests/ui/indexing_slicing_index.rs:69:5 - | -LL | const { &ARR[idx4()] }; - | ^^^^^^^^^^^^^^^^^^^^^^ - error: indexing may panic --> tests/ui/indexing_slicing_index.rs:48:5 | @@ -63,13 +51,13 @@ LL | const { &ARR[idx4()] }; = note: the suggestion might not be applicable in constant blocks error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:77:5 + --> tests/ui/indexing_slicing_index.rs:76:5 | LL | y[4]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:81:5 + --> tests/ui/indexing_slicing_index.rs:80:5 | LL | v[0]; | ^^^^ @@ -77,7 +65,7 @@ LL | v[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:83:5 + --> tests/ui/indexing_slicing_index.rs:82:5 | LL | v[10]; | ^^^^^ @@ -85,7 +73,7 @@ LL | v[10]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:85:5 + --> tests/ui/indexing_slicing_index.rs:84:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -93,13 +81,13 @@ LL | v[1 << 3]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:93:5 + --> tests/ui/indexing_slicing_index.rs:92:5 | LL | x[N]; | ^^^^ error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:97:5 + --> tests/ui/indexing_slicing_index.rs:96:5 | LL | v[N]; | ^^^^ @@ -107,7 +95,7 @@ LL | v[N]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_index.rs:99:5 + --> tests/ui/indexing_slicing_index.rs:98:5 | LL | v[M]; | ^^^^ @@ -115,11 +103,10 @@ LL | v[M]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: index is out of bounds - --> tests/ui/indexing_slicing_index.rs:103:13 + --> tests/ui/indexing_slicing_index.rs:102:13 | LL | let _ = x[4]; | ^^^^ -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/indexing_slicing_slice.rs b/tests/ui/indexing_slicing_slice.rs index cad77f56d03..dea31530a0b 100644 --- a/tests/ui/indexing_slicing_slice.rs +++ b/tests/ui/indexing_slicing_slice.rs @@ -1,6 +1,5 @@ //@aux-build: proc_macros.rs -#![warn(clippy::indexing_slicing)] // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] diff --git a/tests/ui/indexing_slicing_slice.stderr b/tests/ui/indexing_slicing_slice.stderr index e3ef89823e3..e3d6086544d 100644 --- a/tests/ui/indexing_slicing_slice.stderr +++ b/tests/ui/indexing_slicing_slice.stderr @@ -1,5 +1,5 @@ error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:115:6 + --> tests/ui/indexing_slicing_slice.rs:114:6 | LL | &x[index..]; | ^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | &x[index..]; = help: to override `-D warnings` add `#[allow(clippy::indexing_slicing)]` error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:117:6 + --> tests/ui/indexing_slicing_slice.rs:116:6 | LL | &x[..index]; | ^^^^^^^^^^ @@ -17,7 +17,7 @@ LL | &x[..index]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:119:6 + --> tests/ui/indexing_slicing_slice.rs:118:6 | LL | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL | &x[index_from..index_to]; = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:121:6 + --> tests/ui/indexing_slicing_slice.rs:120:6 | LL | &x[index_from..][..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | &x[index_from..][..index_to]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:121:6 + --> tests/ui/indexing_slicing_slice.rs:120:6 | LL | &x[index_from..][..index_to]; | ^^^^^^^^^^^^^^^ @@ -41,7 +41,7 @@ LL | &x[index_from..][..index_to]; = help: consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:124:6 + --> tests/ui/indexing_slicing_slice.rs:123:6 | LL | &x[5..][..10]; | ^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | &x[5..][..10]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:124:8 + --> tests/ui/indexing_slicing_slice.rs:123:8 | LL | &x[5..][..10]; | ^ @@ -58,7 +58,7 @@ LL | &x[5..][..10]; = help: to override `-D warnings` add `#[allow(clippy::out_of_bounds_indexing)]` error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:127:6 + --> tests/ui/indexing_slicing_slice.rs:126:6 | LL | &x[0..][..3]; | ^^^^^^^^^^^ @@ -66,7 +66,7 @@ LL | &x[0..][..3]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:129:6 + --> tests/ui/indexing_slicing_slice.rs:128:6 | LL | &x[1..][..5]; | ^^^^^^^^^^^ @@ -74,19 +74,19 @@ LL | &x[1..][..5]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:137:12 + --> tests/ui/indexing_slicing_slice.rs:136:12 | LL | &y[0..=4]; | ^ error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:139:11 + --> tests/ui/indexing_slicing_slice.rs:138:11 | LL | &y[..=4]; | ^ error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:145:6 + --> tests/ui/indexing_slicing_slice.rs:144:6 | LL | &v[10..100]; | ^^^^^^^^^^ @@ -94,7 +94,7 @@ LL | &v[10..100]; = help: consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:147:6 + --> tests/ui/indexing_slicing_slice.rs:146:6 | LL | &x[10..][..100]; | ^^^^^^^^^^^^^^ @@ -102,13 +102,13 @@ LL | &x[10..][..100]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> tests/ui/indexing_slicing_slice.rs:147:8 + --> tests/ui/indexing_slicing_slice.rs:146:8 | LL | &x[10..][..100]; | ^^ error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:150:6 + --> tests/ui/indexing_slicing_slice.rs:149:6 | LL | &v[10..]; | ^^^^^^^ @@ -116,7 +116,7 @@ LL | &v[10..]; = help: consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic - --> tests/ui/indexing_slicing_slice.rs:152:6 + --> tests/ui/indexing_slicing_slice.rs:151:6 | LL | &v[..100]; | ^^^^^^^^ @@ -124,7 +124,7 @@ LL | &v[..100]; = help: consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_slice.rs:170:5 + --> tests/ui/indexing_slicing_slice.rs:169:5 | LL | map_with_get[true]; | ^^^^^^^^^^^^^^^^^^ @@ -132,7 +132,7 @@ LL | map_with_get[true]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_slice.rs:174:5 + --> tests/ui/indexing_slicing_slice.rs:173:5 | LL | s[0]; | ^^^^ @@ -140,7 +140,7 @@ LL | s[0]; = help: consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic - --> tests/ui/indexing_slicing_slice.rs:178:5 + --> tests/ui/indexing_slicing_slice.rs:177:5 | LL | y[0]; | ^^^^ diff --git a/tests/ui/infallible_try_from.stderr b/tests/ui/infallible_try_from.stderr index 705b1188489..d1e0d9e7d3b 100644 --- a/tests/ui/infallible_try_from.stderr +++ b/tests/ui/infallible_try_from.stderr @@ -1,4 +1,4 @@ -error: infallible TryFrom impl; consider implementing From, instead +error: infallible TryFrom impl; consider implementing From instead --> tests/ui/infallible_try_from.rs:8:1 | LL | impl TryFrom<i8> for MyStruct { @@ -10,7 +10,7 @@ LL | type Error = !; = note: `-D clippy::infallible-try-from` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::infallible_try_from)]` -error: infallible TryFrom impl; consider implementing From, instead +error: infallible TryFrom impl; consider implementing From instead --> tests/ui/infallible_try_from.rs:16:1 | LL | impl TryFrom<i16> for MyStruct { diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 002a791a657..701a86534ba 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -38,7 +38,7 @@ fn infinite_iters() { //~^ infinite_iter // infinite iter - (0_u64..).filter(|x| x % 2 == 0).last(); + (0_u64..).filter(|x| x.is_multiple_of(2)).last(); //~^ infinite_iter // not an infinite, because ranges are double-ended diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 47133a2ea62..b9e7c008f93 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -42,8 +42,8 @@ LL | (0_usize..).flat_map(|x| 0..x).product::<usize>(); error: infinite iteration detected --> tests/ui/infinite_iter.rs:41:5 | -LL | (0_u64..).filter(|x| x % 2 == 0).last(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | (0_u64..).filter(|x| x.is_multiple_of(2)).last(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected --> tests/ui/infinite_iter.rs:53:5 diff --git a/tests/ui/infinite_loops.rs b/tests/ui/infinite_loops.rs index fcd1f795fff..7d01a7fb61f 100644 --- a/tests/ui/infinite_loops.rs +++ b/tests/ui/infinite_loops.rs @@ -450,4 +450,90 @@ mod issue_12338 { } } +#[allow(clippy::let_underscore_future, clippy::empty_loop)] +mod issue_14000 { + use super::do_something; + + async fn foo() { + let _ = async move { + loop { + //~^ infinite_loop + do_something(); + } + } + .await; + let _ = async move { + loop { + //~^ infinite_loop + continue; + } + } + .await; + } + + fn bar() { + let _ = async move { + loop { + do_something(); + } + }; + + let _ = async move { + loop { + continue; + } + }; + } +} + +#[allow(clippy::let_underscore_future)] +mod tokio_spawn_test { + use super::do_something; + + fn install_ticker() { + // This should NOT trigger the lint because the async block is spawned, not awaited + std::thread::spawn(move || { + async move { + loop { + // This loop should not trigger infinite_loop lint + do_something(); + } + } + }); + } + + fn spawn_async_block() { + // This should NOT trigger the lint because the async block is not awaited + let _handle = async move { + loop { + do_something(); + } + }; + } + + fn await_async_block() { + // This SHOULD trigger the lint because the async block is awaited + let _ = async move { + loop { + do_something(); + } + }; + } +} + +mod issue15541 { + async fn good() -> ! { + loop { + std::future::pending().await + } + } + + async fn bad() { + //~v infinite_loop + loop { + std::future::pending().await + } + } +} + fn main() {} diff --git a/tests/ui/infinite_loops.stderr b/tests/ui/infinite_loops.stderr index 4d02636ef4a..319f1e5012b 100644 --- a/tests/ui/infinite_loops.stderr +++ b/tests/ui/infinite_loops.stderr @@ -311,5 +311,37 @@ help: if this is intentional, consider specifying `!` as function return LL | fn continue_outer() -> ! { | ++++ -error: aborting due to 21 previous errors +error: infinite loop detected + --> tests/ui/infinite_loops.rs:459:13 + | +LL | / loop { +LL | | +LL | | do_something(); +LL | | } + | |_____________^ + | + = help: if this is not intended, try adding a `break` or `return` condition in the loop + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:466:13 + | +LL | / loop { +LL | | +LL | | continue; +LL | | } + | |_____________^ + | + = help: if this is not intended, try adding a `break` or `return` condition in the loop + +error: infinite loop detected + --> tests/ui/infinite_loops.rs:533:9 + | +LL | / loop { +LL | | std::future::pending().await +LL | | } + | |_________^ + | + = help: if this is not intended, try adding a `break` or `return` condition in the loop + +error: aborting due to 24 previous errors diff --git a/tests/ui/ip_constant.fixed b/tests/ui/ip_constant.fixed index 2e3389c1193..c9479682139 100644 --- a/tests/ui/ip_constant.fixed +++ b/tests/ui/ip_constant.fixed @@ -48,6 +48,20 @@ fn literal_test3() { //~^ ip_constant } +fn wrapped_in_parens() { + let _ = std::net::Ipv4Addr::LOCALHOST; + //~^ ip_constant + let _ = std::net::Ipv4Addr::BROADCAST; + //~^ ip_constant + let _ = std::net::Ipv4Addr::UNSPECIFIED; + //~^ ip_constant + + let _ = std::net::Ipv6Addr::LOCALHOST; + //~^ ip_constant + let _ = std::net::Ipv6Addr::UNSPECIFIED; + //~^ ip_constant +} + const CONST_U8_0: u8 = 0; const CONST_U8_1: u8 = 1; const CONST_U8_127: u8 = 127; diff --git a/tests/ui/ip_constant.rs b/tests/ui/ip_constant.rs index 15e0b0551ba..69a5c3b4e92 100644 --- a/tests/ui/ip_constant.rs +++ b/tests/ui/ip_constant.rs @@ -48,6 +48,20 @@ fn literal_test3() { //~^ ip_constant } +fn wrapped_in_parens() { + let _ = (std::net::Ipv4Addr::new(127, 0, 0, 1)); + //~^ ip_constant + let _ = (std::net::Ipv4Addr::new(255, 255, 255, 255)); + //~^ ip_constant + let _ = (std::net::Ipv4Addr::new(0, 0, 0, 0)); + //~^ ip_constant + + let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + //~^ ip_constant + let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + //~^ ip_constant +} + const CONST_U8_0: u8 = 0; const CONST_U8_1: u8 = 1; const CONST_U8_127: u8 = 127; diff --git a/tests/ui/ip_constant.stderr b/tests/ui/ip_constant.stderr index 3e984c6cb3b..07d912b18a5 100644 --- a/tests/ui/ip_constant.stderr +++ b/tests/ui/ip_constant.stderr @@ -181,8 +181,68 @@ LL + let _ = std::net::Ipv6Addr::UNSPECIFIED; | error: hand-coded well-known IP address + --> tests/ui/ip_constant.rs:52:13 + | +LL | let _ = (std::net::Ipv4Addr::new(127, 0, 0, 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use + | +LL - let _ = (std::net::Ipv4Addr::new(127, 0, 0, 1)); +LL + let _ = std::net::Ipv4Addr::LOCALHOST; + | + +error: hand-coded well-known IP address + --> tests/ui/ip_constant.rs:54:13 + | +LL | let _ = (std::net::Ipv4Addr::new(255, 255, 255, 255)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use + | +LL - let _ = (std::net::Ipv4Addr::new(255, 255, 255, 255)); +LL + let _ = std::net::Ipv4Addr::BROADCAST; + | + +error: hand-coded well-known IP address + --> tests/ui/ip_constant.rs:56:13 + | +LL | let _ = (std::net::Ipv4Addr::new(0, 0, 0, 0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use + | +LL - let _ = (std::net::Ipv4Addr::new(0, 0, 0, 0)); +LL + let _ = std::net::Ipv4Addr::UNSPECIFIED; + | + +error: hand-coded well-known IP address + --> tests/ui/ip_constant.rs:59:13 + | +LL | let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use + | +LL - let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1)); +LL + let _ = std::net::Ipv6Addr::LOCALHOST; + | + +error: hand-coded well-known IP address --> tests/ui/ip_constant.rs:61:13 | +LL | let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use + | +LL - let _ = (std::net::Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0)); +LL + let _ = std::net::Ipv6Addr::UNSPECIFIED; + | + +error: hand-coded well-known IP address + --> tests/ui/ip_constant.rs:75:13 + | LL | let _ = Ipv4Addr::new(CONST_U8_127, CONST_U8_0, CONST_U8_0, CONST_U8_1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | @@ -193,7 +253,7 @@ LL + let _ = Ipv4Addr::LOCALHOST; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:63:13 + --> tests/ui/ip_constant.rs:77:13 | LL | let _ = Ipv4Addr::new(CONST_U8_255, CONST_U8_255, CONST_U8_255, CONST_U8_255); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -205,7 +265,7 @@ LL + let _ = Ipv4Addr::BROADCAST; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:65:13 + --> tests/ui/ip_constant.rs:79:13 | LL | let _ = Ipv4Addr::new(CONST_U8_0, CONST_U8_0, CONST_U8_0, CONST_U8_0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -217,7 +277,7 @@ LL + let _ = Ipv4Addr::UNSPECIFIED; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:69:13 + --> tests/ui/ip_constant.rs:83:13 | LL | let _ = Ipv6Addr::new( | _____________^ @@ -246,7 +306,7 @@ LL + let _ = Ipv6Addr::LOCALHOST; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:81:13 + --> tests/ui/ip_constant.rs:95:13 | LL | let _ = Ipv6Addr::new( | _____________^ @@ -275,7 +335,7 @@ LL + let _ = Ipv6Addr::UNSPECIFIED; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:96:13 + --> tests/ui/ip_constant.rs:110:13 | LL | let _ = Ipv4Addr::new(126 + 1, 0, 0, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -287,7 +347,7 @@ LL + let _ = Ipv4Addr::LOCALHOST; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:98:13 + --> tests/ui/ip_constant.rs:112:13 | LL | let _ = Ipv4Addr::new(254 + CONST_U8_1, 255, { 255 - CONST_U8_0 }, CONST_U8_255); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -299,7 +359,7 @@ LL + let _ = Ipv4Addr::BROADCAST; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:100:13 + --> tests/ui/ip_constant.rs:114:13 | LL | let _ = Ipv4Addr::new(0, CONST_U8_255 - 255, 0, { 1 + 0 - 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -311,7 +371,7 @@ LL + let _ = Ipv4Addr::UNSPECIFIED; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:104:13 + --> tests/ui/ip_constant.rs:118:13 | LL | let _ = Ipv6Addr::new(0 + CONST_U16_0, 0, 0, 0, 0, 0, 0, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -323,7 +383,7 @@ LL + let _ = Ipv6Addr::LOCALHOST; | error: hand-coded well-known IP address - --> tests/ui/ip_constant.rs:106:13 + --> tests/ui/ip_constant.rs:120:13 | LL | let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -334,5 +394,5 @@ LL - let _ = Ipv6Addr::new(0 + 0, 0, 0, 0, 0, { 2 - 1 - CONST_U16_1 }, 0, 1) LL + let _ = Ipv6Addr::LOCALHOST; | -error: aborting due to 25 previous errors +error: aborting due to 30 previous errors diff --git a/tests/ui/iter_kv_map.fixed b/tests/ui/iter_kv_map.fixed index 874f749b33d..b18dda35887 100644 --- a/tests/ui/iter_kv_map.fixed +++ b/tests/ui/iter_kv_map.fixed @@ -30,15 +30,19 @@ fn main() { let _ = map.clone().values().collect::<Vec<_>>(); //~^ iter_kv_map - let _ = map.keys().filter(|x| *x % 2 == 0).count(); + let _ = map.keys().filter(|x| x.is_multiple_of(2)).count(); //~^ iter_kv_map // Don't lint - let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); + let _ = map + .iter() + .filter(|(_, val)| val.is_multiple_of(2)) + .map(|(key, _)| key) + .count(); let _ = map.iter().map(get_key).collect::<Vec<_>>(); // Linting the following could be an improvement to the lint - // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count(); + // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count(); // Lint let _ = map.keys().map(|key| key * 9).count(); @@ -84,15 +88,19 @@ fn main() { let _ = map.clone().values().collect::<Vec<_>>(); //~^ iter_kv_map - let _ = map.keys().filter(|x| *x % 2 == 0).count(); + let _ = map.keys().filter(|x| x.is_multiple_of(2)).count(); //~^ iter_kv_map // Don't lint - let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); + let _ = map + .iter() + .filter(|(_, val)| val.is_multiple_of(2)) + .map(|(key, _)| key) + .count(); let _ = map.iter().map(get_key).collect::<Vec<_>>(); // Linting the following could be an improvement to the lint - // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count(); + // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count(); // Lint let _ = map.keys().map(|key| key * 9).count(); diff --git a/tests/ui/iter_kv_map.rs b/tests/ui/iter_kv_map.rs index f570e3c32cb..729e4e8a266 100644 --- a/tests/ui/iter_kv_map.rs +++ b/tests/ui/iter_kv_map.rs @@ -30,15 +30,19 @@ fn main() { let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>(); //~^ iter_kv_map - let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); + let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); //~^ iter_kv_map // Don't lint - let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); + let _ = map + .iter() + .filter(|(_, val)| val.is_multiple_of(2)) + .map(|(key, _)| key) + .count(); let _ = map.iter().map(get_key).collect::<Vec<_>>(); // Linting the following could be an improvement to the lint - // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count(); + // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count(); // Lint let _ = map.iter().map(|(key, _value)| key * 9).count(); @@ -86,15 +90,19 @@ fn main() { let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>(); //~^ iter_kv_map - let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); + let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); //~^ iter_kv_map // Don't lint - let _ = map.iter().filter(|(_, val)| *val % 2 == 0).map(|(key, _)| key).count(); + let _ = map + .iter() + .filter(|(_, val)| val.is_multiple_of(2)) + .map(|(key, _)| key) + .count(); let _ = map.iter().map(get_key).collect::<Vec<_>>(); // Linting the following could be an improvement to the lint - // map.iter().filter_map(|(_, val)| (val % 2 == 0).then(val * 17)).count(); + // map.iter().filter_map(|(_, val)| (val.is_multiple_of(2)).then(val * 17)).count(); // Lint let _ = map.iter().map(|(key, _value)| key * 9).count(); diff --git a/tests/ui/iter_kv_map.stderr b/tests/ui/iter_kv_map.stderr index 31ee76c25b7..8f73541f503 100644 --- a/tests/ui/iter_kv_map.stderr +++ b/tests/ui/iter_kv_map.stderr @@ -52,29 +52,29 @@ LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>(); error: iterating on a map's keys --> tests/ui/iter_kv_map.rs:33:13 | -LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); +LL | let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:44:13 + --> tests/ui/iter_kv_map.rs:48:13 | LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:46:13 + --> tests/ui/iter_kv_map.rs:50:13 | LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:50:13 + --> tests/ui/iter_kv_map.rs:54:13 | LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:54:13 + --> tests/ui/iter_kv_map.rs:58:13 | LL | let _ = map | _____________^ @@ -97,85 +97,85 @@ LL + }) | error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:65:13 + --> tests/ui/iter_kv_map.rs:69:13 | LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:70:13 + --> tests/ui/iter_kv_map.rs:74:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:72:13 + --> tests/ui/iter_kv_map.rs:76:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:74:13 + --> tests/ui/iter_kv_map.rs:78:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:77:13 + --> tests/ui/iter_kv_map.rs:81:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:79:13 + --> tests/ui/iter_kv_map.rs:83:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:82:13 + --> tests/ui/iter_kv_map.rs:86:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:84:13 + --> tests/ui/iter_kv_map.rs:88:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:87:13 + --> tests/ui/iter_kv_map.rs:91:13 | LL | let _ = map.clone().iter().map(|(_, val)| val).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:89:13 + --> tests/ui/iter_kv_map.rs:93:13 | -LL | let _ = map.iter().map(|(key, _)| key).filter(|x| *x % 2 == 0).count(); +LL | let _ = map.iter().map(|(key, _)| key).filter(|x| x.is_multiple_of(2)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:100:13 + --> tests/ui/iter_kv_map.rs:108:13 | LL | let _ = map.iter().map(|(key, _value)| key * 9).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys().map(|key| key * 9)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:102:13 + --> tests/ui/iter_kv_map.rs:110:13 | LL | let _ = map.iter().map(|(_key, value)| value * 17).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|value| value * 17)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:106:13 + --> tests/ui/iter_kv_map.rs:114:13 | LL | let _ = map.clone().into_iter().map(|(_, ref val)| ref_acceptor(val)).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|ref val| ref_acceptor(val))` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:110:13 + --> tests/ui/iter_kv_map.rs:118:13 | LL | let _ = map | _____________^ @@ -198,73 +198,73 @@ LL + }) | error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:121:13 + --> tests/ui/iter_kv_map.rs:129:13 | LL | let _ = map.clone().into_iter().map(|(_, mut val)| val).count(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:137:13 + --> tests/ui/iter_kv_map.rs:145:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:140:13 + --> tests/ui/iter_kv_map.rs:148:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:143:13 + --> tests/ui/iter_kv_map.rs:151:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:152:13 + --> tests/ui/iter_kv_map.rs:160:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys()` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:155:13 + --> tests/ui/iter_kv_map.rs:163:13 | LL | let _ = map.clone().into_iter().map(|(key, _)| key + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_keys().map(|key| key + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:158:13 + --> tests/ui/iter_kv_map.rs:166:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:161:13 + --> tests/ui/iter_kv_map.rs:169:13 | LL | let _ = map.clone().into_iter().map(|(_, val)| val + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.clone().into_values().map(|val| val + 2)` error: iterating on a map's keys - --> tests/ui/iter_kv_map.rs:164:13 + --> tests/ui/iter_kv_map.rs:172:13 | LL | let _ = map.iter().map(|(key, _)| key).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.keys()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:167:13 + --> tests/ui/iter_kv_map.rs:175:13 | LL | let _ = map.iter().map(|(_, value)| value).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values()` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:170:13 + --> tests/ui/iter_kv_map.rs:178:13 | LL | let _ = map.iter().map(|(_, v)| v + 2).collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.values().map(|v| v + 2)` error: iterating on a map's values - --> tests/ui/iter_kv_map.rs:185:13 + --> tests/ui/iter_kv_map.rs:193:13 | LL | let _ = map.as_ref().iter().map(|(_, v)| v).copied().collect::<Vec<_>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map.as_ref().values()` diff --git a/tests/ui/iter_next_loop.rs b/tests/ui/iter_next_loop.rs index 8e62ed963b9..969c51006af 100644 --- a/tests/ui/iter_next_loop.rs +++ b/tests/ui/iter_next_loop.rs @@ -8,7 +8,7 @@ fn main() { struct Unrelated(&'static [u8]); impl Unrelated { - fn next(&self) -> std::slice::Iter<u8> { + fn next(&self) -> std::slice::Iter<'_, u8> { self.0.iter() } } diff --git a/tests/ui/iter_not_returning_iterator.rs b/tests/ui/iter_not_returning_iterator.rs index 5c8c8eb4a43..d2497ed4330 100644 --- a/tests/ui/iter_not_returning_iterator.rs +++ b/tests/ui/iter_not_returning_iterator.rs @@ -71,7 +71,7 @@ impl S { struct S2([u8]); impl S2 { - fn iter(&self) -> core::slice::Iter<u8> { + fn iter(&self) -> core::slice::Iter<'_, u8> { self.0.iter() } } diff --git a/tests/ui/iter_on_single_items.fixed b/tests/ui/iter_on_single_items.fixed index b43fad6449c..044037aac2e 100644 --- a/tests/ui/iter_on_single_items.fixed +++ b/tests/ui/iter_on_single_items.fixed @@ -66,3 +66,27 @@ fn main() { custom_option::custom_option(); in_macros!(); } + +mod issue14981 { + use std::option::IntoIter; + fn takes_into_iter(_: impl IntoIterator<Item = i32>) {} + + fn let_stmt() { + macro_rules! x { + ($e:expr) => { + let _: IntoIter<i32> = $e; + }; + } + x!(Some(5).into_iter()); + } + + fn fn_ptr() { + fn some_func(_: IntoIter<i32>) -> IntoIter<i32> { + todo!() + } + some_func(Some(5).into_iter()); + + const C: fn(IntoIter<i32>) -> IntoIter<i32> = <IntoIter<i32> as IntoIterator>::into_iter; + C(Some(5).into_iter()); + } +} diff --git a/tests/ui/iter_on_single_items.rs b/tests/ui/iter_on_single_items.rs index 625c96d3ef1..c925d0e480f 100644 --- a/tests/ui/iter_on_single_items.rs +++ b/tests/ui/iter_on_single_items.rs @@ -66,3 +66,27 @@ fn main() { custom_option::custom_option(); in_macros!(); } + +mod issue14981 { + use std::option::IntoIter; + fn takes_into_iter(_: impl IntoIterator<Item = i32>) {} + + fn let_stmt() { + macro_rules! x { + ($e:expr) => { + let _: IntoIter<i32> = $e; + }; + } + x!(Some(5).into_iter()); + } + + fn fn_ptr() { + fn some_func(_: IntoIter<i32>) -> IntoIter<i32> { + todo!() + } + some_func(Some(5).into_iter()); + + const C: fn(IntoIter<i32>) -> IntoIter<i32> = <IntoIter<i32> as IntoIterator>::into_iter; + C(Some(5).into_iter()); + } +} diff --git a/tests/ui/iter_over_hash_type.rs b/tests/ui/iter_over_hash_type.rs index 914cc9df0de..9a3e7033cd8 100644 --- a/tests/ui/iter_over_hash_type.rs +++ b/tests/ui/iter_over_hash_type.rs @@ -3,15 +3,18 @@ #![warn(clippy::iter_over_hash_type)] use std::collections::{HashMap, HashSet}; -extern crate rustc_data_structures; - extern crate proc_macros; +// Ensure it also works via type aliases (this isn't really the Fx hasher but that does not matter). +type FxBuildHasher = std::collections::hash_map::RandomState; +type FxHashMap<K, V> = HashMap<K, V, FxBuildHasher>; +type FxHashSet<K> = HashSet<K, FxBuildHasher>; + fn main() { let mut hash_set = HashSet::<i32>::new(); let mut hash_map = HashMap::<i32, i32>::new(); - let mut fx_hash_map = rustc_data_structures::fx::FxHashMap::<i32, i32>::default(); - let mut fx_hash_set = rustc_data_structures::fx::FxHashMap::<i32, i32>::default(); + let mut fx_hash_map = FxHashMap::<i32, i32>::default(); + let mut fx_hash_set = FxHashSet::<i32>::default(); let vec = Vec::<i32>::new(); // test hashset diff --git a/tests/ui/iter_over_hash_type.stderr b/tests/ui/iter_over_hash_type.stderr index 1bc6f4588d4..3356186547d 100644 --- a/tests/ui/iter_over_hash_type.stderr +++ b/tests/ui/iter_over_hash_type.stderr @@ -1,5 +1,5 @@ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:18:5 + --> tests/ui/iter_over_hash_type.rs:21:5 | LL | / for x in &hash_set { LL | | @@ -11,7 +11,7 @@ LL | | } = help: to override `-D warnings` add `#[allow(clippy::iter_over_hash_type)]` error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:22:5 + --> tests/ui/iter_over_hash_type.rs:25:5 | LL | / for x in hash_set.iter() { LL | | @@ -20,7 +20,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:26:5 + --> tests/ui/iter_over_hash_type.rs:29:5 | LL | / for x in hash_set.clone() { LL | | @@ -29,7 +29,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:30:5 + --> tests/ui/iter_over_hash_type.rs:33:5 | LL | / for x in hash_set.drain() { LL | | @@ -38,7 +38,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:36:5 + --> tests/ui/iter_over_hash_type.rs:39:5 | LL | / for (x, y) in &hash_map { LL | | @@ -47,7 +47,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:40:5 + --> tests/ui/iter_over_hash_type.rs:43:5 | LL | / for x in hash_map.keys() { LL | | @@ -56,7 +56,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:44:5 + --> tests/ui/iter_over_hash_type.rs:47:5 | LL | / for x in hash_map.values() { LL | | @@ -65,7 +65,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:48:5 + --> tests/ui/iter_over_hash_type.rs:51:5 | LL | / for x in hash_map.values_mut() { LL | | @@ -74,7 +74,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:52:5 + --> tests/ui/iter_over_hash_type.rs:55:5 | LL | / for x in hash_map.iter() { LL | | @@ -83,7 +83,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:56:5 + --> tests/ui/iter_over_hash_type.rs:59:5 | LL | / for x in hash_map.clone() { LL | | @@ -92,7 +92,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:60:5 + --> tests/ui/iter_over_hash_type.rs:63:5 | LL | / for x in hash_map.drain() { LL | | @@ -101,7 +101,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:66:5 + --> tests/ui/iter_over_hash_type.rs:69:5 | LL | / for x in fx_hash_set { LL | | @@ -110,7 +110,7 @@ LL | | } | |_____^ error: iteration over unordered hash-based type - --> tests/ui/iter_over_hash_type.rs:70:5 + --> tests/ui/iter_over_hash_type.rs:73:5 | LL | / for x in fx_hash_map { LL | | diff --git a/tests/ui/large_enum_variant.32bit.stderr b/tests/ui/large_enum_variant.32bit.stderr index 80ca5daa1d5..ac1ed27a6b3 100644 --- a/tests/ui/large_enum_variant.32bit.stderr +++ b/tests/ui/large_enum_variant.32bit.stderr @@ -12,7 +12,7 @@ LL | | } | = note: `-D clippy::large-enum-variant` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]` -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B([i32; 8000]), LL + B(Box<[i32; 8000]>), @@ -30,7 +30,7 @@ LL | | ContainingLargeEnum(LargeEnum), LL | | } | |_^ the entire enum is at least 32004 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - ContainingLargeEnum(LargeEnum), LL + ContainingLargeEnum(Box<LargeEnum>), @@ -49,7 +49,7 @@ LL | | StructLikeLittle { x: i32, y: i32 }, LL | | } | |_^ the entire enum is at least 70008 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), LL + ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>), @@ -67,7 +67,7 @@ LL | | StructLikeLarge { x: [i32; 8000], y: i32 }, LL | | } | |_^ the entire enum is at least 32008 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - StructLikeLarge { x: [i32; 8000], y: i32 }, LL + StructLikeLarge { x: Box<[i32; 8000]>, y: i32 }, @@ -85,7 +85,7 @@ LL | | StructLikeLarge2 { x: [i32; 8000] }, LL | | } | |_^ the entire enum is at least 32004 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - StructLikeLarge2 { x: [i32; 8000] }, LL + StructLikeLarge2 { x: Box<[i32; 8000]> }, @@ -104,7 +104,7 @@ LL | | C([u8; 200]), LL | | } | |_^ the entire enum is at least 1256 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B([u8; 1255]), LL + B(Box<[u8; 1255]>), @@ -122,7 +122,7 @@ LL | | ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; LL | | } | |_^ the entire enum is at least 70132 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), LL + ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]), @@ -140,7 +140,7 @@ LL | | B(Struct2), LL | | } | |_^ the entire enum is at least 32004 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B(Struct2), LL + B(Box<Struct2>), @@ -158,7 +158,7 @@ LL | | B(Struct2), LL | | } | |_^ the entire enum is at least 32000 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B(Struct2), LL + B(Box<Struct2>), @@ -176,7 +176,7 @@ LL | | B(Struct2), LL | | } | |_^ the entire enum is at least 32000 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B(Struct2), LL + B(Box<Struct2>), @@ -199,7 +199,7 @@ note: boxing a variant would require the type no longer be `Copy` | LL | enum CopyableLargeEnum { | ^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum --> tests/ui/large_enum_variant.rs:118:5 | LL | B([u64; 8000]), @@ -222,7 +222,7 @@ note: boxing a variant would require the type no longer be `Copy` | LL | enum ManuallyCopyLargeEnum { | ^^^^^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum --> tests/ui/large_enum_variant.rs:124:5 | LL | B([u64; 8000]), @@ -245,7 +245,7 @@ note: boxing a variant would require the type no longer be `Copy` | LL | enum SomeGenericPossiblyCopyEnum<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum --> tests/ui/large_enum_variant.rs:138:5 | LL | B([u64; 4000]), @@ -263,7 +263,7 @@ LL | | Large((T, [u8; 512])), LL | | } | |_^ the entire enum is at least 512 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Large((T, [u8; 512])), LL + Large(Box<(T, [u8; 512])>), @@ -281,7 +281,7 @@ LL | | Small(u8), LL | | } | |_^ the entire enum is at least 516 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Large([Foo<u64>; 64]), LL + Large(Box<[Foo<u64>; 64]>), @@ -299,7 +299,7 @@ LL | | Error(PossiblyLargeEnumWithConst<256>), LL | | } | |_^ the entire enum is at least 514 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Error(PossiblyLargeEnumWithConst<256>), LL + Error(Box<PossiblyLargeEnumWithConst<256>>), @@ -317,7 +317,7 @@ LL | | Recursive(Box<WithRecursion>), LL | | } | |_^ the entire enum is at least 516 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Large([u64; 64]), LL + Large(Box<[u64; 64]>), @@ -335,7 +335,7 @@ LL | | Error(WithRecursionAndGenerics<u64>), LL | | } | |_^ the entire enum is at least 516 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Error(WithRecursionAndGenerics<u64>), LL + Error(Box<WithRecursionAndGenerics<u64>>), diff --git a/tests/ui/large_enum_variant.64bit.stderr b/tests/ui/large_enum_variant.64bit.stderr index 559bdf2a2f5..d8199f9090f 100644 --- a/tests/ui/large_enum_variant.64bit.stderr +++ b/tests/ui/large_enum_variant.64bit.stderr @@ -12,7 +12,7 @@ LL | | } | = note: `-D clippy::large-enum-variant` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]` -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B([i32; 8000]), LL + B(Box<[i32; 8000]>), @@ -30,7 +30,7 @@ LL | | ContainingLargeEnum(LargeEnum), LL | | } | |_^ the entire enum is at least 32004 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - ContainingLargeEnum(LargeEnum), LL + ContainingLargeEnum(Box<LargeEnum>), @@ -49,7 +49,7 @@ LL | | StructLikeLittle { x: i32, y: i32 }, LL | | } | |_^ the entire enum is at least 70008 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), LL + ContainingMoreThanOneField(i32, Box<[i32; 8000]>, Box<[i32; 9500]>), @@ -67,7 +67,7 @@ LL | | StructLikeLarge { x: [i32; 8000], y: i32 }, LL | | } | |_^ the entire enum is at least 32008 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - StructLikeLarge { x: [i32; 8000], y: i32 }, LL + StructLikeLarge { x: Box<[i32; 8000]>, y: i32 }, @@ -85,7 +85,7 @@ LL | | StructLikeLarge2 { x: [i32; 8000] }, LL | | } | |_^ the entire enum is at least 32004 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - StructLikeLarge2 { x: [i32; 8000] }, LL + StructLikeLarge2 { x: Box<[i32; 8000]> }, @@ -104,7 +104,7 @@ LL | | C([u8; 200]), LL | | } | |_^ the entire enum is at least 1256 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B([u8; 1255]), LL + B(Box<[u8; 1255]>), @@ -122,7 +122,7 @@ LL | | ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; LL | | } | |_^ the entire enum is at least 70132 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - ContainingMoreThanOneField([i32; 8000], [i32; 2], [i32; 9500], [i32; 30]), LL + ContainingMoreThanOneField(Box<[i32; 8000]>, [i32; 2], Box<[i32; 9500]>, [i32; 30]), @@ -140,7 +140,7 @@ LL | | B(Struct2), LL | | } | |_^ the entire enum is at least 32004 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B(Struct2), LL + B(Box<Struct2>), @@ -158,7 +158,7 @@ LL | | B(Struct2), LL | | } | |_^ the entire enum is at least 32000 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B(Struct2), LL + B(Box<Struct2>), @@ -176,7 +176,7 @@ LL | | B(Struct2), LL | | } | |_^ the entire enum is at least 32000 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - B(Struct2), LL + B(Box<Struct2>), @@ -199,7 +199,7 @@ note: boxing a variant would require the type no longer be `Copy` | LL | enum CopyableLargeEnum { | ^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum --> tests/ui/large_enum_variant.rs:118:5 | LL | B([u64; 8000]), @@ -222,7 +222,7 @@ note: boxing a variant would require the type no longer be `Copy` | LL | enum ManuallyCopyLargeEnum { | ^^^^^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum --> tests/ui/large_enum_variant.rs:124:5 | LL | B([u64; 8000]), @@ -245,7 +245,7 @@ note: boxing a variant would require the type no longer be `Copy` | LL | enum SomeGenericPossiblyCopyEnum<T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum --> tests/ui/large_enum_variant.rs:138:5 | LL | B([u64; 4000]), @@ -263,7 +263,7 @@ LL | | Large((T, [u8; 512])), LL | | } | |_^ the entire enum is at least 512 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Large((T, [u8; 512])), LL + Large(Box<(T, [u8; 512])>), @@ -281,7 +281,7 @@ LL | | Small(u8), LL | | } | |_^ the entire enum is at least 520 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Large([Foo<u64>; 64]), LL + Large(Box<[Foo<u64>; 64]>), @@ -299,7 +299,7 @@ LL | | Error(PossiblyLargeEnumWithConst<256>), LL | | } | |_^ the entire enum is at least 514 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Error(PossiblyLargeEnumWithConst<256>), LL + Error(Box<PossiblyLargeEnumWithConst<256>>), @@ -317,7 +317,7 @@ LL | | Recursive(Box<WithRecursion>), LL | | } | |_^ the entire enum is at least 520 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Large([u64; 64]), LL + Large(Box<[u64; 64]>), @@ -335,7 +335,7 @@ LL | | Error(WithRecursionAndGenerics<u64>), LL | | } | |_^ the entire enum is at least 520 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - Error(WithRecursionAndGenerics<u64>), LL + Error(Box<WithRecursionAndGenerics<u64>>), @@ -353,7 +353,7 @@ LL | | _SmallBoi(u8), LL | | } | |_____^ the entire enum is at least 296 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - BigBoi(PublishWithBytes), LL + BigBoi(Box<PublishWithBytes>), @@ -371,7 +371,7 @@ LL | | _SmallBoi(u8), LL | | } | |_____^ the entire enum is at least 224 bytes | -help: consider boxing the large fields to reduce the total size of the enum +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum | LL - BigBoi(PublishWithVec), LL + BigBoi(Box<PublishWithVec>), diff --git a/tests/ui/large_enum_variant_no_std.rs b/tests/ui/large_enum_variant_no_std.rs new file mode 100644 index 00000000000..ff0213155b6 --- /dev/null +++ b/tests/ui/large_enum_variant_no_std.rs @@ -0,0 +1,8 @@ +#![no_std] +#![warn(clippy::large_enum_variant)] + +enum Myenum { + //~^ ERROR: large size difference between variants + Small(u8), + Large([u8; 1024]), +} diff --git a/tests/ui/large_enum_variant_no_std.stderr b/tests/ui/large_enum_variant_no_std.stderr new file mode 100644 index 00000000000..4f32e3e4835 --- /dev/null +++ b/tests/ui/large_enum_variant_no_std.stderr @@ -0,0 +1,22 @@ +error: large size difference between variants + --> tests/ui/large_enum_variant_no_std.rs:4:1 + | +LL | / enum Myenum { +LL | | +LL | | Small(u8), + | | --------- the second-largest variant contains at least 1 bytes +LL | | Large([u8; 1024]), + | | ----------------- the largest variant contains at least 1024 bytes +LL | | } + | |_^ the entire enum is at least 1025 bytes + | +help: consider boxing the large fields or introducing indirection in some other way to reduce the total size of the enum + --> tests/ui/large_enum_variant_no_std.rs:7:5 + | +LL | Large([u8; 1024]), + | ^^^^^^^^^^^^^^^^^ + = note: `-D clippy::large-enum-variant` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::large_enum_variant)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/large_stack_frames.rs b/tests/ui/large_stack_frames.rs index 3ed124f69ef..132f1450b6d 100644 --- a/tests/ui/large_stack_frames.rs +++ b/tests/ui/large_stack_frames.rs @@ -1,8 +1,7 @@ //@ normalize-stderr-test: "\b10000(08|16|32)\b" -> "100$$PTR" //@ normalize-stderr-test: "\b2500(060|120)\b" -> "250$$PTR" -#![allow(unused, incomplete_features)] +#![allow(unused)] #![warn(clippy::large_stack_frames)] -#![feature(unsized_locals)] use std::hint::black_box; @@ -11,11 +10,6 @@ fn generic<T: Default>() { black_box(&x); } -fn unsized_local() { - let x: dyn std::fmt::Display = *(Box::new(1) as Box<dyn std::fmt::Display>); - black_box(&x); -} - struct ArrayDefault<const N: usize>([u8; N]); impl<const N: usize> Default for ArrayDefault<N> { diff --git a/tests/ui/large_stack_frames.stderr b/tests/ui/large_stack_frames.stderr index 0ff49e9f5b3..79482e65c3e 100644 --- a/tests/ui/large_stack_frames.stderr +++ b/tests/ui/large_stack_frames.stderr @@ -1,5 +1,5 @@ error: this function may allocate 250$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:27:4 + --> tests/ui/large_stack_frames.rs:21:4 | LL | fn many_small_arrays() { | ^^^^^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL | let x5 = [0u8; 500_000]; = help: to override `-D warnings` add `#[allow(clippy::large_stack_frames)]` error: this function may allocate 1000000 bytes on the stack - --> tests/ui/large_stack_frames.rs:38:4 + --> tests/ui/large_stack_frames.rs:32:4 | LL | fn large_return_value() -> ArrayDefault<1_000_000> { | ^^^^^^^^^^^^^^^^^^ ----------------------- this is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` @@ -21,7 +21,7 @@ LL | fn large_return_value() -> ArrayDefault<1_000_000> { = note: 1000000 bytes is larger than Clippy's configured `stack-size-threshold` of 512000 error: this function may allocate 100$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:44:4 + --> tests/ui/large_stack_frames.rs:38:4 | LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { | ^^^^^^^^^^^^ - `x` is the largest part, at 1000000 bytes for type `ArrayDefault<1000000>` @@ -29,7 +29,7 @@ LL | fn large_fn_arg(x: ArrayDefault<1_000_000>) { = note: 100$PTR bytes is larger than Clippy's configured `stack-size-threshold` of 512000 error: this function may allocate 100$PTR bytes on the stack - --> tests/ui/large_stack_frames.rs:51:13 + --> tests/ui/large_stack_frames.rs:45:13 | LL | let f = || black_box(&[0u8; 1_000_000]); | ^^^^^^^^^^^^^^----------------^ diff --git a/tests/ui/legacy_numeric_constants.fixed b/tests/ui/legacy_numeric_constants.fixed index 30bb549a9d6..d90e7bec027 100644 --- a/tests/ui/legacy_numeric_constants.fixed +++ b/tests/ui/legacy_numeric_constants.fixed @@ -79,9 +79,31 @@ fn main() { f64::consts::E; b!(); + std::primitive::i32::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead [(0, "", i128::MAX)]; //~^ ERROR: usage of a legacy numeric constant //~| HELP: use the associated constant instead + i32::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + assert_eq!(0, -i32::MAX); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + i128::MAX; + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + u32::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + i32::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + type Ω = i32; + Ω::MAX; + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead } #[warn(clippy::legacy_numeric_constants)] diff --git a/tests/ui/legacy_numeric_constants.rs b/tests/ui/legacy_numeric_constants.rs index d3878199055..4a2ef3f70c2 100644 --- a/tests/ui/legacy_numeric_constants.rs +++ b/tests/ui/legacy_numeric_constants.rs @@ -79,9 +79,31 @@ fn main() { f64::consts::E; b!(); + <std::primitive::i32>::max_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead [(0, "", std::i128::MAX)]; //~^ ERROR: usage of a legacy numeric constant //~| HELP: use the associated constant instead + (i32::max_value()); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + assert_eq!(0, -(i32::max_value())); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + (std::i128::MAX); + //~^ ERROR: usage of a legacy numeric constant + //~| HELP: use the associated constant instead + (<u32>::max_value()); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + ((i32::max_value)()); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead + type Ω = i32; + Ω::max_value(); + //~^ ERROR: usage of a legacy numeric method + //~| HELP: use the associated constant instead } #[warn(clippy::legacy_numeric_constants)] diff --git a/tests/ui/legacy_numeric_constants.stderr b/tests/ui/legacy_numeric_constants.stderr index 4d69b8165a3..0b4f32e0abc 100644 --- a/tests/ui/legacy_numeric_constants.stderr +++ b/tests/ui/legacy_numeric_constants.stderr @@ -72,10 +72,10 @@ LL | u32::MAX; | +++++ error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:50:10 + --> tests/ui/legacy_numeric_constants.rs:50:5 | LL | i32::max_value(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^ | help: use the associated constant instead | @@ -84,10 +84,10 @@ LL + i32::MAX; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:53:9 + --> tests/ui/legacy_numeric_constants.rs:53:5 | LL | u8::max_value(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | help: use the associated constant instead | @@ -96,10 +96,10 @@ LL + u8::MAX; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:56:9 + --> tests/ui/legacy_numeric_constants.rs:56:5 | LL | u8::min_value(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^ | help: use the associated constant instead | @@ -120,10 +120,10 @@ LL + u8::MIN; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:62:27 + --> tests/ui/legacy_numeric_constants.rs:62:5 | LL | ::std::primitive::u8::min_value(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: use the associated constant instead | @@ -132,10 +132,10 @@ LL + ::std::primitive::u8::MIN; | error: usage of a legacy numeric method - --> tests/ui/legacy_numeric_constants.rs:65:26 + --> tests/ui/legacy_numeric_constants.rs:65:5 | LL | std::primitive::i32::max_value(); - | ^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: use the associated constant instead | @@ -171,8 +171,20 @@ LL - let x = std::u64::MAX; LL + let x = u64::MAX; | +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:82:5 + | +LL | <std::primitive::i32>::max_value(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - <std::primitive::i32>::max_value(); +LL + std::primitive::i32::MAX; + | + error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:82:14 + --> tests/ui/legacy_numeric_constants.rs:85:14 | LL | [(0, "", std::i128::MAX)]; | ^^^^^^^^^^^^^^ @@ -183,8 +195,80 @@ LL - [(0, "", std::i128::MAX)]; LL + [(0, "", i128::MAX)]; | +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:88:5 + | +LL | (i32::max_value()); + | ^^^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - (i32::max_value()); +LL + i32::MAX; + | + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:91:20 + | +LL | assert_eq!(0, -(i32::max_value())); + | ^^^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - assert_eq!(0, -(i32::max_value())); +LL + assert_eq!(0, -i32::MAX); + | + +error: usage of a legacy numeric constant + --> tests/ui/legacy_numeric_constants.rs:94:5 + | +LL | (std::i128::MAX); + | ^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - (std::i128::MAX); +LL + i128::MAX; + | + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:97:5 + | +LL | (<u32>::max_value()); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - (<u32>::max_value()); +LL + u32::MAX; + | + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:100:5 + | +LL | ((i32::max_value)()); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - ((i32::max_value)()); +LL + i32::MAX; + | + +error: usage of a legacy numeric method + --> tests/ui/legacy_numeric_constants.rs:104:5 + | +LL | Ω::max_value(); + | ^^^^^^^^^^^^^^ + | +help: use the associated constant instead + | +LL - Ω::max_value(); +LL + Ω::MAX; + | + error: usage of a legacy numeric constant - --> tests/ui/legacy_numeric_constants.rs:116:5 + --> tests/ui/legacy_numeric_constants.rs:138:5 | LL | std::u32::MAX; | ^^^^^^^^^^^^^ @@ -195,5 +279,5 @@ LL - std::u32::MAX; LL + u32::MAX; | -error: aborting due to 16 previous errors +error: aborting due to 23 previous errors diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed index 5e7a2ad37a8..381d4cac462 100644 --- a/tests/ui/let_unit.fixed +++ b/tests/ui/let_unit.fixed @@ -61,7 +61,7 @@ fn multiline_sugg() { //~^ let_unit_value .into_iter() .map(|i| i * 2) - .filter(|i| i % 2 == 0) + .filter(|i| i.is_multiple_of(2)) .map(|_| ()) .next() .unwrap(); @@ -198,3 +198,14 @@ pub fn issue12594() { returns_result(res).unwrap(); } } + +fn issue15061() { + fn return_unit() {} + fn do_something(x: ()) {} + + let res = (); + return_unit(); + //~^ let_unit_value + do_something(()); + println!("{res:?}"); +} diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index 7b06f694012..cdfc74991c4 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -61,7 +61,7 @@ fn multiline_sugg() { //~^ let_unit_value .into_iter() .map(|i| i * 2) - .filter(|i| i % 2 == 0) + .filter(|i| i.is_multiple_of(2)) .map(|_| ()) .next() .unwrap(); @@ -198,3 +198,13 @@ pub fn issue12594() { returns_result(res).unwrap(); } } + +fn issue15061() { + fn return_unit() {} + fn do_something(x: ()) {} + + let res = return_unit(); + //~^ let_unit_value + do_something(res); + println!("{res:?}"); +} diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index d7d01d304ca..637c9ff686b 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -25,7 +25,7 @@ LL ~ v LL + LL + .into_iter() LL + .map(|i| i * 2) -LL + .filter(|i| i % 2 == 0) +LL + .filter(|i| i.is_multiple_of(2)) LL + .map(|_| ()) LL + .next() LL + .unwrap(); @@ -68,5 +68,19 @@ LL ~ returns_result(()).unwrap(); LL ~ returns_result(()).unwrap(); | -error: aborting due to 4 previous errors +error: this let-binding has unit value + --> tests/ui/let_unit.rs:206:5 + | +LL | let res = return_unit(); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: replace variable usages with `()` + | +LL ~ let res = (); +LL ~ return_unit(); +LL | +LL ~ do_something(()); + | + +error: aborting due to 5 previous errors diff --git a/tests/ui/let_with_type_underscore.fixed b/tests/ui/let_with_type_underscore.fixed index 7a4af4e3d1e..6339fe595c2 100644 --- a/tests/ui/let_with_type_underscore.fixed +++ b/tests/ui/let_with_type_underscore.fixed @@ -45,3 +45,15 @@ fn main() { x = (); }; } + +fn issue15377() { + let (a) = 0; + //~^ let_with_type_underscore + let ((a)) = 0; + //~^ let_with_type_underscore + let ((a,)) = (0,); + //~^ let_with_type_underscore + #[rustfmt::skip] + let ( (a ) ) = 0; + //~^ let_with_type_underscore +} diff --git a/tests/ui/let_with_type_underscore.rs b/tests/ui/let_with_type_underscore.rs index a7c2f598b56..bd85346cf01 100644 --- a/tests/ui/let_with_type_underscore.rs +++ b/tests/ui/let_with_type_underscore.rs @@ -45,3 +45,15 @@ fn main() { x = (); }; } + +fn issue15377() { + let (a): _ = 0; + //~^ let_with_type_underscore + let ((a)): _ = 0; + //~^ let_with_type_underscore + let ((a,)): _ = (0,); + //~^ let_with_type_underscore + #[rustfmt::skip] + let ( (a ) ): _ = 0; + //~^ let_with_type_underscore +} diff --git a/tests/ui/let_with_type_underscore.stderr b/tests/ui/let_with_type_underscore.stderr index 9179f992207..c3f6c82397b 100644 --- a/tests/ui/let_with_type_underscore.stderr +++ b/tests/ui/let_with_type_underscore.stderr @@ -60,5 +60,53 @@ LL - let x : _ = 1; LL + let x = 1; | -error: aborting due to 5 previous errors +error: variable declared with type underscore + --> tests/ui/let_with_type_underscore.rs:50:5 + | +LL | let (a): _ = 0; + | ^^^^^^^^^^^^^^^ + | +help: remove the explicit type `_` declaration + | +LL - let (a): _ = 0; +LL + let (a) = 0; + | + +error: variable declared with type underscore + --> tests/ui/let_with_type_underscore.rs:52:5 + | +LL | let ((a)): _ = 0; + | ^^^^^^^^^^^^^^^^^ + | +help: remove the explicit type `_` declaration + | +LL - let ((a)): _ = 0; +LL + let ((a)) = 0; + | + +error: variable declared with type underscore + --> tests/ui/let_with_type_underscore.rs:54:5 + | +LL | let ((a,)): _ = (0,); + | ^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit type `_` declaration + | +LL - let ((a,)): _ = (0,); +LL + let ((a,)) = (0,); + | + +error: variable declared with type underscore + --> tests/ui/let_with_type_underscore.rs:57:5 + | +LL | let ( (a ) ): _ = 0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: remove the explicit type `_` declaration + | +LL - let ( (a ) ): _ = 0; +LL + let ( (a ) ) = 0; + | + +error: aborting due to 9 previous errors diff --git a/tests/ui/manual_abs_diff.fixed b/tests/ui/manual_abs_diff.fixed index f1b1278ea6d..2766942140c 100644 --- a/tests/ui/manual_abs_diff.fixed +++ b/tests/ui/manual_abs_diff.fixed @@ -104,3 +104,7 @@ fn non_primitive_ty() { let (a, b) = (S(10), S(20)); let _ = if a < b { b - a } else { a - b }; } + +fn issue15254(a: &usize, b: &usize) -> usize { + b.abs_diff(*a) +} diff --git a/tests/ui/manual_abs_diff.rs b/tests/ui/manual_abs_diff.rs index 60ef819c12d..2c408f2be37 100644 --- a/tests/ui/manual_abs_diff.rs +++ b/tests/ui/manual_abs_diff.rs @@ -114,3 +114,12 @@ fn non_primitive_ty() { let (a, b) = (S(10), S(20)); let _ = if a < b { b - a } else { a - b }; } + +fn issue15254(a: &usize, b: &usize) -> usize { + if a < b { + //~^ manual_abs_diff + b - a + } else { + a - b + } +} diff --git a/tests/ui/manual_abs_diff.stderr b/tests/ui/manual_abs_diff.stderr index c14c1dc830f..bb6d312b435 100644 --- a/tests/ui/manual_abs_diff.stderr +++ b/tests/ui/manual_abs_diff.stderr @@ -79,5 +79,16 @@ error: manual absolute difference pattern without using `abs_diff` LL | let _ = if a > b { (a - b) as u32 } else { (b - a) as u32 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with `abs_diff`: `a.abs_diff(b)` -error: aborting due to 11 previous errors +error: manual absolute difference pattern without using `abs_diff` + --> tests/ui/manual_abs_diff.rs:119:5 + | +LL | / if a < b { +LL | | +LL | | b - a +LL | | } else { +LL | | a - b +LL | | } + | |_____^ help: replace with `abs_diff`: `b.abs_diff(*a)` + +error: aborting due to 12 previous errors diff --git a/tests/ui/manual_assert.edition2018.stderr b/tests/ui/manual_assert.edition2018.stderr index 8cedf2c6863..2e9c9045caa 100644 --- a/tests/ui/manual_assert.edition2018.stderr +++ b/tests/ui/manual_assert.edition2018.stderr @@ -167,7 +167,7 @@ LL - comment */ LL - /// Doc comment LL - panic!("panic with comment") // comment after `panic!` LL - } -LL + assert!(!(a > 2), "panic with comment"); +LL + assert!(a <= 2, "panic with comment"); | error: only a `panic!` in `if`-then statement @@ -186,8 +186,26 @@ LL - const BAR: () = if N == 0 { LL - LL - panic!() LL - }; -LL + const BAR: () = assert!(!(N == 0), ); +LL + const BAR: () = assert!(N != 0, ); | -error: aborting due to 10 previous errors +error: only a `panic!` in `if`-then statement + --> tests/ui/manual_assert.rs:116:5 + | +LL | / if !is_x86_feature_detected!("ssse3") { +LL | | +LL | | panic!("SSSE3 is not supported"); +LL | | } + | |_____^ + | +help: try instead + | +LL - if !is_x86_feature_detected!("ssse3") { +LL - +LL - panic!("SSSE3 is not supported"); +LL - } +LL + assert!(is_x86_feature_detected!("ssse3"), "SSSE3 is not supported"); + | + +error: aborting due to 11 previous errors diff --git a/tests/ui/manual_assert.edition2021.stderr b/tests/ui/manual_assert.edition2021.stderr index 8cedf2c6863..2e9c9045caa 100644 --- a/tests/ui/manual_assert.edition2021.stderr +++ b/tests/ui/manual_assert.edition2021.stderr @@ -167,7 +167,7 @@ LL - comment */ LL - /// Doc comment LL - panic!("panic with comment") // comment after `panic!` LL - } -LL + assert!(!(a > 2), "panic with comment"); +LL + assert!(a <= 2, "panic with comment"); | error: only a `panic!` in `if`-then statement @@ -186,8 +186,26 @@ LL - const BAR: () = if N == 0 { LL - LL - panic!() LL - }; -LL + const BAR: () = assert!(!(N == 0), ); +LL + const BAR: () = assert!(N != 0, ); | -error: aborting due to 10 previous errors +error: only a `panic!` in `if`-then statement + --> tests/ui/manual_assert.rs:116:5 + | +LL | / if !is_x86_feature_detected!("ssse3") { +LL | | +LL | | panic!("SSSE3 is not supported"); +LL | | } + | |_____^ + | +help: try instead + | +LL - if !is_x86_feature_detected!("ssse3") { +LL - +LL - panic!("SSSE3 is not supported"); +LL - } +LL + assert!(is_x86_feature_detected!("ssse3"), "SSSE3 is not supported"); + | + +error: aborting due to 11 previous errors diff --git a/tests/ui/manual_assert.rs b/tests/ui/manual_assert.rs index 46a42c3d00a..ab02bd5f5e5 100644 --- a/tests/ui/manual_assert.rs +++ b/tests/ui/manual_assert.rs @@ -105,3 +105,17 @@ fn issue12505() { }; } } + +fn issue15227(left: u64, right: u64) -> u64 { + macro_rules! is_x86_feature_detected { + ($feature:literal) => { + $feature.len() > 0 && $feature.starts_with("ss") + }; + } + + if !is_x86_feature_detected!("ssse3") { + //~^ manual_assert + panic!("SSSE3 is not supported"); + } + unsafe { todo!() } +} diff --git a/tests/ui/manual_contains.fixed b/tests/ui/manual_contains.fixed index d26c948a781..18171f0b2b4 100644 --- a/tests/ui/manual_contains.fixed +++ b/tests/ui/manual_contains.fixed @@ -58,7 +58,7 @@ fn should_not_lint() { let vec: Vec<u32> = vec![1, 2, 3, 4, 5, 6]; let values = &vec[..]; - let _ = values.iter().any(|&v| v % 2 == 0); + let _ = values.iter().any(|&v| v.is_multiple_of(2)); let _ = values.iter().any(|&v| v * 2 == 6); let _ = values.iter().any(|&v| v == v); let _ = values.iter().any(|&v| 4 == 4); diff --git a/tests/ui/manual_contains.rs b/tests/ui/manual_contains.rs index fe67d2ee5d5..918f4d6b8dd 100644 --- a/tests/ui/manual_contains.rs +++ b/tests/ui/manual_contains.rs @@ -58,7 +58,7 @@ fn should_not_lint() { let vec: Vec<u32> = vec![1, 2, 3, 4, 5, 6]; let values = &vec[..]; - let _ = values.iter().any(|&v| v % 2 == 0); + let _ = values.iter().any(|&v| v.is_multiple_of(2)); let _ = values.iter().any(|&v| v * 2 == 6); let _ = values.iter().any(|&v| v == v); let _ = values.iter().any(|&v| 4 == 4); diff --git a/tests/ui/manual_find_fixable.fixed b/tests/ui/manual_find_fixable.fixed index 01b3ebacbeb..c69b0cb11e3 100644 --- a/tests/ui/manual_find_fixable.fixed +++ b/tests/ui/manual_find_fixable.fixed @@ -11,7 +11,7 @@ fn lookup(n: u32) -> Option<u32> { } fn with_pat(arr: Vec<(u32, u32)>) -> Option<u32> { - arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0) + arr.into_iter().map(|(a, _)| a).find(|&a| a.is_multiple_of(2)) } struct Data { @@ -63,7 +63,7 @@ fn with_side_effects(arr: Vec<u32>) -> Option<u32> { fn with_else(arr: Vec<u32>) -> Option<u32> { for el in arr { - if el % 2 == 0 { + if el.is_multiple_of(2) { return Some(el); } else { println!("{}", el); diff --git a/tests/ui/manual_find_fixable.rs b/tests/ui/manual_find_fixable.rs index ce62a4beba1..db7092f020c 100644 --- a/tests/ui/manual_find_fixable.rs +++ b/tests/ui/manual_find_fixable.rs @@ -19,7 +19,7 @@ fn lookup(n: u32) -> Option<u32> { fn with_pat(arr: Vec<(u32, u32)>) -> Option<u32> { for (a, _) in arr { //~^ manual_find - if a % 2 == 0 { + if a.is_multiple_of(2) { return Some(a); } } @@ -111,7 +111,7 @@ fn with_side_effects(arr: Vec<u32>) -> Option<u32> { fn with_else(arr: Vec<u32>) -> Option<u32> { for el in arr { - if el % 2 == 0 { + if el.is_multiple_of(2) { return Some(el); } else { println!("{}", el); diff --git a/tests/ui/manual_find_fixable.stderr b/tests/ui/manual_find_fixable.stderr index 020635d90bb..0c05c0d2c44 100644 --- a/tests/ui/manual_find_fixable.stderr +++ b/tests/ui/manual_find_fixable.stderr @@ -17,11 +17,11 @@ error: manual implementation of `Iterator::find` | LL | / for (a, _) in arr { LL | | -LL | | if a % 2 == 0 { +LL | | if a.is_multiple_of(2) { LL | | return Some(a); ... | LL | | None - | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a % 2 == 0)` + | |________^ help: replace with an iterator: `arr.into_iter().map(|(a, _)| a).find(|&a| a.is_multiple_of(2))` error: manual implementation of `Iterator::find` --> tests/ui/manual_find_fixable.rs:34:5 diff --git a/tests/ui/manual_flatten.fixed b/tests/ui/manual_flatten.fixed new file mode 100644 index 00000000000..cc1fbd25765 --- /dev/null +++ b/tests/ui/manual_flatten.fixed @@ -0,0 +1,148 @@ +#![warn(clippy::manual_flatten)] +#![allow(clippy::useless_vec, clippy::uninlined_format_args)] + +fn main() { + // Test for loop over implicitly adjusted `Iterator` with `if let` expression + let x = vec![Some(1), Some(2), Some(3)]; + for y in x.into_iter().flatten() { + println!("{}", y); + } + + // Test for loop over implicitly adjusted `Iterator` with `if let` statement + let y: Vec<Result<i32, i32>> = vec![]; + for n in y.clone().into_iter().flatten() { + println!("{}", n); + } + + // Test for loop over by reference + for n in y.iter().flatten() { + println!("{}", n); + } + + // Test for loop over an implicit reference + let z = &y; + for n in z.iter().flatten() { + println!("{}", n); + } + + // Test for loop over `Iterator` with `if let` expression + let z = vec![Some(1), Some(2), Some(3)]; + let z = z.iter(); + for m in z.flatten() { + println!("{}", m); + } + + // Using the `None` variant should not trigger the lint + // Note: for an autofixable suggestion, the binding in the for loop has to take the + // name of the binding in the `if let` + let z = vec![Some(1), Some(2), Some(3)]; + for n in z { + if n.is_none() { + println!("Nada."); + } + } + + // Using the `Err` variant should not trigger the lint + for n in y.clone() { + if let Err(e) = n { + println!("Oops: {}!", e); + } + } + + // Having an else clause should not trigger the lint + for n in y.clone() { + if let Ok(n) = n { + println!("{}", n); + } else { + println!("Oops!"); + } + } + + let vec_of_ref = vec![&Some(1)]; + for n in vec_of_ref.iter().copied().flatten() { + println!("{:?}", n); + } + + let vec_of_ref = &vec_of_ref; + for n in vec_of_ref.iter().copied().flatten() { + println!("{:?}", n); + } + + let slice_of_ref = &[&Some(1)]; + for n in slice_of_ref.iter().copied().flatten() { + println!("{:?}", n); + } + + struct Test { + a: usize, + } + + let mut vec_of_struct = [Some(Test { a: 1 }), None]; + + // Usage of `if let` expression should not trigger lint + for n in vec_of_struct.iter_mut() { + if let Some(z) = n { + *n = None; + } + } + + // Using manual flatten should not trigger the lint + for n in vec![Some(1), Some(2), Some(3)].iter().flatten() { + println!("{}", n); + } + + // Using nested `Some` pattern should not trigger the lint + for n in vec![Some((1, Some(2)))] { + if let Some((_, Some(n))) = n { + println!("{}", n); + } + } + + macro_rules! inner { + ($id:ident / $new:pat => $action:expr) => { + if let Some($new) = $id { + $action; + } + }; + } + + // Usage of `if let` expression with macro should not trigger lint + for ab in [Some((1, 2)), Some((3, 4))] { + inner!(ab / (c, d) => println!("{c}-{d}")); + } + + macro_rules! args { + ($($arg:expr),*) => { + vec![$(Some($arg)),*] + }; + } + + // Usage of `if let` expression with macro should not trigger lint + for n in args!(1, 2, 3) { + if let Some(n) = n { + println!("{:?}", n); + } + } + + // This should trigger the lint, but the applicability is `MaybeIncorrect` + let z = vec![Some(1), Some(2), Some(3)]; + for n in z.into_iter().flatten() { + println!("{:?}", n); + } + + run_unformatted_tests(); +} + +#[rustfmt::skip] +fn run_unformatted_tests() { + // Skip rustfmt here on purpose so the suggestion does not fit in one line + for n in vec![ + //~^ manual_flatten + + Some(1), + Some(2), + Some(3) + ].iter().flatten() { + println!("{:?}", n); + } +} diff --git a/tests/ui/manual_flatten.rs b/tests/ui/manual_flatten.rs index f1a0053ef38..53b4ac7d3b6 100644 --- a/tests/ui/manual_flatten.rs +++ b/tests/ui/manual_flatten.rs @@ -1,6 +1,6 @@ #![warn(clippy::manual_flatten)] #![allow(clippy::useless_vec, clippy::uninlined_format_args)] -//@no-rustfix + fn main() { // Test for loop over implicitly adjusted `Iterator` with `if let` expression let x = vec![Some(1), Some(2), Some(3)]; @@ -130,6 +130,43 @@ fn main() { } } + macro_rules! inner { + ($id:ident / $new:pat => $action:expr) => { + if let Some($new) = $id { + $action; + } + }; + } + + // Usage of `if let` expression with macro should not trigger lint + for ab in [Some((1, 2)), Some((3, 4))] { + inner!(ab / (c, d) => println!("{c}-{d}")); + } + + macro_rules! args { + ($($arg:expr),*) => { + vec![$(Some($arg)),*] + }; + } + + // Usage of `if let` expression with macro should not trigger lint + for n in args!(1, 2, 3) { + if let Some(n) = n { + println!("{:?}", n); + } + } + + // This should trigger the lint, but the applicability is `MaybeIncorrect` + let z = vec![Some(1), Some(2), Some(3)]; + for n in z { + //~^ manual_flatten + + if let Some(n) = n { + println!("{:?}", n); + } + // foo + } + run_unformatted_tests(); } diff --git a/tests/ui/manual_flatten.stderr b/tests/ui/manual_flatten.stderr index 9a846fe17f3..eb39ee42071 100644 --- a/tests/ui/manual_flatten.stderr +++ b/tests/ui/manual_flatten.stderr @@ -1,10 +1,7 @@ error: unnecessary `if let` since only the `Some` variant of the iterator element is used --> tests/ui/manual_flatten.rs:7:5 | -LL | for n in x { - | ^ - help: try: `x.into_iter().flatten()` - | _____| - | | +LL | / for n in x { LL | | LL | | LL | | if let Some(y) = n { @@ -12,7 +9,7 @@ LL | | if let Some(y) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:10:9 | LL | / if let Some(y) = n { @@ -21,14 +18,17 @@ LL | | } | |_________^ = note: `-D clippy::manual-flatten` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::manual_flatten)]` +help: try + | +LL ~ for y in x.into_iter().flatten() { +LL + println!("{}", y); +LL + } + | error: unnecessary `if let` since only the `Ok` variant of the iterator element is used --> tests/ui/manual_flatten.rs:17:5 | -LL | for n in y.clone() { - | ^ --------- help: try: `y.clone().into_iter().flatten()` - | _____| - | | +LL | / for n in y.clone() { LL | | LL | | LL | | if let Ok(n) = n { @@ -37,21 +37,24 @@ LL | | }; LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:20:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); LL | | }; | |_________^ +help: try + | +LL ~ for n in y.clone().into_iter().flatten() { +LL + println!("{}", n); +LL + } + | error: unnecessary `if let` since only the `Ok` variant of the iterator element is used --> tests/ui/manual_flatten.rs:26:5 | -LL | for n in &y { - | ^ -- help: try: `y.iter().flatten()` - | _____| - | | +LL | / for n in &y { LL | | LL | | LL | | if let Ok(n) = n { @@ -59,21 +62,24 @@ LL | | if let Ok(n) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:29:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); LL | | } | |_________^ +help: try + | +LL ~ for n in y.iter().flatten() { +LL + println!("{}", n); +LL + } + | error: unnecessary `if let` since only the `Ok` variant of the iterator element is used --> tests/ui/manual_flatten.rs:36:5 | -LL | for n in z { - | ^ - help: try: `z.iter().flatten()` - | _____| - | | +LL | / for n in z { LL | | LL | | LL | | if let Ok(n) = n { @@ -81,21 +87,24 @@ LL | | if let Ok(n) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:39:9 | LL | / if let Ok(n) = n { LL | | println!("{}", n); LL | | } | |_________^ +help: try + | +LL ~ for n in z.iter().flatten() { +LL + println!("{}", n); +LL + } + | error: unnecessary `if let` since only the `Some` variant of the iterator element is used --> tests/ui/manual_flatten.rs:47:5 | -LL | for n in z { - | ^ - help: try: `z.flatten()` - | _____| - | | +LL | / for n in z { LL | | LL | | LL | | if let Some(m) = n { @@ -103,21 +112,24 @@ LL | | if let Some(m) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:50:9 | LL | / if let Some(m) = n { LL | | println!("{}", m); LL | | } | |_________^ +help: try + | +LL ~ for m in z.flatten() { +LL + println!("{}", m); +LL + } + | error: unnecessary `if let` since only the `Some` variant of the iterator element is used --> tests/ui/manual_flatten.rs:82:5 | -LL | for n in &vec_of_ref { - | ^ ----------- help: try: `vec_of_ref.iter().copied().flatten()` - | _____| - | | +LL | / for n in &vec_of_ref { LL | | LL | | LL | | if let Some(n) = n { @@ -125,21 +137,24 @@ LL | | if let Some(n) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:85:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); LL | | } | |_________^ +help: try + | +LL ~ for n in vec_of_ref.iter().copied().flatten() { +LL + println!("{:?}", n); +LL + } + | error: unnecessary `if let` since only the `Some` variant of the iterator element is used --> tests/ui/manual_flatten.rs:91:5 | -LL | for n in vec_of_ref { - | ^ ---------- help: try: `vec_of_ref.iter().copied().flatten()` - | _____| - | | +LL | / for n in vec_of_ref { LL | | LL | | LL | | if let Some(n) = n { @@ -147,21 +162,24 @@ LL | | if let Some(n) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:94:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); LL | | } | |_________^ +help: try + | +LL ~ for n in vec_of_ref.iter().copied().flatten() { +LL + println!("{:?}", n); +LL + } + | error: unnecessary `if let` since only the `Some` variant of the iterator element is used --> tests/ui/manual_flatten.rs:100:5 | -LL | for n in slice_of_ref { - | ^ ------------ help: try: `slice_of_ref.iter().copied().flatten()` - | _____| - | | +LL | / for n in slice_of_ref { LL | | LL | | LL | | if let Some(n) = n { @@ -169,16 +187,47 @@ LL | | if let Some(n) = n { LL | | } | |_____^ | -help: ...and remove the `if let` statement in the for loop +help: try `.flatten()` and remove the `if let` statement in the for loop --> tests/ui/manual_flatten.rs:103:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); LL | | } | |_________^ +help: try + | +LL ~ for n in slice_of_ref.iter().copied().flatten() { +LL + println!("{:?}", n); +LL + } + | + +error: unnecessary `if let` since only the `Some` variant of the iterator element is used + --> tests/ui/manual_flatten.rs:161:5 + | +LL | / for n in z { +LL | | +LL | | +LL | | if let Some(n) = n { +... | +LL | | } + | |_____^ + | +help: try `.flatten()` and remove the `if let` statement in the for loop + --> tests/ui/manual_flatten.rs:164:9 + | +LL | / if let Some(n) = n { +LL | | println!("{:?}", n); +LL | | } + | |_________^ +help: try + | +LL ~ for n in z.into_iter().flatten() { +LL + println!("{:?}", n); +LL + } + | error: unnecessary `if let` since only the `Some` variant of the iterator element is used - --> tests/ui/manual_flatten.rs:139:5 + --> tests/ui/manual_flatten.rs:176:5 | LL | / for n in vec![ LL | | @@ -188,8 +237,8 @@ LL | | Some(1), LL | | } | |_____^ | -help: remove the `if let` statement in the for loop and then... - --> tests/ui/manual_flatten.rs:146:9 +help: try `.flatten()` and remove the `if let` statement in the for loop + --> tests/ui/manual_flatten.rs:183:9 | LL | / if let Some(n) = n { LL | | println!("{:?}", n); @@ -201,7 +250,9 @@ LL | for n in vec![ ... LL | Some(3) LL ~ ].iter().flatten() { +LL + println!("{:?}", n); +LL + } | -error: aborting due to 9 previous errors +error: aborting due to 10 previous errors diff --git a/tests/ui/manual_inspect.fixed b/tests/ui/manual_inspect.fixed index 9b768dbad70..00a19155a51 100644 --- a/tests/ui/manual_inspect.fixed +++ b/tests/ui/manual_inspect.fixed @@ -154,7 +154,6 @@ fn main() { }); let _ = [0] - //~^ suspicious_map .into_iter() .inspect(|&x| { //~^ manual_inspect diff --git a/tests/ui/manual_inspect.rs b/tests/ui/manual_inspect.rs index e679636201e..b3b17139cde 100644 --- a/tests/ui/manual_inspect.rs +++ b/tests/ui/manual_inspect.rs @@ -165,7 +165,6 @@ fn main() { }); let _ = [0] - //~^ suspicious_map .into_iter() .map(|x| { //~^ manual_inspect diff --git a/tests/ui/manual_inspect.stderr b/tests/ui/manual_inspect.stderr index 78b085fdfca..70c00c1f755 100644 --- a/tests/ui/manual_inspect.stderr +++ b/tests/ui/manual_inspect.stderr @@ -157,25 +157,8 @@ LL | LL ~ println!("{}", x); | -error: this call to `map()` won't have an effect on the call to `count()` - --> tests/ui/manual_inspect.rs:167:13 - | -LL | let _ = [0] - | _____________^ -LL | | -LL | | .into_iter() -LL | | .map(|x| { -... | -LL | | }) -LL | | .count(); - | |________________^ - | - = help: make sure you did not confuse `map` with `filter`, `for_each` or `inspect` - = note: `-D clippy::suspicious-map` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::suspicious_map)]` - error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:170:10 + --> tests/ui/manual_inspect.rs:169:10 | LL | .map(|x| { | ^^^ @@ -188,7 +171,7 @@ LL ~ println!("{}", x); | error: using `map` over `inspect` - --> tests/ui/manual_inspect.rs:203:30 + --> tests/ui/manual_inspect.rs:202:30 | LL | if let Some(x) = Some(1).map(|x| { println!("{x}"); | ^^^ @@ -200,5 +183,5 @@ LL | // Do not collapse code into this comment LL ~ }) { | -error: aborting due to 14 previous errors +error: aborting due to 13 previous errors diff --git a/tests/ui/manual_is_ascii_check.fixed b/tests/ui/manual_is_ascii_check.fixed index 7b0d1906834..406336dbd09 100644 --- a/tests/ui/manual_is_ascii_check.fixed +++ b/tests/ui/manual_is_ascii_check.fixed @@ -108,6 +108,8 @@ fn generics() { //~^ manual_is_ascii_check take_while(|c: char| c.is_ascii_uppercase()); //~^ manual_is_ascii_check + take_while(|c: char| c.is_ascii_uppercase()); + //~^ manual_is_ascii_check } fn adds_type_reference() { @@ -115,4 +117,6 @@ fn adds_type_reference() { //~^ manual_is_ascii_check let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c: &&mut char| c.is_ascii_digit()).collect(); //~^ manual_is_ascii_check + let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c: &&mut char| c.is_ascii_digit()).collect(); + //~^ manual_is_ascii_check } diff --git a/tests/ui/manual_is_ascii_check.rs b/tests/ui/manual_is_ascii_check.rs index e4f7fe9f583..a624497e75e 100644 --- a/tests/ui/manual_is_ascii_check.rs +++ b/tests/ui/manual_is_ascii_check.rs @@ -108,6 +108,8 @@ fn generics() { //~^ manual_is_ascii_check take_while(|c: char| ('A'..='Z').contains(&c)); //~^ manual_is_ascii_check + take_while(|c| matches!(c, 'A'..='Z')); + //~^ manual_is_ascii_check } fn adds_type_reference() { @@ -115,4 +117,6 @@ fn adds_type_reference() { //~^ manual_is_ascii_check let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| ('0'..='9').contains(c)).collect(); //~^ manual_is_ascii_check + let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| matches!(c, '0'..='9')).collect(); + //~^ manual_is_ascii_check } diff --git a/tests/ui/manual_is_ascii_check.stderr b/tests/ui/manual_is_ascii_check.stderr index 9fd7f457b42..cb2548ea731 100644 --- a/tests/ui/manual_is_ascii_check.stderr +++ b/tests/ui/manual_is_ascii_check.stderr @@ -176,7 +176,19 @@ LL | take_while(|c: char| ('A'..='Z').contains(&c)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `c.is_ascii_uppercase()` error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:114:63 + --> tests/ui/manual_is_ascii_check.rs:111:20 + | +LL | take_while(|c| matches!(c, 'A'..='Z')); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - take_while(|c| matches!(c, 'A'..='Z')); +LL + take_while(|c: char| c.is_ascii_uppercase()); + | + +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:116:63 | LL | let digits: Vec<&char> = ['1', 'A'].iter().take_while(|c| ('0'..='9').contains(c)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -188,7 +200,7 @@ LL + let digits: Vec<&char> = ['1', 'A'].iter().take_while(|c: &&char| c.is_ | error: manual check for common ascii range - --> tests/ui/manual_is_ascii_check.rs:116:71 + --> tests/ui/manual_is_ascii_check.rs:118:71 | LL | let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| ('0'..='9').contains(c)).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -199,5 +211,17 @@ LL - let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| ('0'. LL + let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c: &&mut char| c.is_ascii_digit()).collect(); | -error: aborting due to 29 previous errors +error: manual check for common ascii range + --> tests/ui/manual_is_ascii_check.rs:120:71 + | +LL | let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| matches!(c, '0'..='9')).collect(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL - let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c| matches!(c, '0'..='9')).collect(); +LL + let digits: Vec<&mut char> = ['1', 'A'].iter_mut().take_while(|c: &&mut char| c.is_ascii_digit()).collect(); + | + +error: aborting due to 31 previous errors diff --git a/tests/ui/manual_is_multiple_of.fixed b/tests/ui/manual_is_multiple_of.fixed new file mode 100644 index 00000000000..03f75e725ed --- /dev/null +++ b/tests/ui/manual_is_multiple_of.fixed @@ -0,0 +1,103 @@ +//@aux-build: proc_macros.rs +#![warn(clippy::manual_is_multiple_of)] + +fn main() {} + +#[clippy::msrv = "1.87"] +fn f(a: u64, b: u64) { + let _ = a.is_multiple_of(b); //~ manual_is_multiple_of + let _ = (a + 1).is_multiple_of(b + 1); //~ manual_is_multiple_of + let _ = !a.is_multiple_of(b); //~ manual_is_multiple_of + let _ = !(a + 1).is_multiple_of(b + 1); //~ manual_is_multiple_of + + let _ = !a.is_multiple_of(b); //~ manual_is_multiple_of + let _ = !a.is_multiple_of(b); //~ manual_is_multiple_of + + proc_macros::external! { + let a: u64 = 23424; + let _ = a % 4096 == 0; + } +} + +#[clippy::msrv = "1.86"] +fn g(a: u64, b: u64) { + let _ = a % b == 0; +} + +fn needs_deref(a: &u64, b: &u64) { + let _ = a.is_multiple_of(*b); //~ manual_is_multiple_of +} + +fn closures(a: u64, b: u64) { + // Do not lint, types are ambiguous at this point + let cl = |a, b| a % b == 0; + let _ = cl(a, b); + + // Do not lint, types are ambiguous at this point + let cl = |a: _, b: _| a % b == 0; + let _ = cl(a, b); + + // Type of `a` is enough + let cl = |a: u64, b| a.is_multiple_of(b); //~ manual_is_multiple_of + let _ = cl(a, b); + + // Type of `a` is enough + let cl = |a: &u64, b| a.is_multiple_of(b); //~ manual_is_multiple_of + let _ = cl(&a, b); + + // Type of `b` is not enough + let cl = |a, b: u64| a % b == 0; + let _ = cl(&a, b); +} + +fn any_rem<T: std::ops::Rem<Output = u32>>(a: T, b: T) { + // An arbitrary `Rem` implementation should not lint + let _ = a % b == 0; +} + +mod issue15103 { + fn foo() -> Option<u64> { + let mut n: u64 = 150_000_000; + + (2..).find(|p| { + while n.is_multiple_of(*p) { + //~^ manual_is_multiple_of + n /= p; + } + n <= 1 + }) + } + + const fn generate_primes<const N: usize>() -> [u64; N] { + let mut result = [0; N]; + if N == 0 { + return result; + } + result[0] = 2; + if N == 1 { + return result; + } + let mut idx = 1; + let mut p = 3; + while idx < N { + let mut j = 0; + while j < idx && p % result[j] != 0 { + j += 1; + } + if j == idx { + result[idx] = p; + idx += 1; + } + p += 1; + } + result + } + + fn bar() -> u32 { + let d = |n: u32| -> u32 { (1..=n / 2).filter(|i| n.is_multiple_of(*i)).sum() }; + //~^ manual_is_multiple_of + + let d = |n| (1..=n / 2).filter(|i| n % i == 0).sum(); + (1..1_000).filter(|&i| i == d(d(i)) && i != d(i)).sum() + } +} diff --git a/tests/ui/manual_is_multiple_of.rs b/tests/ui/manual_is_multiple_of.rs new file mode 100644 index 00000000000..7b6fa64c843 --- /dev/null +++ b/tests/ui/manual_is_multiple_of.rs @@ -0,0 +1,103 @@ +//@aux-build: proc_macros.rs +#![warn(clippy::manual_is_multiple_of)] + +fn main() {} + +#[clippy::msrv = "1.87"] +fn f(a: u64, b: u64) { + let _ = a % b == 0; //~ manual_is_multiple_of + let _ = (a + 1) % (b + 1) == 0; //~ manual_is_multiple_of + let _ = a % b != 0; //~ manual_is_multiple_of + let _ = (a + 1) % (b + 1) != 0; //~ manual_is_multiple_of + + let _ = a % b > 0; //~ manual_is_multiple_of + let _ = 0 < a % b; //~ manual_is_multiple_of + + proc_macros::external! { + let a: u64 = 23424; + let _ = a % 4096 == 0; + } +} + +#[clippy::msrv = "1.86"] +fn g(a: u64, b: u64) { + let _ = a % b == 0; +} + +fn needs_deref(a: &u64, b: &u64) { + let _ = a % b == 0; //~ manual_is_multiple_of +} + +fn closures(a: u64, b: u64) { + // Do not lint, types are ambiguous at this point + let cl = |a, b| a % b == 0; + let _ = cl(a, b); + + // Do not lint, types are ambiguous at this point + let cl = |a: _, b: _| a % b == 0; + let _ = cl(a, b); + + // Type of `a` is enough + let cl = |a: u64, b| a % b == 0; //~ manual_is_multiple_of + let _ = cl(a, b); + + // Type of `a` is enough + let cl = |a: &u64, b| a % b == 0; //~ manual_is_multiple_of + let _ = cl(&a, b); + + // Type of `b` is not enough + let cl = |a, b: u64| a % b == 0; + let _ = cl(&a, b); +} + +fn any_rem<T: std::ops::Rem<Output = u32>>(a: T, b: T) { + // An arbitrary `Rem` implementation should not lint + let _ = a % b == 0; +} + +mod issue15103 { + fn foo() -> Option<u64> { + let mut n: u64 = 150_000_000; + + (2..).find(|p| { + while n % p == 0 { + //~^ manual_is_multiple_of + n /= p; + } + n <= 1 + }) + } + + const fn generate_primes<const N: usize>() -> [u64; N] { + let mut result = [0; N]; + if N == 0 { + return result; + } + result[0] = 2; + if N == 1 { + return result; + } + let mut idx = 1; + let mut p = 3; + while idx < N { + let mut j = 0; + while j < idx && p % result[j] != 0 { + j += 1; + } + if j == idx { + result[idx] = p; + idx += 1; + } + p += 1; + } + result + } + + fn bar() -> u32 { + let d = |n: u32| -> u32 { (1..=n / 2).filter(|i| n % i == 0).sum() }; + //~^ manual_is_multiple_of + + let d = |n| (1..=n / 2).filter(|i| n % i == 0).sum(); + (1..1_000).filter(|&i| i == d(d(i)) && i != d(i)).sum() + } +} diff --git a/tests/ui/manual_is_multiple_of.stderr b/tests/ui/manual_is_multiple_of.stderr new file mode 100644 index 00000000000..8523599ec40 --- /dev/null +++ b/tests/ui/manual_is_multiple_of.stderr @@ -0,0 +1,71 @@ +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:8:13 + | +LL | let _ = a % b == 0; + | ^^^^^^^^^^ help: replace with: `a.is_multiple_of(b)` + | + = note: `-D clippy::manual-is-multiple-of` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::manual_is_multiple_of)]` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:9:13 + | +LL | let _ = (a + 1) % (b + 1) == 0; + | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `(a + 1).is_multiple_of(b + 1)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:10:13 + | +LL | let _ = a % b != 0; + | ^^^^^^^^^^ help: replace with: `!a.is_multiple_of(b)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:11:13 + | +LL | let _ = (a + 1) % (b + 1) != 0; + | ^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `!(a + 1).is_multiple_of(b + 1)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:13:13 + | +LL | let _ = a % b > 0; + | ^^^^^^^^^ help: replace with: `!a.is_multiple_of(b)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:14:13 + | +LL | let _ = 0 < a % b; + | ^^^^^^^^^ help: replace with: `!a.is_multiple_of(b)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:28:13 + | +LL | let _ = a % b == 0; + | ^^^^^^^^^^ help: replace with: `a.is_multiple_of(*b)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:41:26 + | +LL | let cl = |a: u64, b| a % b == 0; + | ^^^^^^^^^^ help: replace with: `a.is_multiple_of(b)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:45:27 + | +LL | let cl = |a: &u64, b| a % b == 0; + | ^^^^^^^^^^ help: replace with: `a.is_multiple_of(b)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:63:19 + | +LL | while n % p == 0 { + | ^^^^^^^^^^ help: replace with: `n.is_multiple_of(*p)` + +error: manual implementation of `.is_multiple_of()` + --> tests/ui/manual_is_multiple_of.rs:97:58 + | +LL | let d = |n: u32| -> u32 { (1..=n / 2).filter(|i| n % i == 0).sum() }; + | ^^^^^^^^^^ help: replace with: `n.is_multiple_of(*i)` + +error: aborting due to 11 previous errors + diff --git a/tests/ui/manual_is_variant_and.fixed b/tests/ui/manual_is_variant_and.fixed index 18a72188ab5..65a9cfa6e64 100644 --- a/tests/ui/manual_is_variant_and.fixed +++ b/tests/ui/manual_is_variant_and.fixed @@ -61,7 +61,7 @@ fn option_methods() { let _ = Some(2).is_some_and(|x| x % 2 == 0); //~^ manual_is_variant_and - let _ = Some(2).is_none_or(|x| x % 2 == 0); + let _ = Some(2).is_none_or(|x| x % 2 != 0); //~^ manual_is_variant_and let _ = Some(2).is_some_and(|x| x % 2 == 0); //~^ manual_is_variant_and @@ -77,7 +77,7 @@ fn option_methods() { let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint // Should not lint. - let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true); + let _ = Foo::<u32>(0).map(|x| x.is_multiple_of(2)) == Some(true); let _ = Some(2).map(|x| x % 2 == 0) != foo(); let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true)); let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true); @@ -96,11 +96,11 @@ fn result_methods() { }); let _ = res.is_ok_and(|x| x > 1); - let _ = Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0); + let _ = Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2)); //~^ manual_is_variant_and - let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0); + let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2)); //~^ manual_is_variant_and - let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0); + let _ = !Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2)); //~^ manual_is_variant_and // won't fix because the return type of the closure is not `bool` @@ -116,3 +116,113 @@ fn main() { option_methods(); result_methods(); } + +fn issue15202() { + let xs = [None, Some(b'_'), Some(b'1')]; + for x in xs { + let a1 = x.is_none_or(|b| !b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = x.is_none_or(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.is_none_or(|b| b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = x.is_none_or(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.is_some_and(|b| b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = x.is_some_and(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.is_some_and(|b| !b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = x.is_some_and(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + let xs = [Err("foo"), Ok(b'_'), Ok(b'1')]; + for x in xs { + let a1 = !x.is_ok_and(|b| b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = !x.is_ok_and(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = !x.is_ok_and(|b| !b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = !x.is_ok_and(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.is_ok_and(|b| b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = x.is_ok_and(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.is_ok_and(|b| !b.is_ascii_digit()); + //~^ manual_is_variant_and + let a2 = x.is_ok_and(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } +} + +mod with_func { + fn iad(b: u8) -> bool { + b.is_ascii_digit() + } + + fn check_option(b: Option<u8>) { + let a1 = b.is_some_and(iad); + //~^ manual_is_variant_and + let a2 = b.is_some_and(iad); + assert_eq!(a1, a2); + + let a1 = b.is_some_and(|x| !iad(x)); + //~^ manual_is_variant_and + let a2 = b.is_some_and(|x| !iad(x)); + assert_eq!(a1, a2); + + let a1 = b.is_none_or(|x| !iad(x)); + //~^ manual_is_variant_and + let a2 = b.is_none_or(|x| !iad(x)); + assert_eq!(a1, a2); + + let a1 = b.is_none_or(iad); + //~^ manual_is_variant_and + let a2 = b.is_none_or(iad); + assert_eq!(a1, a2); + } + + fn check_result(b: Result<u8, ()>) { + let a1 = b.is_ok_and(iad); + //~^ manual_is_variant_and + let a2 = b.is_ok_and(iad); + assert_eq!(a1, a2); + + let a1 = b.is_ok_and(|x| !iad(x)); + //~^ manual_is_variant_and + let a2 = b.is_ok_and(|x| !iad(x)); + assert_eq!(a1, a2); + + let a1 = !b.is_ok_and(iad); + //~^ manual_is_variant_and + let a2 = !b.is_ok_and(iad); + assert_eq!(a1, a2); + + let a1 = !b.is_ok_and(|x| !iad(x)); + //~^ manual_is_variant_and + let a2 = !b.is_ok_and(|x| !iad(x)); + assert_eq!(a1, a2); + } +} diff --git a/tests/ui/manual_is_variant_and.rs b/tests/ui/manual_is_variant_and.rs index a92f7c04369..85b45d654a7 100644 --- a/tests/ui/manual_is_variant_and.rs +++ b/tests/ui/manual_is_variant_and.rs @@ -83,7 +83,7 @@ fn option_methods() { let _ = opt_map!(opt2, |x| x == 'a').unwrap_or_default(); // should not lint // Should not lint. - let _ = Foo::<u32>(0).map(|x| x % 2 == 0) == Some(true); + let _ = Foo::<u32>(0).map(|x| x.is_multiple_of(2)) == Some(true); let _ = Some(2).map(|x| x % 2 == 0) != foo(); let _ = mac!(eq Some(2).map(|x| x % 2 == 0), Some(true)); let _ = mac!(some 2).map(|x| x % 2 == 0) == Some(true); @@ -105,11 +105,11 @@ fn result_methods() { //~^ manual_is_variant_and .unwrap_or_default(); - let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true); + let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) == Ok(true); //~^ manual_is_variant_and - let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true); + let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true); //~^ manual_is_variant_and - let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true); + let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true); //~^ manual_is_variant_and // won't fix because the return type of the closure is not `bool` @@ -125,3 +125,113 @@ fn main() { option_methods(); result_methods(); } + +fn issue15202() { + let xs = [None, Some(b'_'), Some(b'1')]; + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) != Some(true); + //~^ manual_is_variant_and + let a2 = x.is_none_or(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) != Some(false); + //~^ manual_is_variant_and + let a2 = x.is_none_or(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) == Some(true); + //~^ manual_is_variant_and + let a2 = x.is_some_and(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) == Some(false); + //~^ manual_is_variant_and + let a2 = x.is_some_and(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + let xs = [Err("foo"), Ok(b'_'), Ok(b'1')]; + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) != Ok(true); + //~^ manual_is_variant_and + let a2 = !x.is_ok_and(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) != Ok(false); + //~^ manual_is_variant_and + let a2 = !x.is_ok_and(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) == Ok(true); + //~^ manual_is_variant_and + let a2 = x.is_ok_and(|b| b.is_ascii_digit()); + assert_eq!(a1, a2); + } + + for x in xs { + let a1 = x.map(|b| b.is_ascii_digit()) == Ok(false); + //~^ manual_is_variant_and + let a2 = x.is_ok_and(|b| !b.is_ascii_digit()); + assert_eq!(a1, a2); + } +} + +mod with_func { + fn iad(b: u8) -> bool { + b.is_ascii_digit() + } + + fn check_option(b: Option<u8>) { + let a1 = b.map(iad) == Some(true); + //~^ manual_is_variant_and + let a2 = b.is_some_and(iad); + assert_eq!(a1, a2); + + let a1 = b.map(iad) == Some(false); + //~^ manual_is_variant_and + let a2 = b.is_some_and(|x| !iad(x)); + assert_eq!(a1, a2); + + let a1 = b.map(iad) != Some(true); + //~^ manual_is_variant_and + let a2 = b.is_none_or(|x| !iad(x)); + assert_eq!(a1, a2); + + let a1 = b.map(iad) != Some(false); + //~^ manual_is_variant_and + let a2 = b.is_none_or(iad); + assert_eq!(a1, a2); + } + + fn check_result(b: Result<u8, ()>) { + let a1 = b.map(iad) == Ok(true); + //~^ manual_is_variant_and + let a2 = b.is_ok_and(iad); + assert_eq!(a1, a2); + + let a1 = b.map(iad) == Ok(false); + //~^ manual_is_variant_and + let a2 = b.is_ok_and(|x| !iad(x)); + assert_eq!(a1, a2); + + let a1 = b.map(iad) != Ok(true); + //~^ manual_is_variant_and + let a2 = !b.is_ok_and(iad); + assert_eq!(a1, a2); + + let a1 = b.map(iad) != Ok(false); + //~^ manual_is_variant_and + let a2 = !b.is_ok_and(|x| !iad(x)); + assert_eq!(a1, a2); + } +} diff --git a/tests/ui/manual_is_variant_and.stderr b/tests/ui/manual_is_variant_and.stderr index 1fb437a8bc7..da36b5a07d2 100644 --- a/tests/ui/manual_is_variant_and.stderr +++ b/tests/ui/manual_is_variant_and.stderr @@ -54,7 +54,7 @@ error: called `.map() != Some()` --> tests/ui/manual_is_variant_and.rs:70:13 | LL | let _ = Some(2).map(|x| x % 2 == 0) != Some(true); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 == 0)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Some(2).is_none_or(|x| x % 2 != 0)` error: called `.map() == Some()` --> tests/ui/manual_is_variant_and.rs:72:13 @@ -105,20 +105,20 @@ LL | | .unwrap_or_default(); error: called `.map() == Ok()` --> tests/ui/manual_is_variant_and.rs:108:13 | -LL | let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) == Ok(true); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)` +LL | let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) == Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2))` error: called `.map() != Ok()` --> tests/ui/manual_is_variant_and.rs:110:13 | -LL | let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)` +LL | let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2))` error: called `.map() != Ok()` --> tests/ui/manual_is_variant_and.rs:112:13 | -LL | let _ = Ok::<usize, ()>(2).map(|x| x % 2 == 0) != Ok(true); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x % 2 == 0)` +LL | let _ = Ok::<usize, ()>(2).map(|x| x.is_multiple_of(2)) != Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!Ok::<usize, ()>(2).is_ok_and(|x| x.is_multiple_of(2))` error: called `map(<f>).unwrap_or_default()` on a `Result` value --> tests/ui/manual_is_variant_and.rs:119:18 @@ -126,5 +126,101 @@ error: called `map(<f>).unwrap_or_default()` on a `Result` value LL | let _ = res2.map(char::is_alphanumeric).unwrap_or_default(); // should lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `is_ok_and(char::is_alphanumeric)` -error: aborting due to 15 previous errors +error: called `.map() != Some()` + --> tests/ui/manual_is_variant_and.rs:132:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) != Some(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_none_or(|b| !b.is_ascii_digit())` + +error: called `.map() != Some()` + --> tests/ui/manual_is_variant_and.rs:139:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) != Some(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_none_or(|b| b.is_ascii_digit())` + +error: called `.map() == Some()` + --> tests/ui/manual_is_variant_and.rs:146:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) == Some(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_some_and(|b| b.is_ascii_digit())` + +error: called `.map() == Some()` + --> tests/ui/manual_is_variant_and.rs:153:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) == Some(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_some_and(|b| !b.is_ascii_digit())` + +error: called `.map() != Ok()` + --> tests/ui/manual_is_variant_and.rs:161:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) != Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!x.is_ok_and(|b| b.is_ascii_digit())` + +error: called `.map() != Ok()` + --> tests/ui/manual_is_variant_and.rs:168:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) != Ok(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!x.is_ok_and(|b| !b.is_ascii_digit())` + +error: called `.map() == Ok()` + --> tests/ui/manual_is_variant_and.rs:175:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) == Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_ok_and(|b| b.is_ascii_digit())` + +error: called `.map() == Ok()` + --> tests/ui/manual_is_variant_and.rs:182:18 + | +LL | let a1 = x.map(|b| b.is_ascii_digit()) == Ok(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `x.is_ok_and(|b| !b.is_ascii_digit())` + +error: called `.map() == Some()` + --> tests/ui/manual_is_variant_and.rs:195:18 + | +LL | let a1 = b.map(iad) == Some(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_some_and(iad)` + +error: called `.map() == Some()` + --> tests/ui/manual_is_variant_and.rs:200:18 + | +LL | let a1 = b.map(iad) == Some(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_some_and(|x| !iad(x))` + +error: called `.map() != Some()` + --> tests/ui/manual_is_variant_and.rs:205:18 + | +LL | let a1 = b.map(iad) != Some(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_none_or(|x| !iad(x))` + +error: called `.map() != Some()` + --> tests/ui/manual_is_variant_and.rs:210:18 + | +LL | let a1 = b.map(iad) != Some(false); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_none_or(iad)` + +error: called `.map() == Ok()` + --> tests/ui/manual_is_variant_and.rs:217:18 + | +LL | let a1 = b.map(iad) == Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_ok_and(iad)` + +error: called `.map() == Ok()` + --> tests/ui/manual_is_variant_and.rs:222:18 + | +LL | let a1 = b.map(iad) == Ok(false); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use: `b.is_ok_and(|x| !iad(x))` + +error: called `.map() != Ok()` + --> tests/ui/manual_is_variant_and.rs:227:18 + | +LL | let a1 = b.map(iad) != Ok(true); + | ^^^^^^^^^^^^^^^^^^^^^^ help: use: `!b.is_ok_and(iad)` + +error: called `.map() != Ok()` + --> tests/ui/manual_is_variant_and.rs:232:18 + | +LL | let a1 = b.map(iad) != Ok(false); + | ^^^^^^^^^^^^^^^^^^^^^^^ help: use: `!b.is_ok_and(|x| !iad(x))` + +error: aborting due to 31 previous errors diff --git a/tests/ui/manual_let_else_match.fixed b/tests/ui/manual_let_else_match.fixed index 588ba5edd8f..15f604aec29 100644 --- a/tests/ui/manual_let_else_match.fixed +++ b/tests/ui/manual_let_else_match.fixed @@ -137,3 +137,48 @@ fn not_fire() { fn issue11579() { let Some(msg) = Some("hi") else { unreachable!("can't happen") }; } + +#[derive(Clone, Copy)] +struct Issue9939<T> { + avalanche: T, +} + +fn issue9939() { + let issue = Some(Issue9939 { avalanche: 1 }); + let Some(Issue9939 { avalanche: tornado }) = issue else { unreachable!("can't happen") }; + let issue = Some(Issue9939 { avalanche: true }); + let Some(Issue9939 { avalanche: acid_rain }) = issue else { unreachable!("can't happen") }; + assert_eq!(tornado, 1); + assert!(acid_rain); + + // without shadowing + let _x @ Some(Issue9939 { avalanche: _y }) = issue else { unreachable!("can't happen") }; + + // with shadowing + let Some(Issue9939 { avalanche: _x }) = issue else { unreachable!("can't happen") }; +} + +#[derive(Clone, Copy)] +struct Issue9939b<T, U> { + earthquake: T, + hurricane: U, +} + +fn issue9939b() { + let issue = Some(Issue9939b { + earthquake: true, + hurricane: 1, + }); + let issue @ Some(Issue9939b { earthquake: flood, hurricane: drought }) = issue else { unreachable!("can't happen") }; + assert_eq!(drought, 1); + assert!(flood); + assert!(issue.is_some()); + + // without shadowing + let _x @ Some(Issue9939b { earthquake: erosion, hurricane: _y }) = issue else { unreachable!("can't happen") }; + assert!(erosion); + + // with shadowing + let Some(Issue9939b { earthquake: erosion, hurricane: _x }) = issue else { unreachable!("can't happen") }; + assert!(erosion); +} diff --git a/tests/ui/manual_let_else_match.rs b/tests/ui/manual_let_else_match.rs index 6416753bac1..44a044b142b 100644 --- a/tests/ui/manual_let_else_match.rs +++ b/tests/ui/manual_let_else_match.rs @@ -177,3 +177,76 @@ fn issue11579() { _ => unreachable!("can't happen"), }; } + +#[derive(Clone, Copy)] +struct Issue9939<T> { + avalanche: T, +} + +fn issue9939() { + let issue = Some(Issue9939 { avalanche: 1 }); + let tornado = match issue { + //~^ manual_let_else + Some(Issue9939 { avalanche }) => avalanche, + _ => unreachable!("can't happen"), + }; + let issue = Some(Issue9939 { avalanche: true }); + let acid_rain = match issue { + //~^ manual_let_else + Some(Issue9939 { avalanche: tornado }) => tornado, + _ => unreachable!("can't happen"), + }; + assert_eq!(tornado, 1); + assert!(acid_rain); + + // without shadowing + let _y = match issue { + //~^ manual_let_else + _x @ Some(Issue9939 { avalanche }) => avalanche, + None => unreachable!("can't happen"), + }; + + // with shadowing + let _x = match issue { + //~^ manual_let_else + _x @ Some(Issue9939 { avalanche }) => avalanche, + None => unreachable!("can't happen"), + }; +} + +#[derive(Clone, Copy)] +struct Issue9939b<T, U> { + earthquake: T, + hurricane: U, +} + +fn issue9939b() { + let issue = Some(Issue9939b { + earthquake: true, + hurricane: 1, + }); + let (issue, drought, flood) = match issue { + //~^ manual_let_else + flood @ Some(Issue9939b { earthquake, hurricane }) => (flood, hurricane, earthquake), + None => unreachable!("can't happen"), + }; + assert_eq!(drought, 1); + assert!(flood); + assert!(issue.is_some()); + + // without shadowing + let (_y, erosion) = match issue { + //~^ manual_let_else + _x @ Some(Issue9939b { earthquake, hurricane }) => (hurricane, earthquake), + None => unreachable!("can't happen"), + }; + assert!(erosion); + + // with shadowing + let (_x, erosion) = match issue { + //~^ manual_let_else + _x @ Some(Issue9939b { earthquake, hurricane }) => (hurricane, earthquake), + None => unreachable!("can't happen"), + }; + assert!(erosion); +} diff --git a/tests/ui/manual_let_else_match.stderr b/tests/ui/manual_let_else_match.stderr index 393562c629b..ed6117ebffb 100644 --- a/tests/ui/manual_let_else_match.stderr +++ b/tests/ui/manual_let_else_match.stderr @@ -101,5 +101,75 @@ LL | | _ => unreachable!("can't happen"), LL | | }; | |______^ help: consider writing: `let Some(msg) = Some("hi") else { unreachable!("can't happen") };` -error: aborting due to 10 previous errors +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:188:5 + | +LL | / let tornado = match issue { +LL | | +LL | | Some(Issue9939 { avalanche }) => avalanche, +LL | | _ => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let Some(Issue9939 { avalanche: tornado }) = issue else { unreachable!("can't happen") };` + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:194:5 + | +LL | / let acid_rain = match issue { +LL | | +LL | | Some(Issue9939 { avalanche: tornado }) => tornado, +LL | | _ => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let Some(Issue9939 { avalanche: acid_rain }) = issue else { unreachable!("can't happen") };` + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:203:5 + | +LL | / let _y = match issue { +LL | | +LL | | _x @ Some(Issue9939 { avalanche }) => avalanche, +LL | | None => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let _x @ Some(Issue9939 { avalanche: _y }) = issue else { unreachable!("can't happen") };` + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:210:5 + | +LL | / let _x = match issue { +LL | | +LL | | _x @ Some(Issue9939 { avalanche }) => avalanche, +LL | | None => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let Some(Issue9939 { avalanche: _x }) = issue else { unreachable!("can't happen") };` + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:228:5 + | +LL | / let (issue, drought, flood) = match issue { +LL | | +LL | | flood @ Some(Issue9939b { earthquake, hurricane }) => (flood, hurricane, earthquake), +LL | | None => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let issue @ Some(Issue9939b { earthquake: flood, hurricane: drought }) = issue else { unreachable!("can't happen") };` + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:238:5 + | +LL | / let (_y, erosion) = match issue { +LL | | +LL | | _x @ Some(Issue9939b { earthquake, hurricane }) => (hurricane, earthquake), +LL | | None => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let _x @ Some(Issue9939b { earthquake: erosion, hurricane: _y }) = issue else { unreachable!("can't happen") };` + +error: this could be rewritten as `let...else` + --> tests/ui/manual_let_else_match.rs:246:5 + | +LL | / let (_x, erosion) = match issue { +LL | | +LL | | _x @ Some(Issue9939b { earthquake, hurricane }) => (hurricane, earthquake), +LL | | None => unreachable!("can't happen"), +LL | | }; + | |______^ help: consider writing: `let Some(Issue9939b { earthquake: erosion, hurricane: _x }) = issue else { unreachable!("can't happen") };` + +error: aborting due to 17 previous errors diff --git a/tests/ui/manual_ok_err.fixed b/tests/ui/manual_ok_err.fixed index e6f799aa58d..9b70ce0df43 100644 --- a/tests/ui/manual_ok_err.fixed +++ b/tests/ui/manual_ok_err.fixed @@ -103,3 +103,27 @@ fn issue14239() { }; //~^^^^^ manual_ok_err } + +mod issue15051 { + struct Container { + field: Result<bool, ()>, + } + + #[allow(clippy::needless_borrow)] + fn with_addr_of(x: &Container) -> Option<&bool> { + (&x.field).as_ref().ok() + } + + fn from_fn(x: &Container) -> Option<&bool> { + let result_with_ref = || &x.field; + result_with_ref().as_ref().ok() + } + + fn result_with_ref_mut(x: &mut Container) -> &mut Result<bool, ()> { + &mut x.field + } + + fn from_fn_mut(x: &mut Container) -> Option<&mut bool> { + result_with_ref_mut(x).as_mut().ok() + } +} diff --git a/tests/ui/manual_ok_err.rs b/tests/ui/manual_ok_err.rs index 972b2c41ee7..dee90463824 100644 --- a/tests/ui/manual_ok_err.rs +++ b/tests/ui/manual_ok_err.rs @@ -141,3 +141,39 @@ fn issue14239() { }; //~^^^^^ manual_ok_err } + +mod issue15051 { + struct Container { + field: Result<bool, ()>, + } + + #[allow(clippy::needless_borrow)] + fn with_addr_of(x: &Container) -> Option<&bool> { + match &x.field { + //~^ manual_ok_err + Ok(panel) => Some(panel), + Err(_) => None, + } + } + + fn from_fn(x: &Container) -> Option<&bool> { + let result_with_ref = || &x.field; + match result_with_ref() { + //~^ manual_ok_err + Ok(panel) => Some(panel), + Err(_) => None, + } + } + + fn result_with_ref_mut(x: &mut Container) -> &mut Result<bool, ()> { + &mut x.field + } + + fn from_fn_mut(x: &mut Container) -> Option<&mut bool> { + match result_with_ref_mut(x) { + //~^ manual_ok_err + Ok(panel) => Some(panel), + Err(_) => None, + } + } +} diff --git a/tests/ui/manual_ok_err.stderr b/tests/ui/manual_ok_err.stderr index 040e170f397..448fbffc050 100644 --- a/tests/ui/manual_ok_err.stderr +++ b/tests/ui/manual_ok_err.stderr @@ -111,5 +111,35 @@ LL + "1".parse::<u8>().ok() LL ~ }; | -error: aborting due to 9 previous errors +error: manual implementation of `ok` + --> tests/ui/manual_ok_err.rs:152:9 + | +LL | / match &x.field { +LL | | +LL | | Ok(panel) => Some(panel), +LL | | Err(_) => None, +LL | | } + | |_________^ help: replace with: `(&x.field).as_ref().ok()` + +error: manual implementation of `ok` + --> tests/ui/manual_ok_err.rs:161:9 + | +LL | / match result_with_ref() { +LL | | +LL | | Ok(panel) => Some(panel), +LL | | Err(_) => None, +LL | | } + | |_________^ help: replace with: `result_with_ref().as_ref().ok()` + +error: manual implementation of `ok` + --> tests/ui/manual_ok_err.rs:173:9 + | +LL | / match result_with_ref_mut(x) { +LL | | +LL | | Ok(panel) => Some(panel), +LL | | Err(_) => None, +LL | | } + | |_________^ help: replace with: `result_with_ref_mut(x).as_mut().ok()` + +error: aborting due to 12 previous errors diff --git a/tests/ui/manual_strip.rs b/tests/ui/manual_strip.rs index 086b75a3987..0fdaa1c045e 100644 --- a/tests/ui/manual_strip.rs +++ b/tests/ui/manual_strip.rs @@ -75,7 +75,7 @@ fn main() { s4[2..].to_string(); } - // Don't propose to reuse the `stripped` identifier as it is overriden + // Don't propose to reuse the `stripped` identifier as it is overridden if s.starts_with("ab") { let stripped = &s["ab".len()..]; //~^ ERROR: stripping a prefix manually diff --git a/tests/ui/manual_swap_auto_fix.fixed b/tests/ui/manual_swap_auto_fix.fixed index 28466ff3f9b..6cd81bafce8 100644 --- a/tests/ui/manual_swap_auto_fix.fixed +++ b/tests/ui/manual_swap_auto_fix.fixed @@ -55,3 +55,14 @@ fn swap8() { let i2 = 1; v.swap(i1 + i2, i2); } + +fn issue_14931() { + let mut v = [1, 2, 3, 4]; + + let mut i1 = 0; + for i2 in 0..4 { + v.swap(i1, i2); + + i1 += 2; + } +} diff --git a/tests/ui/manual_swap_auto_fix.rs b/tests/ui/manual_swap_auto_fix.rs index c9880e651cd..19dabfd833f 100644 --- a/tests/ui/manual_swap_auto_fix.rs +++ b/tests/ui/manual_swap_auto_fix.rs @@ -78,3 +78,17 @@ fn swap8() { v[i1 + i2] = v[i2]; v[i2] = tmp; } + +fn issue_14931() { + let mut v = [1, 2, 3, 4]; + + let mut i1 = 0; + for i2 in 0..4 { + let tmp = v[i1]; + //~^ manual_swap + v[i1] = v[i2]; + v[i2] = tmp; + + i1 += 2; + } +} diff --git a/tests/ui/manual_swap_auto_fix.stderr b/tests/ui/manual_swap_auto_fix.stderr index 7ab898fcc72..a0bb32233e2 100644 --- a/tests/ui/manual_swap_auto_fix.stderr +++ b/tests/ui/manual_swap_auto_fix.stderr @@ -92,5 +92,14 @@ LL | | v[i1 + i2] = v[i2]; LL | | v[i2] = tmp; | |________________^ help: try: `v.swap(i1 + i2, i2);` -error: aborting due to 8 previous errors +error: this looks like you are swapping elements of `v` manually + --> tests/ui/manual_swap_auto_fix.rs:87:9 + | +LL | / let tmp = v[i1]; +LL | | +LL | | v[i1] = v[i2]; +LL | | v[i2] = tmp; + | |____________________^ help: try: `v.swap(i1, i2);` + +error: aborting due to 9 previous errors diff --git a/tests/ui/manual_unwrap_or_default.fixed b/tests/ui/manual_unwrap_or_default.fixed index 41ca44ceef4..189fe876aa5 100644 --- a/tests/ui/manual_unwrap_or_default.fixed +++ b/tests/ui/manual_unwrap_or_default.fixed @@ -102,7 +102,7 @@ fn issue_12928() { let y = if let Some(Y(a, ..)) = x { a } else { 0 }; } -// For symetry with `manual_unwrap_or` test +// For symmetry with `manual_unwrap_or` test fn allowed_manual_unwrap_or_zero() -> u32 { Some(42).unwrap_or_default() } diff --git a/tests/ui/manual_unwrap_or_default.rs b/tests/ui/manual_unwrap_or_default.rs index 343fbc4879c..ca87926763c 100644 --- a/tests/ui/manual_unwrap_or_default.rs +++ b/tests/ui/manual_unwrap_or_default.rs @@ -138,7 +138,7 @@ fn issue_12928() { let y = if let Some(Y(a, ..)) = x { a } else { 0 }; } -// For symetry with `manual_unwrap_or` test +// For symmetry with `manual_unwrap_or` test fn allowed_manual_unwrap_or_zero() -> u32 { if let Some(x) = Some(42) { //~^ manual_unwrap_or_default diff --git a/tests/ui/map_flatten.rs b/tests/ui/map_flatten.rs index d7e9c9d9900..0970da8039a 100644 --- a/tests/ui/map_flatten.rs +++ b/tests/ui/map_flatten.rs @@ -1,5 +1,5 @@ #![warn(clippy::map_flatten)] -#![feature(result_flattening)] + //@no-rustfix // issue #8506, multi-line #[rustfmt::skip] diff --git a/tests/ui/map_flatten_fixable.fixed b/tests/ui/map_flatten_fixable.fixed index f8379ed23c5..6d8a27d3018 100644 --- a/tests/ui/map_flatten_fixable.fixed +++ b/tests/ui/map_flatten_fixable.fixed @@ -1,4 +1,3 @@ -#![feature(result_flattening)] #![allow( clippy::let_underscore_untyped, clippy::missing_docs_in_private_items, diff --git a/tests/ui/map_flatten_fixable.rs b/tests/ui/map_flatten_fixable.rs index 040a9ca85f6..845e3a79ae2 100644 --- a/tests/ui/map_flatten_fixable.rs +++ b/tests/ui/map_flatten_fixable.rs @@ -1,4 +1,3 @@ -#![feature(result_flattening)] #![allow( clippy::let_underscore_untyped, clippy::missing_docs_in_private_items, diff --git a/tests/ui/map_flatten_fixable.stderr b/tests/ui/map_flatten_fixable.stderr index fe68eb7e4ab..05d4d9a6ad8 100644 --- a/tests/ui/map_flatten_fixable.stderr +++ b/tests/ui/map_flatten_fixable.stderr @@ -1,5 +1,5 @@ error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:17:47 + --> tests/ui/map_flatten_fixable.rs:16:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id)` @@ -8,43 +8,43 @@ LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id).flatten().coll = help: to override `-D warnings` add `#[allow(clippy::map_flatten)]` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:19:47 + --> tests/ui/map_flatten_fixable.rs:18:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_ref).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_ref)` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:21:47 + --> tests/ui/map_flatten_fixable.rs:20:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(option_id_closure).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(option_id_closure)` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:23:47 + --> tests/ui/map_flatten_fixable.rs:22:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| x.checked_add(1)).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `filter_map` and remove the `.flatten()`: `filter_map(|x| x.checked_add(1))` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:27:47 + --> tests/ui/map_flatten_fixable.rs:26:47 | LL | let _: Vec<_> = vec![5_i8; 6].into_iter().map(|x| 0..x).flatten().collect(); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `flat_map` and remove the `.flatten()`: `flat_map(|x| 0..x)` error: called `map(..).flatten()` on `Option` - --> tests/ui/map_flatten_fixable.rs:31:40 + --> tests/ui/map_flatten_fixable.rs:30:40 | LL | let _: Option<_> = (Some(Some(1))).map(|x| x).flatten(); | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)` error: called `map(..).flatten()` on `Result` - --> tests/ui/map_flatten_fixable.rs:35:42 + --> tests/ui/map_flatten_fixable.rs:34:42 | LL | let _: Result<_, &str> = (Ok(Ok(1))).map(|x| x).flatten(); | ^^^^^^^^^^^^^^^^^^^^ help: try replacing `map` with `and_then` and remove the `.flatten()`: `and_then(|x| x)` error: called `map(..).flatten()` on `Iterator` - --> tests/ui/map_flatten_fixable.rs:45:10 + --> tests/ui/map_flatten_fixable.rs:44:10 | LL | .map(|n| match n { | __________^ @@ -74,7 +74,7 @@ LL ~ }); | error: called `map(..).flatten()` on `Option` - --> tests/ui/map_flatten_fixable.rs:66:10 + --> tests/ui/map_flatten_fixable.rs:65:10 | LL | .map(|_| { | __________^ diff --git a/tests/ui/map_identity.fixed b/tests/ui/map_identity.fixed index 83b2dac5fc5..6c971ba6338 100644 --- a/tests/ui/map_identity.fixed +++ b/tests/ui/map_identity.fixed @@ -1,5 +1,5 @@ #![warn(clippy::map_identity)] -#![allow(clippy::needless_return)] +#![allow(clippy::needless_return, clippy::disallowed_names)] fn main() { let x: [u16; 3] = [1, 2, 3]; @@ -87,3 +87,77 @@ fn issue13904() { let _ = { it }.next(); //~^ map_identity } + +// same as `issue11764`, but for arrays +fn issue15198() { + let x = [[1, 2], [3, 4]]; + // don't lint: `&[i32; 2]` becomes `[&i32; 2]` + let _ = x.iter().map(|[x, y]| [x, y]); + let _ = x.iter().map(|x| [x[0]]).map(|[x]| x); + + // no match ergonomics for `[i32, i32]` + let _ = x.iter().copied(); + //~^ map_identity +} + +mod foo { + #[derive(Clone, Copy)] + pub struct Foo { + pub foo: u8, + pub bar: u8, + } + + #[derive(Clone, Copy)] + pub struct Foo2(pub u8, pub u8); +} +use foo::{Foo, Foo2}; + +struct Bar { + foo: u8, + bar: u8, +} + +struct Bar2(u8, u8); + +fn structs() { + let x = [Foo { foo: 0, bar: 0 }]; + + let _ = x.into_iter(); + //~^ map_identity + + // still lint when different paths are used for the same struct + let _ = x.into_iter(); + //~^ map_identity + + // don't lint: same fields but different structs + let _ = x.into_iter().map(|Foo { foo, bar }| Bar { foo, bar }); + + // still lint with redundant field names + #[allow(clippy::redundant_field_names)] + let _ = x.into_iter(); + //~^ map_identity + + // still lint with field order change + let _ = x.into_iter(); + //~^ map_identity + + // don't lint: switched field assignment + let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: bar, bar: foo }); +} + +fn tuple_structs() { + let x = [Foo2(0, 0)]; + + let _ = x.into_iter(); + //~^ map_identity + + // still lint when different paths are used for the same struct + let _ = x.into_iter(); + //~^ map_identity + + // don't lint: same fields but different structs + let _ = x.into_iter().map(|Foo2(foo, bar)| Bar2(foo, bar)); + + // don't lint: switched field assignment + let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(bar, foo)); +} diff --git a/tests/ui/map_identity.rs b/tests/ui/map_identity.rs index e839c551364..59dcfcda3b6 100644 --- a/tests/ui/map_identity.rs +++ b/tests/ui/map_identity.rs @@ -1,5 +1,5 @@ #![warn(clippy::map_identity)] -#![allow(clippy::needless_return)] +#![allow(clippy::needless_return, clippy::disallowed_names)] fn main() { let x: [u16; 3] = [1, 2, 3]; @@ -93,3 +93,77 @@ fn issue13904() { let _ = { it }.map(|x| x).next(); //~^ map_identity } + +// same as `issue11764`, but for arrays +fn issue15198() { + let x = [[1, 2], [3, 4]]; + // don't lint: `&[i32; 2]` becomes `[&i32; 2]` + let _ = x.iter().map(|[x, y]| [x, y]); + let _ = x.iter().map(|x| [x[0]]).map(|[x]| x); + + // no match ergonomics for `[i32, i32]` + let _ = x.iter().copied().map(|[x, y]| [x, y]); + //~^ map_identity +} + +mod foo { + #[derive(Clone, Copy)] + pub struct Foo { + pub foo: u8, + pub bar: u8, + } + + #[derive(Clone, Copy)] + pub struct Foo2(pub u8, pub u8); +} +use foo::{Foo, Foo2}; + +struct Bar { + foo: u8, + bar: u8, +} + +struct Bar2(u8, u8); + +fn structs() { + let x = [Foo { foo: 0, bar: 0 }]; + + let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo, bar }); + //~^ map_identity + + // still lint when different paths are used for the same struct + let _ = x.into_iter().map(|Foo { foo, bar }| foo::Foo { foo, bar }); + //~^ map_identity + + // don't lint: same fields but different structs + let _ = x.into_iter().map(|Foo { foo, bar }| Bar { foo, bar }); + + // still lint with redundant field names + #[allow(clippy::redundant_field_names)] + let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: foo, bar: bar }); + //~^ map_identity + + // still lint with field order change + let _ = x.into_iter().map(|Foo { foo, bar }| Foo { bar, foo }); + //~^ map_identity + + // don't lint: switched field assignment + let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: bar, bar: foo }); +} + +fn tuple_structs() { + let x = [Foo2(0, 0)]; + + let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(foo, bar)); + //~^ map_identity + + // still lint when different paths are used for the same struct + let _ = x.into_iter().map(|Foo2(foo, bar)| foo::Foo2(foo, bar)); + //~^ map_identity + + // don't lint: same fields but different structs + let _ = x.into_iter().map(|Foo2(foo, bar)| Bar2(foo, bar)); + + // don't lint: switched field assignment + let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(bar, foo)); +} diff --git a/tests/ui/map_identity.stderr b/tests/ui/map_identity.stderr index 9836f3b4cc5..a50c0d6b87b 100644 --- a/tests/ui/map_identity.stderr +++ b/tests/ui/map_identity.stderr @@ -87,5 +87,47 @@ error: unnecessary map of the identity function LL | let _ = { it }.map(|x| x).next(); | ^^^^^^^^^^^ help: remove the call to `map` -error: aborting due to 13 previous errors +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:105:30 + | +LL | let _ = x.iter().copied().map(|[x, y]| [x, y]); + | ^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:131:26 + | +LL | let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo, bar }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:135:26 + | +LL | let _ = x.into_iter().map(|Foo { foo, bar }| foo::Foo { foo, bar }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:143:26 + | +LL | let _ = x.into_iter().map(|Foo { foo, bar }| Foo { foo: foo, bar: bar }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:147:26 + | +LL | let _ = x.into_iter().map(|Foo { foo, bar }| Foo { bar, foo }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:157:26 + | +LL | let _ = x.into_iter().map(|Foo2(foo, bar)| Foo2(foo, bar)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: unnecessary map of the identity function + --> tests/ui/map_identity.rs:161:26 + | +LL | let _ = x.into_iter().map(|Foo2(foo, bar)| foo::Foo2(foo, bar)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove the call to `map` + +error: aborting due to 20 previous errors diff --git a/tests/ui/match_bool.fixed b/tests/ui/match_bool.fixed index 1dfb82db120..876ae935afd 100644 --- a/tests/ui/match_bool.fixed +++ b/tests/ui/match_bool.fixed @@ -61,4 +61,17 @@ fn issue14099() { } } } +fn issue15351() { + let mut d = false; + match d { + false => println!("foo"), + ref mut d => *d = false, + } + + match d { + false => println!("foo"), + e => println!("{e}"), + } +} + fn main() {} diff --git a/tests/ui/match_bool.rs b/tests/ui/match_bool.rs index 719b4e51eb6..a134ad8346e 100644 --- a/tests/ui/match_bool.rs +++ b/tests/ui/match_bool.rs @@ -113,4 +113,17 @@ fn issue14099() { } } +fn issue15351() { + let mut d = false; + match d { + false => println!("foo"), + ref mut d => *d = false, + } + + match d { + false => println!("foo"), + e => println!("{e}"), + } +} + fn main() {} diff --git a/tests/ui/match_ref_pats.fixed b/tests/ui/match_ref_pats.fixed index 8add3da0c99..f727546838b 100644 --- a/tests/ui/match_ref_pats.fixed +++ b/tests/ui/match_ref_pats.fixed @@ -1,6 +1,12 @@ #![warn(clippy::match_ref_pats)] #![allow(dead_code, unused_variables)] -#![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)] +#![allow( + clippy::enum_variant_names, + clippy::equatable_if_let, + clippy::uninlined_format_args, + clippy::empty_loop, + clippy::diverging_sub_expression +)] fn ref_pats() { { @@ -120,4 +126,32 @@ mod issue_7740 { } } +mod issue15378 { + fn never_in_match() { + match unimplemented!() { + &_ => {}, + &&&42 => { + todo!() + }, + _ => {}, + } + + match panic!() { + &_ => {}, + &&&42 => { + todo!() + }, + _ => {}, + } + + match loop {} { + &_ => {}, + &&&42 => { + todo!() + }, + _ => {}, + } + } +} + fn main() {} diff --git a/tests/ui/match_ref_pats.rs b/tests/ui/match_ref_pats.rs index 07889b0dfc2..eca4d584acd 100644 --- a/tests/ui/match_ref_pats.rs +++ b/tests/ui/match_ref_pats.rs @@ -1,6 +1,12 @@ #![warn(clippy::match_ref_pats)] #![allow(dead_code, unused_variables)] -#![allow(clippy::enum_variant_names, clippy::equatable_if_let, clippy::uninlined_format_args)] +#![allow( + clippy::enum_variant_names, + clippy::equatable_if_let, + clippy::uninlined_format_args, + clippy::empty_loop, + clippy::diverging_sub_expression +)] fn ref_pats() { { @@ -120,4 +126,32 @@ mod issue_7740 { } } +mod issue15378 { + fn never_in_match() { + match unimplemented!() { + &_ => {}, + &&&42 => { + todo!() + }, + _ => {}, + } + + match panic!() { + &_ => {}, + &&&42 => { + todo!() + }, + _ => {}, + } + + match loop {} { + &_ => {}, + &&&42 => { + todo!() + }, + _ => {}, + } + } +} + fn main() {} diff --git a/tests/ui/match_ref_pats.stderr b/tests/ui/match_ref_pats.stderr index f81b290b32c..ecb08e6972d 100644 --- a/tests/ui/match_ref_pats.stderr +++ b/tests/ui/match_ref_pats.stderr @@ -1,5 +1,5 @@ error: you don't need to add `&` to all patterns - --> tests/ui/match_ref_pats.rs:8:9 + --> tests/ui/match_ref_pats.rs:14:9 | LL | / match v { LL | | @@ -19,7 +19,7 @@ LL ~ None => println!("none"), | error: you don't need to add `&` to both the expression and the patterns - --> tests/ui/match_ref_pats.rs:26:5 + --> tests/ui/match_ref_pats.rs:32:5 | LL | / match &w { LL | | @@ -37,7 +37,7 @@ LL ~ None => println!("none"), | error: redundant pattern matching, consider using `is_none()` - --> tests/ui/match_ref_pats.rs:39:12 + --> tests/ui/match_ref_pats.rs:45:12 | LL | if let &None = a { | -------^^^^^---- help: try: `if a.is_none()` @@ -46,13 +46,13 @@ LL | if let &None = a { = help: to override `-D warnings` add `#[allow(clippy::redundant_pattern_matching)]` error: redundant pattern matching, consider using `is_none()` - --> tests/ui/match_ref_pats.rs:45:12 + --> tests/ui/match_ref_pats.rs:51:12 | LL | if let &None = &b { | -------^^^^^----- help: try: `if b.is_none()` error: you don't need to add `&` to all patterns - --> tests/ui/match_ref_pats.rs:106:9 + --> tests/ui/match_ref_pats.rs:112:9 | LL | / match foobar_variant!(0) { LL | | diff --git a/tests/ui/match_single_binding.fixed b/tests/ui/match_single_binding.fixed index bdf39796ebf..e29fb87dbc3 100644 --- a/tests/ui/match_single_binding.fixed +++ b/tests/ui/match_single_binding.fixed @@ -188,3 +188,81 @@ fn issue14634() { let id!(_a) = dbg!(b + 1); //~^^^ match_single_binding } + +mod issue14991 { + struct AnnoConstWOBlock { + inner: [(); { + let _n = 1; + 42 + }], + } + + struct AnnoConstWBlock { + inner: [(); { + let _n = 1; + 42 + }], + } +} + +mod issue15018 { + fn used_later(a: i32, b: i32, c: i32) { + let x = 1; + { + let (x, y, z) = (a, b, c); + println!("{} {} {}", x, y, z); + } + println!("x = {x}"); + } + + fn not_used_later(a: i32, b: i32, c: i32) { + let (x, y, z) = (a, b, c); + println!("{} {} {}", x, y, z) + } + + #[allow(irrefutable_let_patterns)] + fn not_used_later_but_shadowed(a: i32, b: i32, c: i32) { + let (x, y, z) = (a, b, c); + println!("{} {} {}", x, y, z); + let x = 1; + println!("x = {x}"); + } + + #[allow(irrefutable_let_patterns)] + fn not_used_later_but_shadowed_nested(a: i32, b: i32, c: i32) { + let (x, y, z) = (a, b, c); + println!("{} {} {}", x, y, z); + if let (x, y, z) = (a, b, c) { + println!("{} {} {}", x, y, z) + } + + { + let x: i32 = 1; + { + let (x, y, z) = (a, b, c); + println!("{} {} {}", x, y, z); + } + if let (x, y, z) = (a, x, c) { + println!("{} {} {}", x, y, z) + } + } + + { + let (x, y, z) = (a, b, c); + println!("{} {} {}", x, y, z); + let fn_ = |y| { + println!("{} {} {}", a, b, y); + }; + fn_(c); + } + } +} + +#[allow(clippy::short_circuit_statement)] +fn issue15269(a: usize, b: usize, c: usize) -> bool { + a < b + && b < c; + + a < b + && b < c +} diff --git a/tests/ui/match_single_binding.rs b/tests/ui/match_single_binding.rs index 419ff95d873..ede1ab32beb 100644 --- a/tests/ui/match_single_binding.rs +++ b/tests/ui/match_single_binding.rs @@ -249,3 +249,97 @@ fn issue14634() { }; //~^^^ match_single_binding } + +mod issue14991 { + struct AnnoConstWOBlock { + inner: [(); match 1 { + //~^ match_single_binding + _n => 42, + }], + } + + struct AnnoConstWBlock { + inner: [(); { + match 1 { + //~^ match_single_binding + _n => 42, + } + }], + } +} + +mod issue15018 { + fn used_later(a: i32, b: i32, c: i32) { + let x = 1; + match (a, b, c) { + //~^ match_single_binding + (x, y, z) => println!("{} {} {}", x, y, z), + } + println!("x = {x}"); + } + + fn not_used_later(a: i32, b: i32, c: i32) { + match (a, b, c) { + //~^ match_single_binding + (x, y, z) => println!("{} {} {}", x, y, z), + } + } + + #[allow(irrefutable_let_patterns)] + fn not_used_later_but_shadowed(a: i32, b: i32, c: i32) { + match (a, b, c) { + //~^ match_single_binding + (x, y, z) => println!("{} {} {}", x, y, z), + } + let x = 1; + println!("x = {x}"); + } + + #[allow(irrefutable_let_patterns)] + fn not_used_later_but_shadowed_nested(a: i32, b: i32, c: i32) { + match (a, b, c) { + //~^ match_single_binding + (x, y, z) => println!("{} {} {}", x, y, z), + } + if let (x, y, z) = (a, b, c) { + println!("{} {} {}", x, y, z) + } + + { + let x: i32 = 1; + match (a, b, c) { + //~^ match_single_binding + (x, y, z) => println!("{} {} {}", x, y, z), + } + if let (x, y, z) = (a, x, c) { + println!("{} {} {}", x, y, z) + } + } + + { + match (a, b, c) { + //~^ match_single_binding + (x, y, z) => println!("{} {} {}", x, y, z), + } + let fn_ = |y| { + println!("{} {} {}", a, b, y); + }; + fn_(c); + } + } +} + +#[allow(clippy::short_circuit_statement)] +fn issue15269(a: usize, b: usize, c: usize) -> bool { + a < b + && match b { + //~^ match_single_binding + b => b < c, + }; + + a < b + && match (a, b) { + //~^ match_single_binding + (a, b) => b < c, + } +} diff --git a/tests/ui/match_single_binding.stderr b/tests/ui/match_single_binding.stderr index bdd0134a5f1..eea71777890 100644 --- a/tests/ui/match_single_binding.stderr +++ b/tests/ui/match_single_binding.stderr @@ -378,5 +378,152 @@ LL ~ let id!(b) = dbg!(3); LL + let id!(_a) = dbg!(b + 1); | -error: aborting due to 27 previous errors +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:255:21 + | +LL | inner: [(); match 1 { + | _____________________^ +LL | | +LL | | _n => 42, +LL | | }], + | |_________^ + | +help: consider using a `let` statement + | +LL ~ inner: [(); { +LL + let _n = 1; +LL + 42 +LL ~ }], + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:263:13 + | +LL | / match 1 { +LL | | +LL | | _n => 42, +LL | | } + | |_____________^ + | +help: consider using a `let` statement + | +LL ~ let _n = 1; +LL + 42 + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:274:9 + | +LL | / match (a, b, c) { +LL | | +LL | | (x, y, z) => println!("{} {} {}", x, y, z), +LL | | } + | |_________^ + | +help: consider using a `let` statement + | +LL ~ { +LL + let (x, y, z) = (a, b, c); +LL + println!("{} {} {}", x, y, z); +LL + } + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:282:9 + | +LL | / match (a, b, c) { +LL | | +LL | | (x, y, z) => println!("{} {} {}", x, y, z), +LL | | } + | |_________^ + | +help: consider using a `let` statement + | +LL ~ let (x, y, z) = (a, b, c); +LL + println!("{} {} {}", x, y, z) + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:290:9 + | +LL | / match (a, b, c) { +LL | | +LL | | (x, y, z) => println!("{} {} {}", x, y, z), +LL | | } + | |_________^ + | +help: consider using a `let` statement + | +LL ~ let (x, y, z) = (a, b, c); +LL + println!("{} {} {}", x, y, z); + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:300:9 + | +LL | / match (a, b, c) { +LL | | +LL | | (x, y, z) => println!("{} {} {}", x, y, z), +LL | | } + | |_________^ + | +help: consider using a `let` statement + | +LL ~ let (x, y, z) = (a, b, c); +LL + println!("{} {} {}", x, y, z); + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:310:13 + | +LL | / match (a, b, c) { +LL | | +LL | | (x, y, z) => println!("{} {} {}", x, y, z), +LL | | } + | |_____________^ + | +help: consider using a `let` statement + | +LL ~ { +LL + let (x, y, z) = (a, b, c); +LL + println!("{} {} {}", x, y, z); +LL + } + | + +error: this match could be written as a `let` statement + --> tests/ui/match_single_binding.rs:320:13 + | +LL | / match (a, b, c) { +LL | | +LL | | (x, y, z) => println!("{} {} {}", x, y, z), +LL | | } + | |_____________^ + | +help: consider using a `let` statement + | +LL ~ let (x, y, z) = (a, b, c); +LL + println!("{} {} {}", x, y, z); + | + +error: this match could be replaced by its body itself + --> tests/ui/match_single_binding.rs:335:12 + | +LL | && match b { + | ____________^ +LL | | +LL | | b => b < c, +LL | | }; + | |_________^ help: consider using the match body instead: `b < c` + +error: this match could be replaced by its body itself + --> tests/ui/match_single_binding.rs:341:12 + | +LL | && match (a, b) { + | ____________^ +LL | | +LL | | (a, b) => b < c, +LL | | } + | |_________^ help: consider using the match body instead: `b < c` + +error: aborting due to 37 previous errors diff --git a/tests/ui/match_str_case_mismatch.stderr b/tests/ui/match_str_case_mismatch.stderr index 8068edfff94..c2b58b952aa 100644 --- a/tests/ui/match_str_case_mismatch.stderr +++ b/tests/ui/match_str_case_mismatch.stderr @@ -18,7 +18,7 @@ error: this `match` arm has a differing case than its expression LL | "~!@#$%^&*()-_=+Foo" => {}, | ^^^^^^^^^^^^^^^^^^^^ | -help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization difference) +help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization) | LL - "~!@#$%^&*()-_=+Foo" => {}, LL + "~!@#$%^&*()-_=+foo" => {}, diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 2f4004181f6..f73fe288b0f 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -49,7 +49,7 @@ struct Lt2<'a> { impl<'a> Lt2<'a> { // The lifetime is different, but that’s irrelevant; see issue #734. - pub fn new(s: &str) -> Lt2 { + pub fn new(s: &str) -> Lt2<'_> { unimplemented!() } } diff --git a/tests/ui/min_ident_chars.rs b/tests/ui/min_ident_chars.rs index f473ac848a8..e2f82e2a182 100644 --- a/tests/ui/min_ident_chars.rs +++ b/tests/ui/min_ident_chars.rs @@ -124,3 +124,52 @@ fn wrong_pythagoras(a: f32, b: f32) -> f32 { mod issue_11163 { struct Array<T, const N: usize>([T; N]); } + +struct Issue13396; + +impl core::fmt::Display for Issue13396 { + fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + write!(f, "Issue13396") + } +} + +impl core::fmt::Debug for Issue13396 { + fn fmt(&self, g: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + //~^ min_ident_chars + write!(g, "Issue13396") + } +} + +fn issue13396() { + let a = |f: i8| f; + //~^ min_ident_chars + //~| min_ident_chars +} + +trait D { + //~^ min_ident_chars + fn f(g: i32); + //~^ min_ident_chars + //~| min_ident_chars + fn long(long: i32); + + fn g(arg: i8) { + //~^ min_ident_chars + fn c(d: u8) {} + //~^ min_ident_chars + //~| min_ident_chars + } +} + +impl D for Issue13396 { + fn f(g: i32) { + fn h() {} + //~^ min_ident_chars + fn inner(a: i32) {} + //~^ min_ident_chars + let a = |f: String| f; + //~^ min_ident_chars + //~| min_ident_chars + } + fn long(long: i32) {} +} diff --git a/tests/ui/min_ident_chars.stderr b/tests/ui/min_ident_chars.stderr index bd6c45cf648..36bf89e79f0 100644 --- a/tests/ui/min_ident_chars.stderr +++ b/tests/ui/min_ident_chars.stderr @@ -193,5 +193,83 @@ error: this ident consists of a single char LL | fn wrong_pythagoras(a: f32, b: f32) -> f32 { | ^ -error: aborting due to 32 previous errors +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:137:19 + | +LL | fn fmt(&self, g: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:144:14 + | +LL | let a = |f: i8| f; + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:144:9 + | +LL | let a = |f: i8| f; + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:149:7 + | +LL | trait D { + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:151:10 + | +LL | fn f(g: i32); + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:151:8 + | +LL | fn f(g: i32); + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:156:8 + | +LL | fn g(arg: i8) { + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:158:12 + | +LL | fn c(d: u8) {} + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:158:14 + | +LL | fn c(d: u8) {} + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:166:12 + | +LL | fn h() {} + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:168:18 + | +LL | fn inner(a: i32) {} + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:170:18 + | +LL | let a = |f: String| f; + | ^ + +error: this ident consists of a single char + --> tests/ui/min_ident_chars.rs:170:13 + | +LL | let a = |f: String| f; + | ^ + +error: aborting due to 45 previous errors diff --git a/tests/ui/missing_const_for_fn/const_trait.fixed b/tests/ui/missing_const_for_fn/const_trait.fixed index 7e0d4fccaae..c113c1caaa6 100644 --- a/tests/ui/missing_const_for_fn/const_trait.fixed +++ b/tests/ui/missing_const_for_fn/const_trait.fixed @@ -3,8 +3,7 @@ // Reduced test case from https://github.com/rust-lang/rust-clippy/issues/14658 -#[const_trait] -trait ConstTrait { +const trait ConstTrait { fn method(self); } @@ -25,7 +24,7 @@ const fn can_be_const() { 0u64.method(); } -// False negative, see FIXME comment in `clipy_utils::qualify_min_const` +// False negative, see FIXME comment in `clippy_utils::qualify_min_const_fn` fn could_be_const_but_does_not_trigger<T>(t: T) where T: const ConstTrait, diff --git a/tests/ui/missing_const_for_fn/const_trait.rs b/tests/ui/missing_const_for_fn/const_trait.rs index 439da4622d7..69248bc52d5 100644 --- a/tests/ui/missing_const_for_fn/const_trait.rs +++ b/tests/ui/missing_const_for_fn/const_trait.rs @@ -3,8 +3,7 @@ // Reduced test case from https://github.com/rust-lang/rust-clippy/issues/14658 -#[const_trait] -trait ConstTrait { +const trait ConstTrait { fn method(self); } @@ -25,7 +24,7 @@ fn can_be_const() { 0u64.method(); } -// False negative, see FIXME comment in `clipy_utils::qualify_min_const` +// False negative, see FIXME comment in `clippy_utils::qualify_min_const_fn` fn could_be_const_but_does_not_trigger<T>(t: T) where T: const ConstTrait, diff --git a/tests/ui/missing_const_for_fn/const_trait.stderr b/tests/ui/missing_const_for_fn/const_trait.stderr index b994b88fac6..7ea009cfc9b 100644 --- a/tests/ui/missing_const_for_fn/const_trait.stderr +++ b/tests/ui/missing_const_for_fn/const_trait.stderr @@ -1,5 +1,5 @@ error: this could be a `const fn` - --> tests/ui/missing_const_for_fn/const_trait.rs:24:1 + --> tests/ui/missing_const_for_fn/const_trait.rs:23:1 | LL | / fn can_be_const() { LL | | 0u64.method(); diff --git a/tests/ui/missing_const_for_fn/could_be_const.fixed b/tests/ui/missing_const_for_fn/could_be_const.fixed index 65eb2d5938b..95bf63ed1df 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.fixed +++ b/tests/ui/missing_const_for_fn/could_be_const.fixed @@ -221,3 +221,60 @@ const fn mut_add(x: &mut i32) { //~^ missing_const_for_fn *x += 1; } + +mod issue_15079 { + pub trait Trait {} + + pub struct Struct<T: Trait> { + _t: Option<T>, + } + + impl<T: Trait> Struct<T> { + #[clippy::msrv = "1.60"] + pub fn new_1_60() -> Self { + Self { _t: None } + } + + #[clippy::msrv = "1.61"] + pub const fn new_1_61() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + } + + pub struct S2<T> { + _t: Option<T>, + } + + impl<T> S2<T> { + #[clippy::msrv = "1.60"] + pub const fn new_1_60() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + + #[clippy::msrv = "1.61"] + pub const fn new_1_61() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + } + + pub struct S3<T: ?Sized + 'static> { + _t: Option<&'static T>, + } + + impl<T: ?Sized + 'static> S3<T> { + #[clippy::msrv = "1.60"] + pub const fn new_1_60() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + + #[clippy::msrv = "1.61"] + pub const fn new_1_61() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.rs b/tests/ui/missing_const_for_fn/could_be_const.rs index 3690d2f799f..8290be67546 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.rs +++ b/tests/ui/missing_const_for_fn/could_be_const.rs @@ -221,3 +221,60 @@ fn mut_add(x: &mut i32) { //~^ missing_const_for_fn *x += 1; } + +mod issue_15079 { + pub trait Trait {} + + pub struct Struct<T: Trait> { + _t: Option<T>, + } + + impl<T: Trait> Struct<T> { + #[clippy::msrv = "1.60"] + pub fn new_1_60() -> Self { + Self { _t: None } + } + + #[clippy::msrv = "1.61"] + pub fn new_1_61() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + } + + pub struct S2<T> { + _t: Option<T>, + } + + impl<T> S2<T> { + #[clippy::msrv = "1.60"] + pub fn new_1_60() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + + #[clippy::msrv = "1.61"] + pub fn new_1_61() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + } + + pub struct S3<T: ?Sized + 'static> { + _t: Option<&'static T>, + } + + impl<T: ?Sized + 'static> S3<T> { + #[clippy::msrv = "1.60"] + pub fn new_1_60() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + + #[clippy::msrv = "1.61"] + pub fn new_1_61() -> Self { + //~^ missing_const_for_fn + Self { _t: None } + } + } +} diff --git a/tests/ui/missing_const_for_fn/could_be_const.stderr b/tests/ui/missing_const_for_fn/could_be_const.stderr index 10e07d12f5a..17cbc431276 100644 --- a/tests/ui/missing_const_for_fn/could_be_const.stderr +++ b/tests/ui/missing_const_for_fn/could_be_const.stderr @@ -332,5 +332,75 @@ help: make the function `const` LL | const fn mut_add(x: &mut i32) { | +++++ -error: aborting due to 25 previous errors +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:239:9 + | +LL | / pub fn new_1_61() -> Self { +LL | | +LL | | Self { _t: None } +LL | | } + | |_________^ + | +help: make the function `const` + | +LL | pub const fn new_1_61() -> Self { + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:251:9 + | +LL | / pub fn new_1_60() -> Self { +LL | | +LL | | Self { _t: None } +LL | | } + | |_________^ + | +help: make the function `const` + | +LL | pub const fn new_1_60() -> Self { + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:257:9 + | +LL | / pub fn new_1_61() -> Self { +LL | | +LL | | Self { _t: None } +LL | | } + | |_________^ + | +help: make the function `const` + | +LL | pub const fn new_1_61() -> Self { + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:269:9 + | +LL | / pub fn new_1_60() -> Self { +LL | | +LL | | Self { _t: None } +LL | | } + | |_________^ + | +help: make the function `const` + | +LL | pub const fn new_1_60() -> Self { + | +++++ + +error: this could be a `const fn` + --> tests/ui/missing_const_for_fn/could_be_const.rs:275:9 + | +LL | / pub fn new_1_61() -> Self { +LL | | +LL | | Self { _t: None } +LL | | } + | |_________^ + | +help: make the function `const` + | +LL | pub const fn new_1_61() -> Self { + | +++++ + +error: aborting due to 30 previous errors diff --git a/tests/ui/missing_inline.rs b/tests/ui/missing_inline.rs index c1801005b77..8e937d60951 100644 --- a/tests/ui/missing_inline.rs +++ b/tests/ui/missing_inline.rs @@ -80,3 +80,27 @@ impl PubFoo { // do not lint this since users cannot control the external code #[derive(Debug)] pub struct S; + +pub mod issue15301 { + #[unsafe(no_mangle)] + pub extern "C" fn call_from_c() { + println!("Just called a Rust function from C!"); + } + + #[unsafe(no_mangle)] + pub extern "Rust" fn call_from_rust() { + println!("Just called a Rust function from Rust!"); + } + + #[unsafe(no_mangle)] + pub fn call_from_rust_no_extern() { + println!("Just called a Rust function from Rust!"); + } +} + +pub mod issue15491 { + pub trait Foo { + #[allow(clippy::missing_inline_in_public_items)] + fn foo(&self) {} + } +} diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index ffdae8504f7..d016e099e30 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -250,3 +250,31 @@ pub fn issue_12760<const N: usize>() { } } } + +/// This needs documenting +pub fn unwrap_expect_etc_in_const() { + let a = const { std::num::NonZeroUsize::new(1).unwrap() }; + // This should still pass the lint even if it is guaranteed to panic at compile-time + let b = const { std::num::NonZeroUsize::new(0).unwrap() }; +} + +/// This needs documenting +pub const fn unwrap_expect_etc_in_const_fn_fails() { + //~^ missing_panics_doc + let a = std::num::NonZeroUsize::new(1).unwrap(); +} + +/// This needs documenting +pub const fn assert_in_const_fn_fails() { + //~^ missing_panics_doc + let x = 0; + if x == 0 { + panic!(); + } +} + +/// This needs documenting +pub const fn in_const_fn<const N: usize>(n: usize) { + //~^ missing_panics_doc + assert!(N > n); +} diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 7f0acf8de9b..85a00914427 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -180,5 +180,41 @@ note: first possible panic found here LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 15 previous errors +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:262:1 + | +LL | pub const fn unwrap_expect_etc_in_const_fn_fails() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:264:13 + | +LL | let a = std::num::NonZeroUsize::new(1).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:268:1 + | +LL | pub const fn assert_in_const_fn_fails() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:272:9 + | +LL | panic!(); + | ^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:277:1 + | +LL | pub const fn in_const_fn<const N: usize>(n: usize) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:279:5 + | +LL | assert!(N > n); + | ^^^^^^^^^^^^^^ + +error: aborting due to 18 previous errors diff --git a/tests/ui/module_name_repetitions.rs b/tests/ui/module_name_repetitions.rs index 2fde98d7927..5d16858bf85 100644 --- a/tests/ui/module_name_repetitions.rs +++ b/tests/ui/module_name_repetitions.rs @@ -55,3 +55,21 @@ pub mod foo { } fn main() {} + +pub mod issue14095 { + pub mod widget { + #[macro_export] + macro_rules! define_widget { + ($id:ident) => { + /* ... */ + }; + } + + #[macro_export] + macro_rules! widget_impl { + ($id:ident) => { + /* ... */ + }; + } + } +} diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index 4c1d6b1ccb5..1e8589cf39d 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -13,13 +13,15 @@ use std::sync::atomic::{AtomicBool, Ordering}; pub struct MyAtomic(AtomicBool); pub struct MyPure; -#[must_use] pub fn pure(i: u8) -> u8 { +#[must_use] +pub fn pure(i: u8) -> u8 { //~^ must_use_candidate i } impl MyPure { - #[must_use] pub fn inherent_pure(&self) -> u8 { + #[must_use] + pub fn inherent_pure(&self) -> u8 { //~^ must_use_candidate 0 } @@ -51,7 +53,8 @@ pub fn with_callback<F: Fn(u32) -> bool>(f: &F) -> bool { f(0) } -#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { +#[must_use] +pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { //~^ must_use_candidate true } @@ -64,7 +67,8 @@ pub fn atomics(b: &AtomicBool) -> bool { b.load(Ordering::SeqCst) } -#[must_use] pub fn rcd(_x: Rc<u32>) -> bool { +#[must_use] +pub fn rcd(_x: Rc<u32>) -> bool { //~^ must_use_candidate true } @@ -73,7 +77,8 @@ pub fn rcmut(_x: Rc<&mut u32>) -> bool { true } -#[must_use] pub fn arcd(_x: Arc<u32>) -> bool { +#[must_use] +pub fn arcd(_x: Arc<u32>) -> bool { //~^ must_use_candidate false } diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index 590253d95f9..5ddbd026062 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -1,35 +1,64 @@ error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:16:1 + --> tests/ui/must_use_candidates.rs:16:8 | LL | pub fn pure(i: u8) -> u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8` + | ^^^^ | = note: `-D clippy::must-use-candidate` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::must_use_candidate)]` +help: add the attribute + | +LL + #[must_use] +LL | pub fn pure(i: u8) -> u8 { + | error: this method could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:22:5 + --> tests/ui/must_use_candidates.rs:22:12 | LL | pub fn inherent_pure(&self) -> u8 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8` + | ^^^^^^^^^^^^^ + | +help: add the attribute + | +LL ~ #[must_use] +LL ~ pub fn inherent_pure(&self) -> u8 { + | error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:54:1 + --> tests/ui/must_use_candidates.rs:54:8 + | +LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { + | ^^^^^^^^^^^ + | +help: add the attribute | +LL + #[must_use] LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool` + | error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:67:1 + --> tests/ui/must_use_candidates.rs:67:8 | LL | pub fn rcd(_x: Rc<u32>) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc<u32>) -> bool` + | ^^^ + | +help: add the attribute + | +LL + #[must_use] +LL | pub fn rcd(_x: Rc<u32>) -> bool { + | error: this function could have a `#[must_use]` attribute - --> tests/ui/must_use_candidates.rs:76:1 + --> tests/ui/must_use_candidates.rs:76:8 | LL | pub fn arcd(_x: Arc<u32>) -> bool { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc<u32>) -> bool` + | ^^^^ + | +help: add the attribute + | +LL + #[must_use] +LL | pub fn arcd(_x: Arc<u32>) -> bool { + | error: aborting due to 5 previous errors diff --git a/tests/ui/needless_bool/fixable.stderr b/tests/ui/needless_bool/fixable.stderr index 3f117ee5a50..9404d07ba0e 100644 --- a/tests/ui/needless_bool/fixable.stderr +++ b/tests/ui/needless_bool/fixable.stderr @@ -135,7 +135,7 @@ error: equality checks against true are unnecessary --> tests/ui/needless_bool/fixable.rs:157:8 | LL | if x == true {}; - | ^^^^^^^^^ help: try simplifying it as shown: `x` + | ^^^^^^^^^ help: try: `x` | = note: `-D clippy::bool-comparison` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` @@ -144,19 +144,19 @@ error: equality checks against false can be replaced by a negation --> tests/ui/needless_bool/fixable.rs:162:8 | LL | if x == false {}; - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` + | ^^^^^^^^^^ help: try: `!x` error: equality checks against true are unnecessary --> tests/ui/needless_bool/fixable.rs:173:8 | LL | if x == true {}; - | ^^^^^^^^^ help: try simplifying it as shown: `x` + | ^^^^^^^^^ help: try: `x` error: equality checks against false can be replaced by a negation --> tests/ui/needless_bool/fixable.rs:175:8 | LL | if x == false {}; - | ^^^^^^^^^^ help: try simplifying it as shown: `!x` + | ^^^^^^^^^^ help: try: `!x` error: this if-then-else expression returns a bool literal --> tests/ui/needless_bool/fixable.rs:185:12 diff --git a/tests/ui/needless_bool_assign.fixed b/tests/ui/needless_bool_assign.fixed index e0c717ecda2..d6fab4c51b5 100644 --- a/tests/ui/needless_bool_assign.fixed +++ b/tests/ui/needless_bool_assign.fixed @@ -33,3 +33,12 @@ fn main() { b = true; } } + +fn issue15063(x: bool, y: bool) { + let mut z = false; + + if x && y { + todo!() + } else { z = x || y; } + //~^^^^^ needless_bool_assign +} diff --git a/tests/ui/needless_bool_assign.rs b/tests/ui/needless_bool_assign.rs index 3e4fecefa78..c504f61f4dd 100644 --- a/tests/ui/needless_bool_assign.rs +++ b/tests/ui/needless_bool_assign.rs @@ -45,3 +45,16 @@ fn main() { b = true; } } + +fn issue15063(x: bool, y: bool) { + let mut z = false; + + if x && y { + todo!() + } else if x || y { + z = true; + } else { + z = false; + } + //~^^^^^ needless_bool_assign +} diff --git a/tests/ui/needless_bool_assign.stderr b/tests/ui/needless_bool_assign.stderr index f33a4bc0c59..1d09b8b25a0 100644 --- a/tests/ui/needless_bool_assign.stderr +++ b/tests/ui/needless_bool_assign.stderr @@ -51,5 +51,16 @@ LL | | } = note: `-D clippy::if-same-then-else` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::if_same_then_else)]` -error: aborting due to 4 previous errors +error: this if-then-else expression assigns a bool literal + --> tests/ui/needless_bool_assign.rs:54:12 + | +LL | } else if x || y { + | ____________^ +LL | | z = true; +LL | | } else { +LL | | z = false; +LL | | } + | |_____^ help: you can reduce it to: `{ z = x || y; }` + +error: aborting due to 5 previous errors diff --git a/tests/ui/needless_collect_indirect.rs b/tests/ui/needless_collect_indirect.rs index 57d0f2b9948..fff6d2f34b8 100644 --- a/tests/ui/needless_collect_indirect.rs +++ b/tests/ui/needless_collect_indirect.rs @@ -1,5 +1,4 @@ -#![allow(clippy::uninlined_format_args, clippy::useless_vec)] -#![allow(clippy::needless_if, clippy::uninlined_format_args)] +#![allow(clippy::uninlined_format_args, clippy::useless_vec, clippy::needless_if)] #![warn(clippy::needless_collect)] //@no-rustfix use std::collections::{BinaryHeap, HashMap, HashSet, LinkedList, VecDeque}; diff --git a/tests/ui/needless_collect_indirect.stderr b/tests/ui/needless_collect_indirect.stderr index c7bf1b14df8..24523c9f97b 100644 --- a/tests/ui/needless_collect_indirect.stderr +++ b/tests/ui/needless_collect_indirect.stderr @@ -1,5 +1,5 @@ error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:9:39 + --> tests/ui/needless_collect_indirect.rs:8:39 | LL | let indirect_iter = sample.iter().collect::<Vec<_>>(); | ^^^^^^^ @@ -18,7 +18,7 @@ LL ~ sample.iter().map(|x| (x, x + 1)).collect::<HashMap<_, _>>(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:13:38 + --> tests/ui/needless_collect_indirect.rs:12:38 | LL | let indirect_len = sample.iter().collect::<VecDeque<_>>(); | ^^^^^^^ @@ -35,7 +35,7 @@ LL ~ sample.iter().count(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:17:40 + --> tests/ui/needless_collect_indirect.rs:16:40 | LL | let indirect_empty = sample.iter().collect::<VecDeque<_>>(); | ^^^^^^^ @@ -52,7 +52,7 @@ LL ~ sample.iter().next().is_none(); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:21:43 + --> tests/ui/needless_collect_indirect.rs:20:43 | LL | let indirect_contains = sample.iter().collect::<VecDeque<_>>(); | ^^^^^^^ @@ -69,7 +69,7 @@ LL ~ sample.iter().any(|x| x == &5); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:35:48 + --> tests/ui/needless_collect_indirect.rs:34:48 | LL | let non_copy_contains = sample.into_iter().collect::<Vec<_>>(); | ^^^^^^^ @@ -86,7 +86,7 @@ LL ~ sample.into_iter().any(|x| x == a); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:66:51 + --> tests/ui/needless_collect_indirect.rs:65:51 | LL | let buffer: Vec<&str> = string.split('/').collect(); | ^^^^^^^ @@ -103,7 +103,7 @@ LL ~ string.split('/').count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:73:55 + --> tests/ui/needless_collect_indirect.rs:72:55 | LL | let indirect_len: VecDeque<_> = sample.iter().collect(); | ^^^^^^^ @@ -120,7 +120,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:80:57 + --> tests/ui/needless_collect_indirect.rs:79:57 | LL | let indirect_len: LinkedList<_> = sample.iter().collect(); | ^^^^^^^ @@ -137,7 +137,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:87:57 + --> tests/ui/needless_collect_indirect.rs:86:57 | LL | let indirect_len: BinaryHeap<_> = sample.iter().collect(); | ^^^^^^^ @@ -154,7 +154,7 @@ LL ~ sample.iter().count() | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:149:59 + --> tests/ui/needless_collect_indirect.rs:148:59 | LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -172,7 +172,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == i); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:176:59 + --> tests/ui/needless_collect_indirect.rs:175:59 | LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -190,7 +190,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:207:63 + --> tests/ui/needless_collect_indirect.rs:206:63 | LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -208,7 +208,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:245:59 + --> tests/ui/needless_collect_indirect.rs:244:59 | LL | let y: Vec<usize> = vec.iter().map(|k| k * k).collect(); | ^^^^^^^ @@ -226,7 +226,7 @@ LL ~ vec.iter().map(|k| k * k).any(|x| x == n); | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:272:26 + --> tests/ui/needless_collect_indirect.rs:271:26 | LL | let w = v.iter().collect::<Vec<_>>(); | ^^^^^^^ @@ -244,7 +244,7 @@ LL ~ for _ in 0..v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:296:30 + --> tests/ui/needless_collect_indirect.rs:295:30 | LL | let mut w = v.iter().collect::<Vec<_>>(); | ^^^^^^^ @@ -262,7 +262,7 @@ LL ~ while 1 == v.iter().count() { | error: avoid using `collect()` when not needed - --> tests/ui/needless_collect_indirect.rs:320:30 + --> tests/ui/needless_collect_indirect.rs:319:30 | LL | let mut w = v.iter().collect::<Vec<_>>(); | ^^^^^^^ diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed index a73aff55639..a6d64d9afc1 100644 --- a/tests/ui/needless_for_each_fixable.fixed +++ b/tests/ui/needless_for_each_fixable.fixed @@ -143,3 +143,9 @@ mod issue14734 { //~^ needless_for_each } } + +fn issue15256() { + let vec: Vec<i32> = Vec::new(); + for v in vec.iter() { println!("{v}"); } + //~^ needless_for_each +} diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs index d92f055d3f4..7e74d2b428f 100644 --- a/tests/ui/needless_for_each_fixable.rs +++ b/tests/ui/needless_for_each_fixable.rs @@ -143,3 +143,9 @@ mod issue14734 { //~^ needless_for_each } } + +fn issue15256() { + let vec: Vec<i32> = Vec::new(); + vec.iter().for_each(|v| println!("{v}")); + //~^ needless_for_each +} diff --git a/tests/ui/needless_for_each_fixable.stderr b/tests/ui/needless_for_each_fixable.stderr index f8014456097..204cfa36b02 100644 --- a/tests/ui/needless_for_each_fixable.stderr +++ b/tests/ui/needless_for_each_fixable.stderr @@ -148,5 +148,11 @@ error: needless use of `for_each` LL | rows.iter().for_each(|x| do_something(x, 1u8)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { do_something(x, 1u8); }` -error: aborting due to 10 previous errors +error: needless use of `for_each` + --> tests/ui/needless_for_each_fixable.rs:149:5 + | +LL | vec.iter().for_each(|v| println!("{v}")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for v in vec.iter() { println!("{v}"); }` + +error: aborting due to 11 previous errors diff --git a/tests/ui/needless_lifetimes.fixed b/tests/ui/needless_lifetimes.fixed index e9d811986aa..15ca409c95b 100644 --- a/tests/ui/needless_lifetimes.fixed +++ b/tests/ui/needless_lifetimes.fixed @@ -10,7 +10,7 @@ clippy::unnecessary_wraps, dyn_drop, clippy::get_first, - elided_named_lifetimes + mismatched_lifetime_syntaxes )] extern crate proc_macros; diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index 0b6eb9755b9..af9649d7298 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -10,7 +10,7 @@ clippy::unnecessary_wraps, dyn_drop, clippy::get_first, - elided_named_lifetimes + mismatched_lifetime_syntaxes )] extern crate proc_macros; diff --git a/tests/ui/needless_range_loop.rs b/tests/ui/needless_range_loop.rs index 8a1c1be289c..70cf9fa7369 100644 --- a/tests/ui/needless_range_loop.rs +++ b/tests/ui/needless_range_loop.rs @@ -185,3 +185,28 @@ mod issue_2496 { unimplemented!() } } + +fn needless_loop() { + use std::hint::black_box; + let x = [0; 64]; + for i in 0..64 { + let y = [0; 64]; + + black_box(x[i]); + black_box(y[i]); + } + + for i in 0..64 { + black_box(x[i]); + black_box([0; 64][i]); + } + + for i in 0..64 { + black_box(x[i]); + black_box([1, 2, 3, 4, 5, 6, 7, 8][i]); + } + + for i in 0..64 { + black_box([1, 2, 3, 4, 5, 6, 7, 8][i]); + } +} diff --git a/tests/ui/neg_multiply.fixed b/tests/ui/neg_multiply.fixed index ff6e08300e2..32d466e88fc 100644 --- a/tests/ui/neg_multiply.fixed +++ b/tests/ui/neg_multiply.fixed @@ -82,3 +82,15 @@ fn float() { -1.0 * -1.0; // should be ok } + +struct Y { + delta: f64, +} + +fn nested() { + let a = Y { delta: 1.0 }; + let b = Y { delta: 1.0 }; + let _ = (-(a.delta - 0.5).abs()).total_cmp(&1.0); + //~^ neg_multiply + let _ = (-(a.delta - 0.5).abs()).total_cmp(&1.0); +} diff --git a/tests/ui/neg_multiply.rs b/tests/ui/neg_multiply.rs index b0f4e85c78e..241a72c6d99 100644 --- a/tests/ui/neg_multiply.rs +++ b/tests/ui/neg_multiply.rs @@ -82,3 +82,15 @@ fn float() { -1.0 * -1.0; // should be ok } + +struct Y { + delta: f64, +} + +fn nested() { + let a = Y { delta: 1.0 }; + let b = Y { delta: 1.0 }; + let _ = ((a.delta - 0.5).abs() * -1.0).total_cmp(&1.0); + //~^ neg_multiply + let _ = (-(a.delta - 0.5).abs()).total_cmp(&1.0); +} diff --git a/tests/ui/neg_multiply.stderr b/tests/ui/neg_multiply.stderr index 2ef7e32ce05..f4fb6d3ce54 100644 --- a/tests/ui/neg_multiply.stderr +++ b/tests/ui/neg_multiply.stderr @@ -97,5 +97,11 @@ error: this multiplication by -1 can be written more succinctly LL | (3.0_f32 as f64) * -1.0; | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `-(3.0_f32 as f64)` -error: aborting due to 16 previous errors +error: this multiplication by -1 can be written more succinctly + --> tests/ui/neg_multiply.rs:93:13 + | +LL | let _ = ((a.delta - 0.5).abs() * -1.0).total_cmp(&1.0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(-(a.delta - 0.5).abs())` + +error: aborting due to 17 previous errors diff --git a/tests/ui/never_loop.rs b/tests/ui/never_loop.rs index e0f54ef899b..48d4b8ad151 100644 --- a/tests/ui/never_loop.rs +++ b/tests/ui/never_loop.rs @@ -466,3 +466,35 @@ fn main() { test13(); test14(); } + +fn issue15059() { + 'a: for _ in 0..1 { + //~^ never_loop + break 'a; + } + + let mut b = 1; + 'a: for i in 0..1 { + //~^ never_loop + match i { + 0 => { + b *= 2; + break 'a; + }, + x => { + b += x; + break 'a; + }, + } + } + + #[allow(clippy::unused_unit)] + for v in 0..10 { + //~^ never_loop + break; + println!("{v}"); + // This is comment and should be kept + println!("This is a comment"); + () + } +} diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index bc9a7ec48b4..54b463266a3 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -176,8 +176,10 @@ LL | | } | help: if you need the first element of the iterator, try writing | -LL - for v in 0..10 { -LL + if let Some(v) = (0..10).next() { +LL ~ if let Some(v) = (0..10).next() { +LL | +LL ~ +LL ~ | error: this loop never actually loops @@ -232,5 +234,68 @@ LL | | break 'inner; LL | | } | |_________^ -error: aborting due to 21 previous errors +error: this loop never actually loops + --> tests/ui/never_loop.rs:471:5 + | +LL | / 'a: for _ in 0..1 { +LL | | +LL | | break 'a; +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL ~ if let Some(_) = (0..1).next() { +LL | +LL ~ + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:477:5 + | +LL | / 'a: for i in 0..1 { +LL | | +LL | | match i { +LL | | 0 => { +... | +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL ~ if let Some(i) = (0..1).next() { +LL | +... +LL | b *= 2; +LL ~ +LL | }, +LL | x => { +LL | b += x; +LL ~ + | + +error: this loop never actually loops + --> tests/ui/never_loop.rs:492:5 + | +LL | / for v in 0..10 { +LL | | +LL | | break; +LL | | println!("{v}"); +... | +LL | | () +LL | | } + | |_____^ + | +help: if you need the first element of the iterator, try writing + | +LL ~ if let Some(v) = (0..10).next() { +LL | +LL ~ +LL ~ +LL | // This is comment and should be kept +LL ~ +LL ~ + | + +error: aborting due to 24 previous errors diff --git a/tests/ui/nonminimal_bool.rs b/tests/ui/nonminimal_bool.rs index 1eecc3dee3d..f03f74dfafe 100644 --- a/tests/ui/nonminimal_bool.rs +++ b/tests/ui/nonminimal_bool.rs @@ -182,14 +182,12 @@ fn issue_5794() { if !b == true {} //~^ nonminimal_bool //~| bool_comparison - //~| bool_comparison if !b != true {} //~^ nonminimal_bool //~| bool_comparison if true == !b {} //~^ nonminimal_bool //~| bool_comparison - //~| bool_comparison if true != !b {} //~^ nonminimal_bool //~| bool_comparison @@ -236,3 +234,21 @@ mod issue14404 { } } } + +fn dont_simplify_double_not_if_types_differ() { + struct S; + + impl std::ops::Not for S { + type Output = bool; + fn not(self) -> bool { + true + } + } + + // The lint must propose `if !!S`, not `if S`. + // FIXME: `bool_comparison` will propose to use `S == true` + // which is invalid. + if !S != true {} + //~^ nonminimal_bool + //~| bool_comparison +} diff --git a/tests/ui/nonminimal_bool.stderr b/tests/ui/nonminimal_bool.stderr index 0e3e4cf7988..6a20b9216da 100644 --- a/tests/ui/nonminimal_bool.stderr +++ b/tests/ui/nonminimal_bool.stderr @@ -154,86 +154,86 @@ error: this boolean expression can be simplified LL | if !b == true {} | ^^^^^^^^^^ help: try: `b != true` -error: this comparison might be written more concisely +error: equality checks against true are unnecessary --> tests/ui/nonminimal_bool.rs:182:8 | LL | if !b == true {} - | ^^^^^^^^^^ help: try simplifying it as shown: `b != true` + | ^^^^^^^^^^ help: try: `!b` | = note: `-D clippy::bool-comparison` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::bool_comparison)]` -error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:182:8 - | -LL | if !b == true {} - | ^^^^^^^^^^ help: try simplifying it as shown: `!b` - error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:186:8 + --> tests/ui/nonminimal_bool.rs:185:8 | LL | if !b != true {} | ^^^^^^^^^^ help: try: `b == true` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:186:8 + --> tests/ui/nonminimal_bool.rs:185:8 | LL | if !b != true {} - | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` + | ^^^^^^^^^^ help: try: `b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:189:8 + --> tests/ui/nonminimal_bool.rs:188:8 | LL | if true == !b {} | ^^^^^^^^^^ help: try: `true != b` -error: this comparison might be written more concisely - --> tests/ui/nonminimal_bool.rs:189:8 - | -LL | if true == !b {} - | ^^^^^^^^^^ help: try simplifying it as shown: `true != b` - error: equality checks against true are unnecessary - --> tests/ui/nonminimal_bool.rs:189:8 + --> tests/ui/nonminimal_bool.rs:188:8 | LL | if true == !b {} - | ^^^^^^^^^^ help: try simplifying it as shown: `!b` + | ^^^^^^^^^^ help: try: `!b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:193:8 + --> tests/ui/nonminimal_bool.rs:191:8 | LL | if true != !b {} | ^^^^^^^^^^ help: try: `true == b` error: inequality checks against true can be replaced by a negation - --> tests/ui/nonminimal_bool.rs:193:8 + --> tests/ui/nonminimal_bool.rs:191:8 | LL | if true != !b {} - | ^^^^^^^^^^ help: try simplifying it as shown: `!(!b)` + | ^^^^^^^^^^ help: try: `b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:196:8 + --> tests/ui/nonminimal_bool.rs:194:8 | LL | if !b == !c {} | ^^^^^^^^ help: try: `b == c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:198:8 + --> tests/ui/nonminimal_bool.rs:196:8 | LL | if !b != !c {} | ^^^^^^^^ help: try: `b != c` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:214:8 + --> tests/ui/nonminimal_bool.rs:212:8 | LL | if !(a < 2.0 && !b) { | ^^^^^^^^^^^^^^^^ help: try: `a >= 2.0 || b` error: this boolean expression can be simplified - --> tests/ui/nonminimal_bool.rs:233:12 + --> tests/ui/nonminimal_bool.rs:231:12 | LL | if !(matches!(ty, TyKind::Ref(_, _, _)) && !is_mutable(&expr)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `!matches!(ty, TyKind::Ref(_, _, _)) || is_mutable(&expr)` +error: this boolean expression can be simplified + --> tests/ui/nonminimal_bool.rs:251:8 + | +LL | if !S != true {} + | ^^^^^^^^^^ help: try: `S == true` + +error: inequality checks against true can be replaced by a negation + --> tests/ui/nonminimal_bool.rs:251:8 + | +LL | if !S != true {} + | ^^^^^^^^^^ help: try: `!!S` + error: aborting due to 31 previous errors diff --git a/tests/ui/op_ref.fixed b/tests/ui/op_ref.fixed index f412190b9fd..4bf4b91888c 100644 --- a/tests/ui/op_ref.fixed +++ b/tests/ui/op_ref.fixed @@ -110,3 +110,37 @@ mod issue_2597 { &array[idx] < val } } + +#[allow(clippy::needless_if)] +fn issue15063() { + use std::ops::BitAnd; + + macro_rules! mac { + ($e:expr) => { + $e.clone() + }; + } + + let x = 1; + if x == mac!(1) {} + //~^ op_ref + + #[derive(Copy, Clone)] + struct Y(i32); + impl BitAnd for Y { + type Output = Y; + fn bitand(self, rhs: Y) -> Y { + Y(self.0 & rhs.0) + } + } + impl<'a> BitAnd<&'a Y> for Y { + type Output = Y; + fn bitand(self, rhs: &'a Y) -> Y { + Y(self.0 & rhs.0) + } + } + let x = Y(1); + let y = Y(2); + let z = x & mac!(y); + //~^ op_ref +} diff --git a/tests/ui/op_ref.rs b/tests/ui/op_ref.rs index a4bbd86c7e9..9a192661aaf 100644 --- a/tests/ui/op_ref.rs +++ b/tests/ui/op_ref.rs @@ -110,3 +110,37 @@ mod issue_2597 { &array[idx] < val } } + +#[allow(clippy::needless_if)] +fn issue15063() { + use std::ops::BitAnd; + + macro_rules! mac { + ($e:expr) => { + $e.clone() + }; + } + + let x = 1; + if &x == &mac!(1) {} + //~^ op_ref + + #[derive(Copy, Clone)] + struct Y(i32); + impl BitAnd for Y { + type Output = Y; + fn bitand(self, rhs: Y) -> Y { + Y(self.0 & rhs.0) + } + } + impl<'a> BitAnd<&'a Y> for Y { + type Output = Y; + fn bitand(self, rhs: &'a Y) -> Y { + Y(self.0 & rhs.0) + } + } + let x = Y(1); + let y = Y(2); + let z = x & &mac!(y); + //~^ op_ref +} diff --git a/tests/ui/op_ref.stderr b/tests/ui/op_ref.stderr index 51c2963a9ee..8a58b154c81 100644 --- a/tests/ui/op_ref.stderr +++ b/tests/ui/op_ref.stderr @@ -36,5 +36,25 @@ LL | let _ = two + &three; | | | help: use the right value directly: `three` -error: aborting due to 4 previous errors +error: needlessly taken reference of both operands + --> tests/ui/op_ref.rs:125:8 + | +LL | if &x == &mac!(1) {} + | ^^^^^^^^^^^^^^ + | +help: use the values directly + | +LL - if &x == &mac!(1) {} +LL + if x == mac!(1) {} + | + +error: taken reference of right operand + --> tests/ui/op_ref.rs:144:13 + | +LL | let z = x & &mac!(y); + | ^^^^-------- + | | + | help: use the right value directly: `mac!(y)` + +error: aborting due to 6 previous errors diff --git a/tests/ui/option_if_let_else.fixed b/tests/ui/option_if_let_else.fixed index fe3ac9e8f92..0f86de5646c 100644 --- a/tests/ui/option_if_let_else.fixed +++ b/tests/ui/option_if_let_else.fixed @@ -302,3 +302,15 @@ mod issue11059 { if let Some(o) = o { o } else { &S } } } + +fn issue15379() { + let opt = Some(0usize); + let opt_raw_ptr = &opt as *const Option<usize>; + let _ = unsafe { (*opt_raw_ptr).map_or(1, |o| o) }; + //~^ option_if_let_else +} + +fn issue15002() { + let res: Result<String, ()> = Ok("_".to_string()); + let _ = res.map_or_else(|_| String::new(), |s| s.clone()); +} diff --git a/tests/ui/option_if_let_else.rs b/tests/ui/option_if_let_else.rs index 5b7498bc8e2..7aabd778f87 100644 --- a/tests/ui/option_if_let_else.rs +++ b/tests/ui/option_if_let_else.rs @@ -365,3 +365,19 @@ mod issue11059 { if let Some(o) = o { o } else { &S } } } + +fn issue15379() { + let opt = Some(0usize); + let opt_raw_ptr = &opt as *const Option<usize>; + let _ = unsafe { if let Some(o) = *opt_raw_ptr { o } else { 1 } }; + //~^ option_if_let_else +} + +fn issue15002() { + let res: Result<String, ()> = Ok("_".to_string()); + let _ = match res { + //~^ option_if_let_else + Ok(s) => s.clone(), + Err(_) => String::new(), + }; +} diff --git a/tests/ui/option_if_let_else.stderr b/tests/ui/option_if_let_else.stderr index 9eb41f81a53..2e2fe6f2049 100644 --- a/tests/ui/option_if_let_else.stderr +++ b/tests/ui/option_if_let_else.stderr @@ -334,5 +334,22 @@ error: use Option::map_or_else instead of an if let/else LL | let mut _hm = if let Some(hm) = &opt { hm.clone() } else { new_map!() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `opt.as_ref().map_or_else(|| new_map!(), |hm| hm.clone())` -error: aborting due to 25 previous errors +error: use Option::map_or instead of an if let/else + --> tests/ui/option_if_let_else.rs:372:22 + | +LL | let _ = unsafe { if let Some(o) = *opt_raw_ptr { o } else { 1 } }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*opt_raw_ptr).map_or(1, |o| o)` + +error: use Option::map_or_else instead of an if let/else + --> tests/ui/option_if_let_else.rs:378:13 + | +LL | let _ = match res { + | _____________^ +LL | | +LL | | Ok(s) => s.clone(), +LL | | Err(_) => String::new(), +LL | | }; + | |_____^ help: try: `res.map_or_else(|_| String::new(), |s| s.clone())` + +error: aborting due to 27 previous errors diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index a1119d75c23..0a8525a12f5 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -5,6 +5,7 @@ clippy::uninlined_format_args, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap, + clippy::unnecessary_result_map_or_else, clippy::useless_vec )] @@ -282,6 +283,8 @@ mod issue8993 { let _ = Some(4).map_or_else(g, f); //~^ or_fun_call let _ = Some(4).map_or(0, f); + let _ = Some(4).map_or_else(|| "asd".to_string().len() as i32, f); + //~^ or_fun_call } } @@ -409,4 +412,55 @@ fn fn_call_in_nested_expr() { //~^ or_fun_call } +mod result_map_or { + fn g() -> i32 { + 3 + } + + fn f(n: i32) -> i32 { + n + } + + fn test_map_or() { + let x: Result<i32, ()> = Ok(4); + let _ = x.map_or_else(|_| g(), |v| v); + //~^ or_fun_call + let _ = x.map_or_else(|_| g(), f); + //~^ or_fun_call + let _ = x.map_or(0, f); + let _ = x.map_or_else(|_| "asd".to_string().len() as i32, f); + //~^ or_fun_call + } +} + +fn test_option_get_or_insert() { + // assume that this is slow call + fn g() -> u8 { + 99 + } + let mut x = Some(42_u8); + let _ = x.get_or_insert_with(g); + //~^ or_fun_call +} + +fn test_option_and() { + // assume that this is slow call + fn g() -> Option<u8> { + Some(99) + } + let mut x = Some(42_u8); + let _ = x.and_then(|_| g()); + //~^ or_fun_call +} + +fn test_result_and() { + // assume that this is slow call + fn g() -> Result<u8, ()> { + Ok(99) + } + let mut x: Result<u8, ()> = Ok(42); + let _ = x.and_then(|_| g()); + //~^ or_fun_call +} + fn main() {} diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index a7cd632bf16..b4f9b950a7f 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -5,6 +5,7 @@ clippy::uninlined_format_args, clippy::unnecessary_wraps, clippy::unnecessary_literal_unwrap, + clippy::unnecessary_result_map_or_else, clippy::useless_vec )] @@ -282,6 +283,8 @@ mod issue8993 { let _ = Some(4).map_or(g(), f); //~^ or_fun_call let _ = Some(4).map_or(0, f); + let _ = Some(4).map_or("asd".to_string().len() as i32, f); + //~^ or_fun_call } } @@ -409,4 +412,55 @@ fn fn_call_in_nested_expr() { //~^ or_fun_call } +mod result_map_or { + fn g() -> i32 { + 3 + } + + fn f(n: i32) -> i32 { + n + } + + fn test_map_or() { + let x: Result<i32, ()> = Ok(4); + let _ = x.map_or(g(), |v| v); + //~^ or_fun_call + let _ = x.map_or(g(), f); + //~^ or_fun_call + let _ = x.map_or(0, f); + let _ = x.map_or("asd".to_string().len() as i32, f); + //~^ or_fun_call + } +} + +fn test_option_get_or_insert() { + // assume that this is slow call + fn g() -> u8 { + 99 + } + let mut x = Some(42_u8); + let _ = x.get_or_insert(g()); + //~^ or_fun_call +} + +fn test_option_and() { + // assume that this is slow call + fn g() -> Option<u8> { + Some(99) + } + let mut x = Some(42_u8); + let _ = x.and(g()); + //~^ or_fun_call +} + +fn test_result_and() { + // assume that this is slow call + fn g() -> Result<u8, ()> { + Ok(99) + } + let mut x: Result<u8, ()> = Ok(42); + let _ = x.and(g()); + //~^ or_fun_call +} + fn main() {} diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index 35bda7e4d33..3e4df772668 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -1,5 +1,5 @@ error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:52:22 + --> tests/ui/or_fun_call.rs:53:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(make)` @@ -8,7 +8,7 @@ LL | with_constructor.unwrap_or(make()); = help: to override `-D warnings` add `#[allow(clippy::or_fun_call)]` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:56:14 + --> tests/ui/or_fun_call.rs:57:14 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` @@ -17,199 +17,205 @@ LL | with_new.unwrap_or(Vec::new()); = help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:60:21 + --> tests/ui/or_fun_call.rs:61:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Vec::with_capacity(12))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:64:14 + --> tests/ui/or_fun_call.rs:65:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| make())` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:68:19 + --> tests/ui/or_fun_call.rs:69:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:72:24 + --> tests/ui/or_fun_call.rs:73:24 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:76:23 + --> tests/ui/or_fun_call.rs:77:23 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:80:18 + --> tests/ui/or_fun_call.rs:81:18 | LL | self_default.unwrap_or(<FakeDefault>::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(<FakeDefault>::default)` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:84:18 + --> tests/ui/or_fun_call.rs:85:18 | LL | real_default.unwrap_or(<FakeDefault as Default>::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:88:14 + --> tests/ui/or_fun_call.rs:89:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:92:21 + --> tests/ui/or_fun_call.rs:93:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(Foo::new)` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:96:19 + --> tests/ui/or_fun_call.rs:97:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:100:23 + --> tests/ui/or_fun_call.rs:101:23 | LL | map_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:104:21 + --> tests/ui/or_fun_call.rs:105:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert` to construct default value - --> tests/ui/or_fun_call.rs:108:25 + --> tests/ui/or_fun_call.rs:109:25 | LL | btree_vec.entry(42).or_insert(vec![]); | ^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:112:21 + --> tests/ui/or_fun_call.rs:113:21 | LL | let _ = stringy.unwrap_or(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `ok_or` - --> tests/ui/or_fun_call.rs:117:17 + --> tests/ui/or_fun_call.rs:118:17 | LL | let _ = opt.ok_or(format!("{} world.", hello)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ok_or_else(|| format!("{} world.", hello))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:122:21 + --> tests/ui/or_fun_call.rs:123:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:125:21 + --> tests/ui/or_fun_call.rs:126:21 | LL | let _ = Some(1).unwrap_or(map[&1]); | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| map[&1])` error: function call inside of `or` - --> tests/ui/or_fun_call.rs:150:35 + --> tests/ui/or_fun_call.rs:151:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_else(|| Some("b".to_string()))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:193:18 + --> tests/ui/or_fun_call.rs:194:18 | LL | None.unwrap_or(ptr_to_ref(s)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| ptr_to_ref(s))` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:201:14 + --> tests/ui/or_fun_call.rs:202:14 | LL | None.unwrap_or(unsafe { ptr_to_ref(s) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:204:14 + --> tests/ui/or_fun_call.rs:205:14 | LL | None.unwrap_or( unsafe { ptr_to_ref(s) } ); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| unsafe { ptr_to_ref(s) })` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:280:25 + --> tests/ui/or_fun_call.rs:281:25 | LL | let _ = Some(4).map_or(g(), |v| v); | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(g, |v| v)` error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:282:25 + --> tests/ui/or_fun_call.rs:283:25 | LL | let _ = Some(4).map_or(g(), f); | ^^^^^^^^^^^^^^ help: try: `map_or_else(g, f)` +error: function call inside of `map_or` + --> tests/ui/or_fun_call.rs:286:25 + | +LL | let _ = Some(4).map_or("asd".to_string().len() as i32, f); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| "asd".to_string().len() as i32, f)` + error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:314:18 + --> tests/ui/or_fun_call.rs:317:18 | LL | with_new.unwrap_or_else(Vec::new); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:318:28 + --> tests/ui/or_fun_call.rs:321:28 | LL | with_default_trait.unwrap_or_else(Default::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:322:27 + --> tests/ui/or_fun_call.rs:325:27 | LL | with_default_type.unwrap_or_else(u64::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:326:22 + --> tests/ui/or_fun_call.rs:329:22 | LL | real_default.unwrap_or_else(<FakeDefault as Default>::default); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/or_fun_call.rs:330:23 + --> tests/ui/or_fun_call.rs:333:23 | LL | map.entry(42).or_insert_with(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `or_insert_with` to construct default value - --> tests/ui/or_fun_call.rs:334:25 + --> tests/ui/or_fun_call.rs:337:25 | LL | btree.entry(42).or_insert_with(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()` error: use of `unwrap_or_else` to construct default value - --> tests/ui/or_fun_call.rs:338:25 + --> tests/ui/or_fun_call.rs:341:25 | LL | let _ = stringy.unwrap_or_else(String::new); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:380:17 + --> tests/ui/or_fun_call.rs:383:17 | LL | let _ = opt.unwrap_or({ f() }); // suggest `.unwrap_or_else(f)` | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(f)` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:385:17 + --> tests/ui/or_fun_call.rs:388:17 | LL | let _ = opt.unwrap_or(f() + 1); // suggest `.unwrap_or_else(|| f() + 1)` | ^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| f() + 1)` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:390:17 + --> tests/ui/or_fun_call.rs:393:17 | LL | let _ = opt.unwrap_or({ | _________________^ @@ -229,22 +235,58 @@ LL ~ }); | error: function call inside of `map_or` - --> tests/ui/or_fun_call.rs:396:17 + --> tests/ui/or_fun_call.rs:399:17 | LL | let _ = opt.map_or(f() + 1, |v| v); // suggest `.map_or_else(|| f() + 1, |v| v)` | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|| f() + 1, |v| v)` error: use of `unwrap_or` to construct default value - --> tests/ui/or_fun_call.rs:401:17 + --> tests/ui/or_fun_call.rs:404:17 | LL | let _ = opt.unwrap_or({ i32::default() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()` error: function call inside of `unwrap_or` - --> tests/ui/or_fun_call.rs:408:21 + --> tests/ui/or_fun_call.rs:411:21 | LL | let _ = opt_foo.unwrap_or(Foo { val: String::default() }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_else(|| Foo { val: String::default() })` -error: aborting due to 38 previous errors +error: function call inside of `map_or` + --> tests/ui/or_fun_call.rs:426:19 + | +LL | let _ = x.map_or(g(), |v| v); + | ^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), |v| v)` + +error: function call inside of `map_or` + --> tests/ui/or_fun_call.rs:428:19 + | +LL | let _ = x.map_or(g(), f); + | ^^^^^^^^^^^^^^ help: try: `map_or_else(|_| g(), f)` + +error: function call inside of `map_or` + --> tests/ui/or_fun_call.rs:431:19 + | +LL | let _ = x.map_or("asd".to_string().len() as i32, f); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `map_or_else(|_| "asd".to_string().len() as i32, f)` + +error: function call inside of `get_or_insert` + --> tests/ui/or_fun_call.rs:442:15 + | +LL | let _ = x.get_or_insert(g()); + | ^^^^^^^^^^^^^^^^^^ help: try: `get_or_insert_with(g)` + +error: function call inside of `and` + --> tests/ui/or_fun_call.rs:452:15 + | +LL | let _ = x.and(g()); + | ^^^^^^^^ help: try: `and_then(|_| g())` + +error: function call inside of `and` + --> tests/ui/or_fun_call.rs:462:15 + | +LL | let _ = x.and(g()); + | ^^^^^^^^ help: try: `and_then(|_| g())` + +error: aborting due to 45 previous errors diff --git a/tests/ui/or_then_unwrap.fixed b/tests/ui/or_then_unwrap.fixed index ba9beef57af..9660b82fe7d 100644 --- a/tests/ui/or_then_unwrap.fixed +++ b/tests/ui/or_then_unwrap.fixed @@ -28,6 +28,12 @@ fn main() { // //~^^ or_then_unwrap + // Call with macro should preserve the macro call rather than expand it + let option: Option<Vec<&str>> = None; + let _ = option.unwrap_or(vec!["fallback"]); // should trigger lint + // + //~^^ or_then_unwrap + // as part of a method chain let option: Option<&str> = None; let _ = option.map(|v| v).unwrap_or("fallback").to_string().chars(); // should trigger lint diff --git a/tests/ui/or_then_unwrap.rs b/tests/ui/or_then_unwrap.rs index fac90249a24..c3873352116 100644 --- a/tests/ui/or_then_unwrap.rs +++ b/tests/ui/or_then_unwrap.rs @@ -28,6 +28,12 @@ fn main() { // //~^^ or_then_unwrap + // Call with macro should preserve the macro call rather than expand it + let option: Option<Vec<&str>> = None; + let _ = option.or(Some(vec!["fallback"])).unwrap(); // should trigger lint + // + //~^^ or_then_unwrap + // as part of a method chain let option: Option<&str> = None; let _ = option.map(|v| v).or(Some("fallback")).unwrap().to_string().chars(); // should trigger lint diff --git a/tests/ui/or_then_unwrap.stderr b/tests/ui/or_then_unwrap.stderr index 1160498c605..3e66b15edbd 100644 --- a/tests/ui/or_then_unwrap.stderr +++ b/tests/ui/or_then_unwrap.stderr @@ -14,10 +14,16 @@ LL | let _ = result.or::<&str>(Ok("fallback")).unwrap(); // should trigger l | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` error: found `.or(Some(…)).unwrap()` - --> tests/ui/or_then_unwrap.rs:33:31 + --> tests/ui/or_then_unwrap.rs:33:20 + | +LL | let _ = option.or(Some(vec!["fallback"])).unwrap(); // should trigger lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or(vec!["fallback"])` + +error: found `.or(Some(…)).unwrap()` + --> tests/ui/or_then_unwrap.rs:39:31 | LL | let _ = option.map(|v| v).or(Some("fallback")).unwrap().to_string().chars(); // should trigger lint | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or("fallback")` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/partialeq_ne_impl.stderr b/tests/ui/partialeq_ne_impl.stderr index dc01a375060..0f700654f7c 100644 --- a/tests/ui/partialeq_ne_impl.stderr +++ b/tests/ui/partialeq_ne_impl.stderr @@ -1,12 +1,8 @@ error: re-implementing `PartialEq::ne` is unnecessary --> tests/ui/partialeq_ne_impl.rs:9:5 | -LL | / fn ne(&self, _: &Foo) -> bool { -LL | | -LL | | -LL | | false -LL | | } - | |_____^ +LL | fn ne(&self, _: &Foo) -> bool { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::partialeq-ne-impl` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::partialeq_ne_impl)]` diff --git a/tests/ui/pattern_type_mismatch/auxiliary/external.rs b/tests/ui/pattern_type_mismatch/auxiliary/external.rs new file mode 100644 index 00000000000..cd27c5c74aa --- /dev/null +++ b/tests/ui/pattern_type_mismatch/auxiliary/external.rs @@ -0,0 +1,13 @@ +//! **FAKE** external macro crate. + +#[macro_export] +macro_rules! macro_with_match { + ( $p:pat ) => { + let something = (); + + match &something { + $p => true, + _ => false, + } + }; +} diff --git a/tests/ui/pattern_type_mismatch/syntax.rs b/tests/ui/pattern_type_mismatch/syntax.rs index 49ea1d3f7a6..aa988a577df 100644 --- a/tests/ui/pattern_type_mismatch/syntax.rs +++ b/tests/ui/pattern_type_mismatch/syntax.rs @@ -6,6 +6,9 @@ clippy::single_match )] +//@aux-build:external.rs +use external::macro_with_match; + fn main() {} fn syntax_match() { @@ -159,3 +162,9 @@ fn macro_expansion() { let value = &Some(23); matching_macro!(value); } + +fn external_macro_expansion() { + macro_with_match! { + () + }; +} diff --git a/tests/ui/pattern_type_mismatch/syntax.stderr b/tests/ui/pattern_type_mismatch/syntax.stderr index cd604d604c1..636841e0a21 100644 --- a/tests/ui/pattern_type_mismatch/syntax.stderr +++ b/tests/ui/pattern_type_mismatch/syntax.stderr @@ -1,5 +1,5 @@ error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:16:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:19:9 | LL | Some(_) => (), | ^^^^^^^ @@ -9,7 +9,7 @@ LL | Some(_) => (), = help: to override `-D warnings` add `#[allow(clippy::pattern_type_mismatch)]` error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:36:12 + --> tests/ui/pattern_type_mismatch/syntax.rs:39:12 | LL | if let Some(_) = ref_value {} | ^^^^^^^ @@ -17,7 +17,7 @@ LL | if let Some(_) = ref_value {} = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:48:15 + --> tests/ui/pattern_type_mismatch/syntax.rs:51:15 | LL | while let Some(_) = ref_value { | ^^^^^^^ @@ -25,7 +25,7 @@ LL | while let Some(_) = ref_value { = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:68:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:71:9 | LL | for (_a, _b) in slice.iter() {} | ^^^^^^^^ @@ -33,7 +33,7 @@ LL | for (_a, _b) in slice.iter() {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:79:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:82:9 | LL | let (_n, _m) = ref_value; | ^^^^^^^^ @@ -41,7 +41,7 @@ LL | let (_n, _m) = ref_value; = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:89:12 + --> tests/ui/pattern_type_mismatch/syntax.rs:92:12 | LL | fn foo((_a, _b): &(i32, i32)) {} | ^^^^^^^^ @@ -49,7 +49,7 @@ LL | fn foo((_a, _b): &(i32, i32)) {} = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:104:10 + --> tests/ui/pattern_type_mismatch/syntax.rs:107:10 | LL | foo(|(_a, _b)| ()); | ^^^^^^^^ @@ -57,7 +57,7 @@ LL | foo(|(_a, _b)| ()); = help: explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:121:9 + --> tests/ui/pattern_type_mismatch/syntax.rs:124:9 | LL | Some(_) => (), | ^^^^^^^ @@ -65,7 +65,7 @@ LL | Some(_) => (), = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings error: type of pattern does not match the expression type - --> tests/ui/pattern_type_mismatch/syntax.rs:142:17 + --> tests/ui/pattern_type_mismatch/syntax.rs:145:17 | LL | Some(_) => (), | ^^^^^^^ diff --git a/tests/ui/ptr_arg.rs b/tests/ui/ptr_arg.rs index 2d77bf06ff9..be14e0762ff 100644 --- a/tests/ui/ptr_arg.rs +++ b/tests/ui/ptr_arg.rs @@ -123,7 +123,7 @@ fn test_cow_with_ref(c: &Cow<[i32]>) {} //~^ ptr_arg fn test_cow(c: Cow<[i32]>) { - let _c = c; + let d = c; } trait Foo2 { @@ -141,36 +141,36 @@ mod issue_5644 { use std::path::PathBuf; fn allowed( - #[allow(clippy::ptr_arg)] _v: &Vec<u32>, - #[allow(clippy::ptr_arg)] _s: &String, - #[allow(clippy::ptr_arg)] _p: &PathBuf, - #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, - #[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>, + #[allow(clippy::ptr_arg)] v: &Vec<u32>, + #[allow(clippy::ptr_arg)] s: &String, + #[allow(clippy::ptr_arg)] p: &PathBuf, + #[allow(clippy::ptr_arg)] c: &Cow<[i32]>, + #[expect(clippy::ptr_arg)] expect: &Cow<[i32]>, ) { } - fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {} + fn some_allowed(#[allow(clippy::ptr_arg)] v: &Vec<u32>, s: &String) {} //~^ ptr_arg struct S; impl S { fn allowed( - #[allow(clippy::ptr_arg)] _v: &Vec<u32>, - #[allow(clippy::ptr_arg)] _s: &String, - #[allow(clippy::ptr_arg)] _p: &PathBuf, - #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, - #[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>, + #[allow(clippy::ptr_arg)] v: &Vec<u32>, + #[allow(clippy::ptr_arg)] s: &String, + #[allow(clippy::ptr_arg)] p: &PathBuf, + #[allow(clippy::ptr_arg)] c: &Cow<[i32]>, + #[expect(clippy::ptr_arg)] expect: &Cow<[i32]>, ) { } } trait T { fn allowed( - #[allow(clippy::ptr_arg)] _v: &Vec<u32>, - #[allow(clippy::ptr_arg)] _s: &String, - #[allow(clippy::ptr_arg)] _p: &PathBuf, - #[allow(clippy::ptr_arg)] _c: &Cow<[i32]>, - #[expect(clippy::ptr_arg)] _expect: &Cow<[i32]>, + #[allow(clippy::ptr_arg)] v: &Vec<u32>, + #[allow(clippy::ptr_arg)] s: &String, + #[allow(clippy::ptr_arg)] p: &PathBuf, + #[allow(clippy::ptr_arg)] c: &Cow<[i32]>, + #[expect(clippy::ptr_arg)] expect: &Cow<[i32]>, ) { } } @@ -182,22 +182,22 @@ mod issue6509 { fn foo_vec(vec: &Vec<u8>) { //~^ ptr_arg - let _ = vec.clone().pop(); - let _ = vec.clone().clone(); + let a = vec.clone().pop(); + let b = vec.clone().clone(); } fn foo_path(path: &PathBuf) { //~^ ptr_arg - let _ = path.clone().pop(); - let _ = path.clone().clone(); + let c = path.clone().pop(); + let d = path.clone().clone(); } - fn foo_str(str: &PathBuf) { + fn foo_str(str: &String) { //~^ ptr_arg - let _ = str.clone().pop(); - let _ = str.clone().clone(); + let e = str.clone().pop(); + let f = str.clone().clone(); } } @@ -312,7 +312,7 @@ mod issue_9218 { // Inferred to be `&'a str`, afaik. fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { - //~^ ERROR: elided lifetime has a name + //~^ ERROR: eliding a lifetime that's named elsewhere is confusing todo!() } } @@ -340,8 +340,8 @@ mod issue_13308 { ToOwned::clone_into(source, destination); } - fn h1(_: &<String as Deref>::Target) {} - fn h2<T: Deref>(_: T, _: &T::Target) {} + fn h1(x: &<String as Deref>::Target) {} + fn h2<T: Deref>(x: T, y: &T::Target) {} // Other cases that are still ok to lint and ideally shouldn't regress fn good(v1: &String, v2: &String) { @@ -352,3 +352,91 @@ mod issue_13308 { h2(String::new(), v2); } } + +mod issue_13489_and_13728 { + // This is a no-lint from now on. + fn foo(_x: &Vec<i32>) { + todo!(); + } + + // But this still gives us a lint. + fn foo_used(x: &Vec<i32>) { + //~^ ptr_arg + + todo!(); + } + + // This is also a no-lint from now on. + fn foo_local(x: &Vec<i32>) { + let _y = x; + + todo!(); + } + + // But this still gives us a lint. + fn foo_local_used(x: &Vec<i32>) { + //~^ ptr_arg + + let y = x; + + todo!(); + } + + // This only lints once from now on. + fn foofoo(_x: &Vec<i32>, y: &String) { + //~^ ptr_arg + + todo!(); + } + + // And this is also a no-lint from now on. + fn foofoo_local(_x: &Vec<i32>, y: &String) { + let _z = y; + + todo!(); + } +} + +mod issue_13489_and_13728_mut { + // This is a no-lint from now on. + fn bar(_x: &mut Vec<u32>) { + todo!() + } + + // But this still gives us a lint. + fn bar_used(x: &mut Vec<u32>) { + //~^ ptr_arg + + todo!() + } + + // This is also a no-lint from now on. + fn bar_local(x: &mut Vec<u32>) { + let _y = x; + + todo!() + } + + // But this still gives us a lint. + fn bar_local_used(x: &mut Vec<u32>) { + //~^ ptr_arg + + let y = x; + + todo!() + } + + // This only lints once from now on. + fn barbar(_x: &mut Vec<u32>, y: &mut String) { + //~^ ptr_arg + + todo!() + } + + // And this is also a no-lint from now on. + fn barbar_local(_x: &mut Vec<u32>, y: &mut String) { + let _z = y; + + todo!() + } +} diff --git a/tests/ui/ptr_arg.stderr b/tests/ui/ptr_arg.stderr index 741e60cbd74..87235057349 100644 --- a/tests/ui/ptr_arg.stderr +++ b/tests/ui/ptr_arg.stderr @@ -1,12 +1,3 @@ -error: elided lifetime has a name - --> tests/ui/ptr_arg.rs:314:56 - | -LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { - | -- lifetime `'a` declared here ^ this elided lifetime gets resolved as `'a` - | - = note: `-D elided-named-lifetimes` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(elided_named_lifetimes)]` - error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:13:14 | @@ -136,10 +127,10 @@ LL | fn test_cow_with_ref(c: &Cow<[i32]>) {} | ^^^^^^^^^^^ help: change this to: `&[i32]` error: writing `&String` instead of `&str` involves a new object where a slice will do - --> tests/ui/ptr_arg.rs:152:66 + --> tests/ui/ptr_arg.rs:152:64 | -LL | fn some_allowed(#[allow(clippy::ptr_arg)] _v: &Vec<u32>, _s: &String) {} - | ^^^^^^^ help: change this to: `&str` +LL | fn some_allowed(#[allow(clippy::ptr_arg)] v: &Vec<u32>, s: &String) {} + | ^^^^^^^ help: change this to: `&str` error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:182:21 @@ -152,8 +143,8 @@ help: change this to LL ~ fn foo_vec(vec: &[u8]) { LL | LL | -LL ~ let _ = vec.to_owned().pop(); -LL ~ let _ = vec.to_owned().clone(); +LL ~ let a = vec.to_owned().pop(); +LL ~ let b = vec.to_owned().clone(); | error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do @@ -167,23 +158,23 @@ help: change this to LL ~ fn foo_path(path: &Path) { LL | LL | -LL ~ let _ = path.to_path_buf().pop(); -LL ~ let _ = path.to_path_buf().clone(); +LL ~ let c = path.to_path_buf().pop(); +LL ~ let d = path.to_path_buf().clone(); | -error: writing `&PathBuf` instead of `&Path` involves a new object where a slice will do +error: writing `&String` instead of `&str` involves a new object where a slice will do --> tests/ui/ptr_arg.rs:196:21 | -LL | fn foo_str(str: &PathBuf) { - | ^^^^^^^^ +LL | fn foo_str(str: &String) { + | ^^^^^^^ | help: change this to | -LL ~ fn foo_str(str: &Path) { +LL ~ fn foo_str(str: &str) { LL | LL | -LL ~ let _ = str.to_path_buf().pop(); -LL ~ let _ = str.to_path_buf().clone(); +LL ~ let e = str.to_owned().pop(); +LL ~ let f = str.to_owned().clone(); | error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do @@ -240,5 +231,58 @@ error: writing `&String` instead of `&str` involves a new object where a slice w LL | fn good(v1: &String, v2: &String) { | ^^^^^^^ help: change this to: `&str` -error: aborting due to 27 previous errors +error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do + --> tests/ui/ptr_arg.rs:363:20 + | +LL | fn foo_used(x: &Vec<i32>) { + | ^^^^^^^^^ help: change this to: `&[i32]` + +error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do + --> tests/ui/ptr_arg.rs:377:26 + | +LL | fn foo_local_used(x: &Vec<i32>) { + | ^^^^^^^^^ help: change this to: `&[i32]` + +error: writing `&String` instead of `&str` involves a new object where a slice will do + --> tests/ui/ptr_arg.rs:386:33 + | +LL | fn foofoo(_x: &Vec<i32>, y: &String) { + | ^^^^^^^ help: change this to: `&str` + +error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do + --> tests/ui/ptr_arg.rs:407:20 + | +LL | fn bar_used(x: &mut Vec<u32>) { + | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` + +error: writing `&mut Vec` instead of `&mut [_]` involves a new object where a slice will do + --> tests/ui/ptr_arg.rs:421:26 + | +LL | fn bar_local_used(x: &mut Vec<u32>) { + | ^^^^^^^^^^^^^ help: change this to: `&mut [u32]` + +error: writing `&mut String` instead of `&mut str` involves a new object where a slice will do + --> tests/ui/ptr_arg.rs:430:37 + | +LL | fn barbar(_x: &mut Vec<u32>, y: &mut String) { + | ^^^^^^^^^^^ help: change this to: `&mut str` + +error: eliding a lifetime that's named elsewhere is confusing + --> tests/ui/ptr_arg.rs:314:36 + | +LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &str { + | ^^ ^^ ---- the same lifetime is elided here + | | | + | | the lifetime is named here + | the lifetime is named here + | + = help: the same lifetime is referred to in inconsistent ways, making the signature confusing + = note: `-D mismatched-lifetime-syntaxes` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(mismatched_lifetime_syntaxes)]` +help: consistently use `'a` + | +LL | fn cow_good_ret_ty<'a>(input: &'a Cow<'a, str>) -> &'a str { + | ++ + +error: aborting due to 33 previous errors diff --git a/tests/ui/ptr_as_ptr.fixed b/tests/ui/ptr_as_ptr.fixed index 2033f31c1ee..4457878b6fa 100644 --- a/tests/ui/ptr_as_ptr.fixed +++ b/tests/ui/ptr_as_ptr.fixed @@ -2,8 +2,8 @@ #![warn(clippy::ptr_as_ptr)] -#[macro_use] extern crate proc_macros; +use proc_macros::{external, inline_macros, with_span}; mod issue_11278_a { #[derive(Debug)] @@ -53,11 +53,13 @@ fn main() { //~^ ptr_as_ptr // Make sure the lint is triggered inside a macro - let _ = inline!($ptr.cast::<i32>()); - //~^ ptr_as_ptr + // FIXME: `is_from_proc_macro` incorrectly stops the lint from firing here + let _ = inline!($ptr as *const i32); // Do not lint inside macros from external crates let _ = external!($ptr as *const i32); + + let _ = with_span!(expr $ptr as *const i32); } #[clippy::msrv = "1.37"] @@ -219,3 +221,17 @@ mod null_entire_infer { //~^ ptr_as_ptr } } + +#[allow(clippy::transmute_null_to_fn)] +fn issue15283() { + unsafe { + let _: fn() = std::mem::transmute(std::ptr::null::<u8>()); + //~^ ptr_as_ptr + } +} + +fn issue15232() { + let mut b = Box::new(0i32); + let _ptr = std::ptr::addr_of_mut!(*b).cast::<()>(); + //~^ ptr_as_ptr +} diff --git a/tests/ui/ptr_as_ptr.rs b/tests/ui/ptr_as_ptr.rs index 224d09b0eb6..9124fc912d2 100644 --- a/tests/ui/ptr_as_ptr.rs +++ b/tests/ui/ptr_as_ptr.rs @@ -2,8 +2,8 @@ #![warn(clippy::ptr_as_ptr)] -#[macro_use] extern crate proc_macros; +use proc_macros::{external, inline_macros, with_span}; mod issue_11278_a { #[derive(Debug)] @@ -53,11 +53,13 @@ fn main() { //~^ ptr_as_ptr // Make sure the lint is triggered inside a macro + // FIXME: `is_from_proc_macro` incorrectly stops the lint from firing here let _ = inline!($ptr as *const i32); - //~^ ptr_as_ptr // Do not lint inside macros from external crates let _ = external!($ptr as *const i32); + + let _ = with_span!(expr $ptr as *const i32); } #[clippy::msrv = "1.37"] @@ -219,3 +221,17 @@ mod null_entire_infer { //~^ ptr_as_ptr } } + +#[allow(clippy::transmute_null_to_fn)] +fn issue15283() { + unsafe { + let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); + //~^ ptr_as_ptr + } +} + +fn issue15232() { + let mut b = Box::new(0i32); + let _ptr = std::ptr::addr_of_mut!(*b) as *mut (); + //~^ ptr_as_ptr +} diff --git a/tests/ui/ptr_as_ptr.stderr b/tests/ui/ptr_as_ptr.stderr index 66dae8e0135..af21c1e35f5 100644 --- a/tests/ui/ptr_as_ptr.stderr +++ b/tests/ui/ptr_as_ptr.stderr @@ -38,168 +38,172 @@ LL | let _: *mut i32 = mut_ptr as _; | ^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:56:21 - | -LL | let _ = inline!($ptr as *const i32); - | ^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `$ptr.cast::<i32>()` - | - = note: this error originates in the macro `__inline_mac_fn_main` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:78:13 + --> tests/ui/ptr_as_ptr.rs:80:13 | LL | let _ = ptr as *const i32; | ^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `ptr.cast::<i32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:80:13 + --> tests/ui/ptr_as_ptr.rs:82:13 | LL | let _ = mut_ptr as *mut i32; | ^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `mut_ptr.cast::<i32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:88:9 + --> tests/ui/ptr_as_ptr.rs:90:9 | LL | ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:93:9 + --> tests/ui/ptr_as_ptr.rs:95:9 | LL | std::ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:99:9 + --> tests/ui/ptr_as_ptr.rs:101:9 | LL | ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:104:9 + --> tests/ui/ptr_as_ptr.rs:106:9 | LL | core::ptr::null_mut() as *mut u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:110:9 + --> tests/ui/ptr_as_ptr.rs:112:9 | LL | ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:115:9 + --> tests/ui/ptr_as_ptr.rs:117:9 | LL | std::ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:121:9 + --> tests/ui/ptr_as_ptr.rs:123:9 | LL | ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:126:9 + --> tests/ui/ptr_as_ptr.rs:128:9 | LL | core::ptr::null() as *const u32 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null::<u32>()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:134:9 + --> tests/ui/ptr_as_ptr.rs:136:9 | LL | ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:139:9 + --> tests/ui/ptr_as_ptr.rs:141:9 | LL | std::ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:145:9 + --> tests/ui/ptr_as_ptr.rs:147:9 | LL | ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:150:9 + --> tests/ui/ptr_as_ptr.rs:152:9 | LL | core::ptr::null_mut() as *mut _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:156:9 + --> tests/ui/ptr_as_ptr.rs:158:9 | LL | ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:161:9 + --> tests/ui/ptr_as_ptr.rs:163:9 | LL | std::ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:167:9 + --> tests/ui/ptr_as_ptr.rs:169:9 | LL | ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:172:9 + --> tests/ui/ptr_as_ptr.rs:174:9 | LL | core::ptr::null() as *const _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:180:9 + --> tests/ui/ptr_as_ptr.rs:182:9 | LL | ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:185:9 + --> tests/ui/ptr_as_ptr.rs:187:9 | LL | std::ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:191:9 + --> tests/ui/ptr_as_ptr.rs:193:9 | LL | ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:196:9 + --> tests/ui/ptr_as_ptr.rs:198:9 | LL | core::ptr::null_mut() as _ | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null_mut()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:202:9 + --> tests/ui/ptr_as_ptr.rs:204:9 | LL | ptr::null() as _ | ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:207:9 + --> tests/ui/ptr_as_ptr.rs:209:9 | LL | std::ptr::null() as _ | ^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:213:9 + --> tests/ui/ptr_as_ptr.rs:215:9 | LL | ptr::null() as _ | ^^^^^^^^^^^^^^^^ help: try call directly: `ptr::null()` error: `as` casting between raw pointers without changing their constness - --> tests/ui/ptr_as_ptr.rs:218:9 + --> tests/ui/ptr_as_ptr.rs:220:9 | LL | core::ptr::null() as _ | ^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `core::ptr::null()` -error: aborting due to 33 previous errors +error: `as` casting between raw pointers without changing their constness + --> tests/ui/ptr_as_ptr.rs:228:43 + | +LL | let _: fn() = std::mem::transmute(std::ptr::null::<()>() as *const u8); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try call directly: `std::ptr::null::<u8>()` + +error: `as` casting between raw pointers without changing their constness + --> tests/ui/ptr_as_ptr.rs:235:16 + | +LL | let _ptr = std::ptr::addr_of_mut!(*b) as *mut (); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try `pointer::cast`, a safer alternative: `std::ptr::addr_of_mut!(*b).cast::<()>()` + +error: aborting due to 34 previous errors diff --git a/tests/ui/question_mark.fixed b/tests/ui/question_mark.fixed index 60dc1c101b6..8d6f5fbadca 100644 --- a/tests/ui/question_mark.fixed +++ b/tests/ui/question_mark.fixed @@ -453,3 +453,15 @@ fn const_in_pattern(x: Option<(i32, i32)>) -> Option<()> { None } + +fn issue_13642(x: Option<i32>) -> Option<()> { + let Some(x) = x else { + #[cfg(false)] + panic!(); + + #[cfg(true)] + return None; + }; + + None +} diff --git a/tests/ui/question_mark.rs b/tests/ui/question_mark.rs index 99d0122a98f..f13eee29c11 100644 --- a/tests/ui/question_mark.rs +++ b/tests/ui/question_mark.rs @@ -549,3 +549,15 @@ fn const_in_pattern(x: Option<(i32, i32)>) -> Option<()> { None } + +fn issue_13642(x: Option<i32>) -> Option<()> { + let Some(x) = x else { + #[cfg(false)] + panic!(); + + #[cfg(true)] + return None; + }; + + None +} diff --git a/tests/ui/range_plus_minus_one.fixed b/tests/ui/range_plus_minus_one.fixed index ee716ef3a6a..5c6da6d5aed 100644 --- a/tests/ui/range_plus_minus_one.fixed +++ b/tests/ui/range_plus_minus_one.fixed @@ -1,5 +1,9 @@ +#![warn(clippy::range_minus_one, clippy::range_plus_one)] #![allow(unused_parens)] #![allow(clippy::iter_with_drain)] + +use std::ops::{Index, IndexMut, Range, RangeBounds, RangeInclusive}; + fn f() -> usize { 42 } @@ -20,8 +24,6 @@ macro_rules! macro_minus_one { }; } -#[warn(clippy::range_plus_one)] -#[warn(clippy::range_minus_one)] fn main() { for _ in 0..2 {} for _ in 0..=2 {} @@ -45,15 +47,13 @@ fn main() { //~^ range_plus_one for _ in 0..=(1 + f()) {} + // Those are not linted, as in the general case we cannot be sure that the exact type won't be + // important. let _ = ..11 - 1; - let _ = ..11; - //~^ range_minus_one - let _ = ..11; - //~^ range_minus_one - let _ = (1..=11); - //~^ range_plus_one - let _ = ((f() + 1)..=f()); - //~^ range_plus_one + let _ = ..=11 - 1; + let _ = ..=(11 - 1); + let _ = (1..11 + 1); + let _ = (f() + 1)..(f() + 1); const ONE: usize = 1; // integer consts are linted, too @@ -65,4 +65,118 @@ fn main() { macro_plus_one!(5); macro_minus_one!(5); + + // As an instance of `Iterator` + (1..=10).for_each(|_| {}); + //~^ range_plus_one + + // As an instance of `IntoIterator` + #[allow(clippy::useless_conversion)] + (1..=10).into_iter().for_each(|_| {}); + //~^ range_plus_one + + // As an instance of `RangeBounds` + { + let _ = (1..=10).start_bound(); + //~^ range_plus_one + } + + // As a `SliceIndex` + let a = [10, 20, 30]; + let _ = &a[1..=1]; + //~^ range_plus_one + + // As method call argument + vec.drain(2..=3); + //~^ range_plus_one + + // As function call argument + take_arg(10..=20); + //~^ range_plus_one + + // As function call argument inside a block + take_arg({ 10..=20 }); + //~^ range_plus_one + + // Do not lint in case types are unified + take_arg(if true { 10..20 } else { 10..20 + 1 }); + + // Do not lint, as the same type is used for both parameters + take_args(10..20 + 1, 10..21); + + // Do not lint, as the range type is also used indirectly in second parameter + take_arg_and_struct(10..20 + 1, S { t: 1..2 }); + + // As target of `IndexMut` + let mut a = [10, 20, 30]; + a[0..=2][0] = 1; + //~^ range_plus_one +} + +fn take_arg<T: Iterator<Item = u32>>(_: T) {} +fn take_args<T: Iterator<Item = u32>>(_: T, _: T) {} + +struct S<T> { + t: T, +} +fn take_arg_and_struct<T: Iterator<Item = u32>>(_: T, _: S<T>) {} + +fn no_index_by_range_inclusive(a: usize) { + struct S; + + impl Index<Range<usize>> for S { + type Output = [u32]; + fn index(&self, _: Range<usize>) -> &Self::Output { + &[] + } + } + + _ = &S[0..a + 1]; +} + +fn no_index_mut_with_switched_range(a: usize) { + struct S(u32); + + impl Index<Range<usize>> for S { + type Output = u32; + fn index(&self, _: Range<usize>) -> &Self::Output { + &self.0 + } + } + + impl IndexMut<Range<usize>> for S { + fn index_mut(&mut self, _: Range<usize>) -> &mut Self::Output { + &mut self.0 + } + } + + impl Index<RangeInclusive<usize>> for S { + type Output = u32; + fn index(&self, _: RangeInclusive<usize>) -> &Self::Output { + &self.0 + } + } + + S(2)[0..a + 1] = 3; +} + +fn issue9908() { + // Simplified test case + let _ = || 0..=1; + + // Original test case + let full_length = 1024; + let range = { + // do some stuff, omit here + None + }; + + let range = range.map(|(s, t)| s..=t).unwrap_or(0..=(full_length - 1)); + + assert_eq!(range, 0..=1023); +} + +fn issue9908_2(n: usize) -> usize { + (1..n).sum() + //~^ range_minus_one } diff --git a/tests/ui/range_plus_minus_one.rs b/tests/ui/range_plus_minus_one.rs index f2d5ae2c150..7172da6034b 100644 --- a/tests/ui/range_plus_minus_one.rs +++ b/tests/ui/range_plus_minus_one.rs @@ -1,5 +1,9 @@ +#![warn(clippy::range_minus_one, clippy::range_plus_one)] #![allow(unused_parens)] #![allow(clippy::iter_with_drain)] + +use std::ops::{Index, IndexMut, Range, RangeBounds, RangeInclusive}; + fn f() -> usize { 42 } @@ -20,8 +24,6 @@ macro_rules! macro_minus_one { }; } -#[warn(clippy::range_plus_one)] -#[warn(clippy::range_minus_one)] fn main() { for _ in 0..2 {} for _ in 0..=2 {} @@ -45,15 +47,13 @@ fn main() { //~^ range_plus_one for _ in 0..=(1 + f()) {} + // Those are not linted, as in the general case we cannot be sure that the exact type won't be + // important. let _ = ..11 - 1; let _ = ..=11 - 1; - //~^ range_minus_one let _ = ..=(11 - 1); - //~^ range_minus_one let _ = (1..11 + 1); - //~^ range_plus_one let _ = (f() + 1)..(f() + 1); - //~^ range_plus_one const ONE: usize = 1; // integer consts are linted, too @@ -65,4 +65,118 @@ fn main() { macro_plus_one!(5); macro_minus_one!(5); + + // As an instance of `Iterator` + (1..10 + 1).for_each(|_| {}); + //~^ range_plus_one + + // As an instance of `IntoIterator` + #[allow(clippy::useless_conversion)] + (1..10 + 1).into_iter().for_each(|_| {}); + //~^ range_plus_one + + // As an instance of `RangeBounds` + { + let _ = (1..10 + 1).start_bound(); + //~^ range_plus_one + } + + // As a `SliceIndex` + let a = [10, 20, 30]; + let _ = &a[1..1 + 1]; + //~^ range_plus_one + + // As method call argument + vec.drain(2..3 + 1); + //~^ range_plus_one + + // As function call argument + take_arg(10..20 + 1); + //~^ range_plus_one + + // As function call argument inside a block + take_arg({ 10..20 + 1 }); + //~^ range_plus_one + + // Do not lint in case types are unified + take_arg(if true { 10..20 } else { 10..20 + 1 }); + + // Do not lint, as the same type is used for both parameters + take_args(10..20 + 1, 10..21); + + // Do not lint, as the range type is also used indirectly in second parameter + take_arg_and_struct(10..20 + 1, S { t: 1..2 }); + + // As target of `IndexMut` + let mut a = [10, 20, 30]; + a[0..2 + 1][0] = 1; + //~^ range_plus_one +} + +fn take_arg<T: Iterator<Item = u32>>(_: T) {} +fn take_args<T: Iterator<Item = u32>>(_: T, _: T) {} + +struct S<T> { + t: T, +} +fn take_arg_and_struct<T: Iterator<Item = u32>>(_: T, _: S<T>) {} + +fn no_index_by_range_inclusive(a: usize) { + struct S; + + impl Index<Range<usize>> for S { + type Output = [u32]; + fn index(&self, _: Range<usize>) -> &Self::Output { + &[] + } + } + + _ = &S[0..a + 1]; +} + +fn no_index_mut_with_switched_range(a: usize) { + struct S(u32); + + impl Index<Range<usize>> for S { + type Output = u32; + fn index(&self, _: Range<usize>) -> &Self::Output { + &self.0 + } + } + + impl IndexMut<Range<usize>> for S { + fn index_mut(&mut self, _: Range<usize>) -> &mut Self::Output { + &mut self.0 + } + } + + impl Index<RangeInclusive<usize>> for S { + type Output = u32; + fn index(&self, _: RangeInclusive<usize>) -> &Self::Output { + &self.0 + } + } + + S(2)[0..a + 1] = 3; +} + +fn issue9908() { + // Simplified test case + let _ = || 0..=1; + + // Original test case + let full_length = 1024; + let range = { + // do some stuff, omit here + None + }; + + let range = range.map(|(s, t)| s..=t).unwrap_or(0..=(full_length - 1)); + + assert_eq!(range, 0..=1023); +} + +fn issue9908_2(n: usize) -> usize { + (1..=n - 1).sum() + //~^ range_minus_one } diff --git a/tests/ui/range_plus_minus_one.stderr b/tests/ui/range_plus_minus_one.stderr index 9b23a8b8c0b..a419d935bd6 100644 --- a/tests/ui/range_plus_minus_one.stderr +++ b/tests/ui/range_plus_minus_one.stderr @@ -1,5 +1,5 @@ error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:29:14 + --> tests/ui/range_plus_minus_one.rs:31:14 | LL | for _ in 0..3 + 1 {} | ^^^^^^^^ help: use: `0..=3` @@ -8,55 +8,85 @@ LL | for _ in 0..3 + 1 {} = help: to override `-D warnings` add `#[allow(clippy::range_plus_one)]` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:33:14 + --> tests/ui/range_plus_minus_one.rs:35:14 | LL | for _ in 0..1 + 5 {} | ^^^^^^^^ help: use: `0..=5` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:37:14 + --> tests/ui/range_plus_minus_one.rs:39:14 | LL | for _ in 1..1 + 1 {} | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:44:14 + --> tests/ui/range_plus_minus_one.rs:46:14 | LL | for _ in 0..(1 + f()) {} | ^^^^^^^^^^^^ help: use: `0..=f()` -error: an exclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:49:13 +error: an inclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:60:14 | -LL | let _ = ..=11 - 1; - | ^^^^^^^^^ help: use: `..11` +LL | for _ in 1..ONE + ONE {} + | ^^^^^^^^^^^^ help: use: `1..=ONE` + +error: an inclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:70:5 | - = note: `-D clippy::range-minus-one` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::range_minus_one)]` +LL | (1..10 + 1).for_each(|_| {}); + | ^^^^^^^^^^^ help: use: `(1..=10)` -error: an exclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:51:13 +error: an inclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:75:5 | -LL | let _ = ..=(11 - 1); - | ^^^^^^^^^^^ help: use: `..11` +LL | (1..10 + 1).into_iter().for_each(|_| {}); + | ^^^^^^^^^^^ help: use: `(1..=10)` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:53:13 + --> tests/ui/range_plus_minus_one.rs:80:17 | -LL | let _ = (1..11 + 1); - | ^^^^^^^^^^^ help: use: `(1..=11)` +LL | let _ = (1..10 + 1).start_bound(); + | ^^^^^^^^^^^ help: use: `(1..=10)` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:55:13 + --> tests/ui/range_plus_minus_one.rs:86:16 | -LL | let _ = (f() + 1)..(f() + 1); - | ^^^^^^^^^^^^^^^^^^^^ help: use: `((f() + 1)..=f())` +LL | let _ = &a[1..1 + 1]; + | ^^^^^^^^ help: use: `1..=1` error: an inclusive range would be more readable - --> tests/ui/range_plus_minus_one.rs:60:14 + --> tests/ui/range_plus_minus_one.rs:90:15 | -LL | for _ in 1..ONE + ONE {} - | ^^^^^^^^^^^^ help: use: `1..=ONE` +LL | vec.drain(2..3 + 1); + | ^^^^^^^^ help: use: `2..=3` + +error: an inclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:94:14 + | +LL | take_arg(10..20 + 1); + | ^^^^^^^^^^ help: use: `10..=20` + +error: an inclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:98:16 + | +LL | take_arg({ 10..20 + 1 }); + | ^^^^^^^^^^ help: use: `10..=20` + +error: an inclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:112:7 + | +LL | a[0..2 + 1][0] = 1; + | ^^^^^^^^ help: use: `0..=2` + +error: an exclusive range would be more readable + --> tests/ui/range_plus_minus_one.rs:180:5 + | +LL | (1..=n - 1).sum() + | ^^^^^^^^^^^ help: use: `(1..n)` + | + = note: `-D clippy::range-minus-one` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::range_minus_one)]` -error: aborting due to 9 previous errors +error: aborting due to 14 previous errors diff --git a/tests/ui/redundant_closure_call_fixable.fixed b/tests/ui/redundant_closure_call_fixable.fixed index 099c118e64e..9f6643e8d52 100644 --- a/tests/ui/redundant_closure_call_fixable.fixed +++ b/tests/ui/redundant_closure_call_fixable.fixed @@ -60,7 +60,7 @@ fn issue9956() { //~^ redundant_closure_call // immediately calling only one closure, so we can't remove the other ones - let a = (|| || 123); + let a = || || 123; //~^ redundant_closure_call dbg!(a()()); @@ -144,3 +144,15 @@ fn issue_12358() { // different. make_closure!(x)(); } + +#[rustfmt::skip] +fn issue_9583() { + Some(true) == Some(true); + //~^ redundant_closure_call + Some(true) == Some(true); + //~^ redundant_closure_call + Some(if 1 > 2 {1} else {2}) == Some(2); + //~^ redundant_closure_call + Some( 1 > 2 ) == Some(true); + //~^ redundant_closure_call +} diff --git a/tests/ui/redundant_closure_call_fixable.rs b/tests/ui/redundant_closure_call_fixable.rs index da5dd7ef263..34f22878678 100644 --- a/tests/ui/redundant_closure_call_fixable.rs +++ b/tests/ui/redundant_closure_call_fixable.rs @@ -144,3 +144,15 @@ fn issue_12358() { // different. make_closure!(x)(); } + +#[rustfmt::skip] +fn issue_9583() { + (|| { Some(true) })() == Some(true); + //~^ redundant_closure_call + (|| Some(true))() == Some(true); + //~^ redundant_closure_call + (|| { Some(if 1 > 2 {1} else {2}) })() == Some(2); + //~^ redundant_closure_call + (|| { Some( 1 > 2 ) })() == Some(true); + //~^ redundant_closure_call +} diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index 2c35aafbe31..a5591cf7813 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -95,7 +95,7 @@ error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:63:13 | LL | let a = (|| || || 123)(); - | ^^^^^^^^^^^^^^^^ help: try doing something like: `(|| || 123)` + | ^^^^^^^^^^^^^^^^ help: try doing something like: `|| || 123` error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:68:13 @@ -145,5 +145,29 @@ error: try not to call a closure in the expression where it is declared LL | std::convert::identity((|| 13_i32 + 36_i32)()).leading_zeros(); | ^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `13_i32 + 36_i32` -error: aborting due to 17 previous errors +error: try not to call a closure in the expression where it is declared + --> tests/ui/redundant_closure_call_fixable.rs:150:5 + | +LL | (|| { Some(true) })() == Some(true); + | ^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `Some(true)` + +error: try not to call a closure in the expression where it is declared + --> tests/ui/redundant_closure_call_fixable.rs:152:5 + | +LL | (|| Some(true))() == Some(true); + | ^^^^^^^^^^^^^^^^^ help: try doing something like: `Some(true)` + +error: try not to call a closure in the expression where it is declared + --> tests/ui/redundant_closure_call_fixable.rs:154:5 + | +LL | (|| { Some(if 1 > 2 {1} else {2}) })() == Some(2); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `Some(if 1 > 2 {1} else {2})` + +error: try not to call a closure in the expression where it is declared + --> tests/ui/redundant_closure_call_fixable.rs:156:5 + | +LL | (|| { Some( 1 > 2 ) })() == Some(true); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try doing something like: `Some( 1 > 2 )` + +error: aborting due to 21 previous errors diff --git a/tests/ui/return_and_then.fixed b/tests/ui/return_and_then.fixed index 8d9481d1595..8ee259b97f3 100644 --- a/tests/ui/return_and_then.fixed +++ b/tests/ui/return_and_then.fixed @@ -99,6 +99,92 @@ fn main() { }; None } + + #[expect(clippy::diverging_sub_expression)] + fn with_return_in_expression() -> Option<i32> { + _ = ( + return { + let x = Some("")?; + if x.len() > 2 { Some(3) } else { None } + }, + //~^ return_and_then + 10, + ); + } + + fn inside_if(a: bool, i: Option<u32>) -> Option<u32> { + if a { + let i = i?; + if i > 3 { Some(i) } else { None } + //~^ return_and_then + } else { + Some(42) + } + } + + fn inside_match(a: u32, i: Option<u32>) -> Option<u32> { + match a { + 1 | 2 => { + let i = i?; + if i > 3 { Some(i) } else { None } + }, + //~^ return_and_then + 3 | 4 => Some(42), + _ => None, + } + } + + fn inside_match_and_block_and_if(a: u32, i: Option<u32>) -> Option<u32> { + match a { + 1 | 2 => { + let a = a * 3; + if a.is_multiple_of(2) { + let i = i?; + if i > 3 { Some(i) } else { None } + //~^ return_and_then + } else { + Some(10) + } + }, + 3 | 4 => Some(42), + _ => None, + } + } + + #[expect(clippy::never_loop)] + fn with_break(i: Option<u32>) -> Option<u32> { + match i { + Some(1) => loop { + break ({ + let i = i?; + if i > 3 { Some(i) } else { None } + }); + //~^ return_and_then + }, + Some(2) => 'foo: loop { + loop { + break 'foo ({ + let i = i?; + if i > 3 { Some(i) } else { None } + }); + //~^ return_and_then + } + }, + Some(3) => 'bar: { + break 'bar ({ + let i = i?; + if i > 3 { Some(i) } else { None } + }); + //~^ return_and_then + }, + Some(4) => 'baz: loop { + _ = loop { + break i.and_then(|i| if i > 3 { Some(i) } else { None }); + }; + }, + _ => None, + } + } } fn gen_option(n: i32) -> Option<i32> { @@ -124,3 +210,48 @@ mod issue14781 { Ok(()) } } + +mod issue15111 { + #[derive(Debug)] + struct EvenOdd { + even: Option<u32>, + odd: Option<u32>, + } + + impl EvenOdd { + fn new(i: Option<u32>) -> Self { + Self { + even: i.and_then(|i| if i.is_multiple_of(2) { Some(i) } else { None }), + odd: i.and_then(|i| if i.is_multiple_of(2) { None } else { Some(i) }), + } + } + } + + fn with_if_let(i: Option<u32>) -> u32 { + if let Some(x) = i.and_then(|i| if i.is_multiple_of(2) { Some(i) } else { None }) { + x + } else { + std::hint::black_box(0) + } + } + + fn main() { + let _ = EvenOdd::new(Some(2)); + } +} + +mod issue14927 { + use std::path::Path; + struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), + } + const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, + }; +} diff --git a/tests/ui/return_and_then.rs b/tests/ui/return_and_then.rs index beada921a91..dcb344f142b 100644 --- a/tests/ui/return_and_then.rs +++ b/tests/ui/return_and_then.rs @@ -90,6 +90,75 @@ fn main() { }; None } + + #[expect(clippy::diverging_sub_expression)] + fn with_return_in_expression() -> Option<i32> { + _ = ( + return Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None }), + //~^ return_and_then + 10, + ); + } + + fn inside_if(a: bool, i: Option<u32>) -> Option<u32> { + if a { + i.and_then(|i| if i > 3 { Some(i) } else { None }) + //~^ return_and_then + } else { + Some(42) + } + } + + fn inside_match(a: u32, i: Option<u32>) -> Option<u32> { + match a { + 1 | 2 => i.and_then(|i| if i > 3 { Some(i) } else { None }), + //~^ return_and_then + 3 | 4 => Some(42), + _ => None, + } + } + + fn inside_match_and_block_and_if(a: u32, i: Option<u32>) -> Option<u32> { + match a { + 1 | 2 => { + let a = a * 3; + if a.is_multiple_of(2) { + i.and_then(|i| if i > 3 { Some(i) } else { None }) + //~^ return_and_then + } else { + Some(10) + } + }, + 3 | 4 => Some(42), + _ => None, + } + } + + #[expect(clippy::never_loop)] + fn with_break(i: Option<u32>) -> Option<u32> { + match i { + Some(1) => loop { + break i.and_then(|i| if i > 3 { Some(i) } else { None }); + //~^ return_and_then + }, + Some(2) => 'foo: loop { + loop { + break 'foo i.and_then(|i| if i > 3 { Some(i) } else { None }); + //~^ return_and_then + } + }, + Some(3) => 'bar: { + break 'bar i.and_then(|i| if i > 3 { Some(i) } else { None }); + //~^ return_and_then + }, + Some(4) => 'baz: loop { + _ = loop { + break i.and_then(|i| if i > 3 { Some(i) } else { None }); + }; + }, + _ => None, + } + } } fn gen_option(n: i32) -> Option<i32> { @@ -115,3 +184,48 @@ mod issue14781 { Ok(()) } } + +mod issue15111 { + #[derive(Debug)] + struct EvenOdd { + even: Option<u32>, + odd: Option<u32>, + } + + impl EvenOdd { + fn new(i: Option<u32>) -> Self { + Self { + even: i.and_then(|i| if i.is_multiple_of(2) { Some(i) } else { None }), + odd: i.and_then(|i| if i.is_multiple_of(2) { None } else { Some(i) }), + } + } + } + + fn with_if_let(i: Option<u32>) -> u32 { + if let Some(x) = i.and_then(|i| if i.is_multiple_of(2) { Some(i) } else { None }) { + x + } else { + std::hint::black_box(0) + } + } + + fn main() { + let _ = EvenOdd::new(Some(2)); + } +} + +mod issue14927 { + use std::path::Path; + struct A { + pub func: fn(check: bool, a: &Path, b: Option<&Path>), + } + const MY_A: A = A { + func: |check, a, b| { + if check { + let _ = (); + } else if let Some(parent) = b.and_then(|p| p.parent()) { + let _ = (); + } + }, + }; +} diff --git a/tests/ui/return_and_then.stderr b/tests/ui/return_and_then.stderr index 5feca882860..33867ea818a 100644 --- a/tests/ui/return_and_then.stderr +++ b/tests/ui/return_and_then.stderr @@ -146,5 +146,99 @@ LL + if x.len() > 2 { Some(3) } else { None } LL ~ }; | -error: aborting due to 10 previous errors +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:97:20 + | +LL | return Some("").and_then(|x| if x.len() > 2 { Some(3) } else { None }), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ return { +LL + let x = Some("")?; +LL + if x.len() > 2 { Some(3) } else { None } +LL ~ }, + | + +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:105:13 + | +LL | i.and_then(|i| if i > 3 { Some(i) } else { None }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ let i = i?; +LL + if i > 3 { Some(i) } else { None } + | + +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:114:22 + | +LL | 1 | 2 => i.and_then(|i| if i > 3 { Some(i) } else { None }), + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ 1 | 2 => { +LL + let i = i?; +LL + if i > 3 { Some(i) } else { None } +LL ~ }, + | + +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:126:21 + | +LL | i.and_then(|i| if i > 3 { Some(i) } else { None }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ let i = i?; +LL + if i > 3 { Some(i) } else { None } + | + +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:141:23 + | +LL | break i.and_then(|i| if i > 3 { Some(i) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ break ({ +LL + let i = i?; +LL + if i > 3 { Some(i) } else { None } +LL ~ }); + | + +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:146:32 + | +LL | break 'foo i.and_then(|i| if i > 3 { Some(i) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ break 'foo ({ +LL + let i = i?; +LL + if i > 3 { Some(i) } else { None } +LL ~ }); + | + +error: use the `?` operator instead of an `and_then` call + --> tests/ui/return_and_then.rs:151:28 + | +LL | break 'bar i.and_then(|i| if i > 3 { Some(i) } else { None }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: try + | +LL ~ break 'bar ({ +LL + let i = i?; +LL + if i > 3 { Some(i) } else { None } +LL ~ }); + | + +error: aborting due to 17 previous errors diff --git a/tests/ui/same_name_method.stderr b/tests/ui/same_name_method.stderr index b2624ac4d26..bf7456d80e2 100644 --- a/tests/ui/same_name_method.stderr +++ b/tests/ui/same_name_method.stderr @@ -2,13 +2,13 @@ error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:20:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ | note: existing `foo` defined here --> tests/ui/same_name_method.rs:25:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ = note: `-D clippy::same-name-method` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::same_name_method)]` @@ -16,7 +16,7 @@ error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:35:13 | LL | fn clone() {} - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^ | note: existing `clone` defined here --> tests/ui/same_name_method.rs:31:18 @@ -28,19 +28,19 @@ error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:46:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ | note: existing `foo` defined here --> tests/ui/same_name_method.rs:51:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:61:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ | note: existing `foo` defined here --> tests/ui/same_name_method.rs:65:9 @@ -52,7 +52,7 @@ error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:74:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ | note: existing `foo` defined here --> tests/ui/same_name_method.rs:79:9 @@ -64,7 +64,7 @@ error: method's name is the same as an existing method in a trait --> tests/ui/same_name_method.rs:74:13 | LL | fn foo() {} - | ^^^^^^^^^^^ + | ^^^^^^^^ | note: existing `foo` defined here --> tests/ui/same_name_method.rs:81:9 diff --git a/tests/ui/search_is_some.rs b/tests/ui/search_is_some.rs index 4143b8bfba5..802d27449ab 100644 --- a/tests/ui/search_is_some.rs +++ b/tests/ui/search_is_some.rs @@ -87,3 +87,18 @@ fn is_none() { let _ = (0..1).find(some_closure).is_none(); //~^ search_is_some } + +#[allow(clippy::match_like_matches_macro)] +fn issue15102() { + let values = [None, Some(3)]; + let has_even = values + //~^ search_is_some + .iter() + .find(|v| match v { + Some(x) if x % 2 == 0 => true, + _ => false, + }) + .is_some(); + + println!("{has_even}"); +} diff --git a/tests/ui/search_is_some.stderr b/tests/ui/search_is_some.stderr index d9a43c8915e..d5412f90111 100644 --- a/tests/ui/search_is_some.stderr +++ b/tests/ui/search_is_some.stderr @@ -90,5 +90,20 @@ error: called `is_none()` after searching an `Iterator` with `find` LL | let _ = (0..1).find(some_closure).is_none(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `!(0..1).any(some_closure)` -error: aborting due to 8 previous errors +error: called `is_some()` after searching an `Iterator` with `find` + --> tests/ui/search_is_some.rs:94:20 + | +LL | let has_even = values + | ____________________^ +LL | | +LL | | .iter() +LL | | .find(|v| match v { +... | +LL | | }) +LL | | .is_some(); + | |__________________^ + | + = help: this is more succinctly expressed by calling `any()` + +error: aborting due to 9 previous errors diff --git a/tests/ui/search_is_some_fixable_some.fixed b/tests/ui/search_is_some_fixable_some.fixed index 42b39b33b57..c7a4422f373 100644 --- a/tests/ui/search_is_some_fixable_some.fixed +++ b/tests/ui/search_is_some_fixable_some.fixed @@ -289,3 +289,10 @@ mod issue9120 { //~^ search_is_some } } + +fn issue15102() { + let values = [None, Some(3)]; + let has_even = values.iter().any(|v| matches!(&v, Some(x) if x % 2 == 0)); + //~^ search_is_some + println!("{has_even}"); +} diff --git a/tests/ui/search_is_some_fixable_some.rs b/tests/ui/search_is_some_fixable_some.rs index ca4f4d941cb..d6b1c67c971 100644 --- a/tests/ui/search_is_some_fixable_some.rs +++ b/tests/ui/search_is_some_fixable_some.rs @@ -297,3 +297,10 @@ mod issue9120 { //~^ search_is_some } } + +fn issue15102() { + let values = [None, Some(3)]; + let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); + //~^ search_is_some + println!("{has_even}"); +} diff --git a/tests/ui/search_is_some_fixable_some.stderr b/tests/ui/search_is_some_fixable_some.stderr index 8291f48d43c..551a670d937 100644 --- a/tests/ui/search_is_some_fixable_some.stderr +++ b/tests/ui/search_is_some_fixable_some.stderr @@ -289,5 +289,11 @@ error: called `is_some()` after searching an `Iterator` with `find` LL | let _ = v.iter().find(|x: &&u32| (*arg_no_deref_dyn)(x)).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| (*arg_no_deref_dyn)(&x))` -error: aborting due to 46 previous errors +error: called `is_some()` after searching an `Iterator` with `find` + --> tests/ui/search_is_some_fixable_some.rs:303:34 + | +LL | let has_even = values.iter().find(|v| matches!(v, Some(x) if x % 2 == 0)).is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|v| matches!(&v, Some(x) if x % 2 == 0))` + +error: aborting due to 47 previous errors diff --git a/tests/ui/semicolon_inside_block.fixed b/tests/ui/semicolon_inside_block.fixed index 7eb53e733ad..7308e78aae2 100644 --- a/tests/ui/semicolon_inside_block.fixed +++ b/tests/ui/semicolon_inside_block.fixed @@ -86,3 +86,8 @@ fn main() { unit_fn_block() } + +pub fn issue15388() { + #[rustfmt::skip] + {0; 0}; +} diff --git a/tests/ui/semicolon_inside_block.rs b/tests/ui/semicolon_inside_block.rs index 9fa5b117194..467bf4d779f 100644 --- a/tests/ui/semicolon_inside_block.rs +++ b/tests/ui/semicolon_inside_block.rs @@ -86,3 +86,8 @@ fn main() { unit_fn_block() } + +pub fn issue15388() { + #[rustfmt::skip] + {0; 0}; +} diff --git a/tests/ui/semicolon_inside_block_stmt_expr_attrs.fixed b/tests/ui/semicolon_inside_block_stmt_expr_attrs.fixed new file mode 100644 index 00000000000..5b93a91da00 --- /dev/null +++ b/tests/ui/semicolon_inside_block_stmt_expr_attrs.fixed @@ -0,0 +1,11 @@ +// Test when the feature `stmt_expr_attributes` is enabled + +#![feature(stmt_expr_attributes)] +#![allow(clippy::no_effect)] +#![warn(clippy::semicolon_inside_block)] + +pub fn issue15388() { + #[rustfmt::skip] + {0; 0;} + //~^ semicolon_inside_block +} diff --git a/tests/ui/semicolon_inside_block_stmt_expr_attrs.rs b/tests/ui/semicolon_inside_block_stmt_expr_attrs.rs new file mode 100644 index 00000000000..aa2c0cb5029 --- /dev/null +++ b/tests/ui/semicolon_inside_block_stmt_expr_attrs.rs @@ -0,0 +1,11 @@ +// Test when the feature `stmt_expr_attributes` is enabled + +#![feature(stmt_expr_attributes)] +#![allow(clippy::no_effect)] +#![warn(clippy::semicolon_inside_block)] + +pub fn issue15388() { + #[rustfmt::skip] + {0; 0}; + //~^ semicolon_inside_block +} diff --git a/tests/ui/semicolon_inside_block_stmt_expr_attrs.stderr b/tests/ui/semicolon_inside_block_stmt_expr_attrs.stderr new file mode 100644 index 00000000000..5bb91915a5f --- /dev/null +++ b/tests/ui/semicolon_inside_block_stmt_expr_attrs.stderr @@ -0,0 +1,16 @@ +error: consider moving the `;` inside the block for consistent formatting + --> tests/ui/semicolon_inside_block_stmt_expr_attrs.rs:9:5 + | +LL | {0; 0}; + | ^^^^^^^ + | + = note: `-D clippy::semicolon-inside-block` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::semicolon_inside_block)]` +help: put the `;` here + | +LL - {0; 0}; +LL + {0; 0;} + | + +error: aborting due to 1 previous error + diff --git a/tests/ui/serde.stderr b/tests/ui/serde.stderr index eb6b7c6b0c3..652248e3578 100644 --- a/tests/ui/serde.stderr +++ b/tests/ui/serde.stderr @@ -5,10 +5,7 @@ LL | / fn visit_string<E>(self, _v: String) -> Result<Self::Value, E> LL | | LL | | where LL | | E: serde::de::Error, -LL | | { -LL | | unimplemented!() -LL | | } - | |_____^ + | |____________________________^ | = note: `-D clippy::serde-api-misuse` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::serde_api_misuse)]` diff --git a/tests/ui/significant_drop_in_scrutinee.rs b/tests/ui/significant_drop_in_scrutinee.rs index 4f65a06680d..78fc365bd5b 100644 --- a/tests/ui/significant_drop_in_scrutinee.rs +++ b/tests/ui/significant_drop_in_scrutinee.rs @@ -191,7 +191,7 @@ struct CounterWrapper<'a> { } impl<'a> CounterWrapper<'a> { - fn new(counter: &Counter) -> CounterWrapper { + fn new(counter: &Counter) -> CounterWrapper<'_> { counter.i.fetch_add(1, Ordering::Relaxed); CounterWrapper { counter } } @@ -204,7 +204,7 @@ impl<'a> Drop for CounterWrapper<'a> { } impl Counter { - fn temp_increment(&self) -> Vec<CounterWrapper> { + fn temp_increment(&self) -> Vec<CounterWrapper<'_>> { vec![CounterWrapper::new(self), CounterWrapper::new(self)] } } @@ -480,7 +480,7 @@ impl StateWithBoxedMutexGuard { fn new() -> StateWithBoxedMutexGuard { StateWithBoxedMutexGuard { u: Mutex::new(42) } } - fn lock(&self) -> Box<MutexGuard<u64>> { + fn lock(&self) -> Box<MutexGuard<'_, u64>> { Box::new(self.u.lock().unwrap()) } } @@ -507,7 +507,7 @@ impl StateStringWithBoxedMutexGuard { s: Mutex::new("A String".to_owned()), } } - fn lock(&self) -> Box<MutexGuard<String>> { + fn lock(&self) -> Box<MutexGuard<'_, String>> { Box::new(self.s.lock().unwrap()) } } @@ -686,11 +686,11 @@ struct Guard<'a, T>(MutexGuard<'a, T>); struct Ref<'a, T>(&'a T); impl<'a, T> Guard<'a, T> { - fn guard(&self) -> &MutexGuard<T> { + fn guard(&self) -> &MutexGuard<'_, T> { &self.0 } - fn guard_ref(&self) -> Ref<MutexGuard<T>> { + fn guard_ref(&self) -> Ref<'_, MutexGuard<'_, T>> { Ref(&self.0) } diff --git a/tests/ui/similar_names.rs b/tests/ui/similar_names.rs index 69b6ab6220b..55a141209f0 100644 --- a/tests/ui/similar_names.rs +++ b/tests/ui/similar_names.rs @@ -89,6 +89,10 @@ fn main() { let iter: i32; let item: i32; + + // 3 letter names are allowed to be similar + let kta: i32; + let ktv: i32; } fn foo() { diff --git a/tests/ui/similar_names.stderr b/tests/ui/similar_names.stderr index 8d722fb8b56..c226f73d4db 100644 --- a/tests/ui/similar_names.stderr +++ b/tests/ui/similar_names.stderr @@ -49,13 +49,13 @@ LL | let parser: i32; | ^^^^^^ error: binding's name is too similar to existing binding - --> tests/ui/similar_names.rs:98:16 + --> tests/ui/similar_names.rs:102:16 | LL | bpple: sprang, | ^^^^^^ | note: existing binding defined here - --> tests/ui/similar_names.rs:97:16 + --> tests/ui/similar_names.rs:101:16 | LL | apple: spring, | ^^^^^^ diff --git a/tests/ui/single_match_else_deref_patterns.fixed b/tests/ui/single_match_else_deref_patterns.fixed new file mode 100644 index 00000000000..7a9f8063096 --- /dev/null +++ b/tests/ui/single_match_else_deref_patterns.fixed @@ -0,0 +1,53 @@ +#![feature(deref_patterns)] +#![allow( + incomplete_features, + clippy::eq_op, + clippy::op_ref, + clippy::deref_addrof, + clippy::borrow_deref_ref, + clippy::needless_if +)] +#![deny(clippy::single_match_else)] + +fn string() { + if *"" == *"" {} + + if *&*&*&*"" == *"" {} + + if ***&&"" == *"" {} + + if *&*&*"" == *"" {} + + if **&&*"" == *"" {} +} + +fn int() { + if &&&1 == &&&2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else + if &&1 == &&2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else + if &&1 == &&2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else + if &1 == &2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else + if &1 == &2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else + if 1 == 2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else + if 1 == 2 { unreachable!() } else { + // ok + } + //~^^^^^^ single_match_else +} diff --git a/tests/ui/single_match_else_deref_patterns.rs b/tests/ui/single_match_else_deref_patterns.rs new file mode 100644 index 00000000000..ef19c7cbde2 --- /dev/null +++ b/tests/ui/single_match_else_deref_patterns.rs @@ -0,0 +1,94 @@ +#![feature(deref_patterns)] +#![allow( + incomplete_features, + clippy::eq_op, + clippy::op_ref, + clippy::deref_addrof, + clippy::borrow_deref_ref, + clippy::needless_if +)] +#![deny(clippy::single_match_else)] + +fn string() { + match *"" { + //~^ single_match + "" => {}, + _ => {}, + } + + match *&*&*&*"" { + //~^ single_match + "" => {}, + _ => {}, + } + + match ***&&"" { + //~^ single_match + "" => {}, + _ => {}, + } + + match *&*&*"" { + //~^ single_match + "" => {}, + _ => {}, + } + + match **&&*"" { + //~^ single_match + "" => {}, + _ => {}, + } +} + +fn int() { + match &&&1 { + &&&2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else + match &&&1 { + &&2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else + match &&1 { + &&2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else + match &&&1 { + &2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else + match &&1 { + &2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else + match &&&1 { + 2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else + match &&1 { + 2 => unreachable!(), + _ => { + // ok + }, + } + //~^^^^^^ single_match_else +} diff --git a/tests/ui/single_match_else_deref_patterns.stderr b/tests/ui/single_match_else_deref_patterns.stderr new file mode 100644 index 00000000000..a47df55459b --- /dev/null +++ b/tests/ui/single_match_else_deref_patterns.stderr @@ -0,0 +1,188 @@ +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:13:5 + | +LL | / match *"" { +LL | | +LL | | "" => {}, +LL | | _ => {}, +LL | | } + | |_____^ help: try: `if *"" == *"" {}` + | + = note: you might want to preserve the comments from inside the `match` + = note: `-D clippy::single-match` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::single_match)]` + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:19:5 + | +LL | / match *&*&*&*"" { +LL | | +LL | | "" => {}, +LL | | _ => {}, +LL | | } + | |_____^ help: try: `if *&*&*&*"" == *"" {}` + | + = note: you might want to preserve the comments from inside the `match` + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:25:5 + | +LL | / match ***&&"" { +LL | | +LL | | "" => {}, +LL | | _ => {}, +LL | | } + | |_____^ help: try: `if ***&&"" == *"" {}` + | + = note: you might want to preserve the comments from inside the `match` + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:31:5 + | +LL | / match *&*&*"" { +LL | | +LL | | "" => {}, +LL | | _ => {}, +LL | | } + | |_____^ help: try: `if *&*&*"" == *"" {}` + | + = note: you might want to preserve the comments from inside the `match` + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:37:5 + | +LL | / match **&&*"" { +LL | | +LL | | "" => {}, +LL | | _ => {}, +LL | | } + | |_____^ help: try: `if **&&*"" == *"" {}` + | + = note: you might want to preserve the comments from inside the `match` + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:45:5 + | +LL | / match &&&1 { +LL | | &&&2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +note: the lint level is defined here + --> tests/ui/single_match_else_deref_patterns.rs:10:9 + | +LL | #![deny(clippy::single_match_else)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +help: try + | +LL ~ if &&&1 == &&&2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:52:5 + | +LL | / match &&&1 { +LL | | &&2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +help: try + | +LL ~ if &&1 == &&2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:59:5 + | +LL | / match &&1 { +LL | | &&2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +help: try + | +LL ~ if &&1 == &&2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:66:5 + | +LL | / match &&&1 { +LL | | &2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +help: try + | +LL ~ if &1 == &2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:73:5 + | +LL | / match &&1 { +LL | | &2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +help: try + | +LL ~ if &1 == &2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:80:5 + | +LL | / match &&&1 { +LL | | 2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +help: try + | +LL ~ if 1 == 2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: you seem to be trying to use `match` for an equality check. Consider using `if` + --> tests/ui/single_match_else_deref_patterns.rs:87:5 + | +LL | / match &&1 { +LL | | 2 => unreachable!(), +LL | | _ => { +... | +LL | | } + | |_____^ + | +help: try + | +LL ~ if 1 == 2 { unreachable!() } else { +LL + // ok +LL + } + | + +error: aborting due to 12 previous errors + diff --git a/tests/ui/single_range_in_vec_init.rs b/tests/ui/single_range_in_vec_init.rs index 25884450b08..0888019e101 100644 --- a/tests/ui/single_range_in_vec_init.rs +++ b/tests/ui/single_range_in_vec_init.rs @@ -2,7 +2,6 @@ //@no-rustfix: overlapping suggestions #![allow(clippy::no_effect, clippy::unnecessary_operation, clippy::useless_vec, unused)] #![warn(clippy::single_range_in_vec_init)] -#![feature(generic_arg_infer)] #[macro_use] extern crate proc_macros; diff --git a/tests/ui/single_range_in_vec_init.stderr b/tests/ui/single_range_in_vec_init.stderr index a99127a7606..b21338e38a3 100644 --- a/tests/ui/single_range_in_vec_init.stderr +++ b/tests/ui/single_range_in_vec_init.stderr @@ -1,5 +1,5 @@ error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:26:5 + --> tests/ui/single_range_in_vec_init.rs:25:5 | LL | [0..200]; | ^^^^^^^^ @@ -18,7 +18,7 @@ LL + [0; 200]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:28:5 + --> tests/ui/single_range_in_vec_init.rs:27:5 | LL | vec![0..200]; | ^^^^^^^^^^^^ @@ -35,7 +35,7 @@ LL + vec![0; 200]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:30:5 + --> tests/ui/single_range_in_vec_init.rs:29:5 | LL | [0u8..200]; | ^^^^^^^^^^ @@ -52,7 +52,7 @@ LL + [0u8; 200]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:32:5 + --> tests/ui/single_range_in_vec_init.rs:31:5 | LL | [0usize..200]; | ^^^^^^^^^^^^^ @@ -69,7 +69,7 @@ LL + [0usize; 200]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:34:5 + --> tests/ui/single_range_in_vec_init.rs:33:5 | LL | [0..200usize]; | ^^^^^^^^^^^^^ @@ -86,7 +86,7 @@ LL + [0; 200usize]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:36:5 + --> tests/ui/single_range_in_vec_init.rs:35:5 | LL | vec![0u8..200]; | ^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL + vec![0u8; 200]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:38:5 + --> tests/ui/single_range_in_vec_init.rs:37:5 | LL | vec![0usize..200]; | ^^^^^^^^^^^^^^^^^ @@ -120,7 +120,7 @@ LL + vec![0usize; 200]; | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:40:5 + --> tests/ui/single_range_in_vec_init.rs:39:5 | LL | vec![0..200usize]; | ^^^^^^^^^^^^^^^^^ @@ -137,7 +137,7 @@ LL + vec![0; 200usize]; | error: an array of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:43:5 + --> tests/ui/single_range_in_vec_init.rs:42:5 | LL | [0..200isize]; | ^^^^^^^^^^^^^ @@ -149,7 +149,7 @@ LL + (0..200isize).collect::<std::vec::Vec<isize>>(); | error: a `Vec` of `Range` that is only one element - --> tests/ui/single_range_in_vec_init.rs:45:5 + --> tests/ui/single_range_in_vec_init.rs:44:5 | LL | vec![0..200isize]; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/std_instead_of_core.fixed b/tests/ui/std_instead_of_core.fixed index ab2e801eee2..603ab0accb0 100644 --- a/tests/ui/std_instead_of_core.fixed +++ b/tests/ui/std_instead_of_core.fixed @@ -8,7 +8,6 @@ extern crate alloc; #[macro_use] extern crate proc_macro_derive; -#[warn(clippy::std_instead_of_core)] fn std_instead_of_core() { // Regular import use core::hash::Hasher; diff --git a/tests/ui/std_instead_of_core.rs b/tests/ui/std_instead_of_core.rs index f760b3561ae..b6d4abad9f8 100644 --- a/tests/ui/std_instead_of_core.rs +++ b/tests/ui/std_instead_of_core.rs @@ -8,7 +8,6 @@ extern crate alloc; #[macro_use] extern crate proc_macro_derive; -#[warn(clippy::std_instead_of_core)] fn std_instead_of_core() { // Regular import use std::hash::Hasher; diff --git a/tests/ui/std_instead_of_core.stderr b/tests/ui/std_instead_of_core.stderr index 45d60d235ce..a5f8fbbe37c 100644 --- a/tests/ui/std_instead_of_core.stderr +++ b/tests/ui/std_instead_of_core.stderr @@ -1,5 +1,5 @@ error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:14:9 + --> tests/ui/std_instead_of_core.rs:13:9 | LL | use std::hash::Hasher; | ^^^ help: consider importing the item from `core`: `core` @@ -8,61 +8,61 @@ LL | use std::hash::Hasher; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:17:11 + --> tests/ui/std_instead_of_core.rs:16:11 | LL | use ::std::hash::Hash; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:23:9 + --> tests/ui/std_instead_of_core.rs:22:9 | LL | use std::fmt::{Debug, Result}; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:28:9 + --> tests/ui/std_instead_of_core.rs:27:9 | LL | use std::{ | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:35:15 + --> tests/ui/std_instead_of_core.rs:34:15 | LL | let ptr = std::ptr::null::<u32>(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:37:21 + --> tests/ui/std_instead_of_core.rs:36:21 | LL | let ptr_mut = ::std::ptr::null_mut::<usize>(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:41:16 + --> tests/ui/std_instead_of_core.rs:40:16 | LL | let cell = std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:43:27 + --> tests/ui/std_instead_of_core.rs:42:27 | LL | let cell_absolute = ::std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:48:9 + --> tests/ui/std_instead_of_core.rs:47:9 | LL | use std::error::Error; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:52:9 + --> tests/ui/std_instead_of_core.rs:51:9 | LL | use std::iter::Iterator; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:59:9 + --> tests/ui/std_instead_of_core.rs:58:9 | LL | use std::vec; | ^^^ help: consider importing the item from `alloc`: `alloc` @@ -71,13 +71,13 @@ LL | use std::vec; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:61:9 + --> tests/ui/std_instead_of_core.rs:60:9 | LL | use std::vec::Vec; | ^^^ help: consider importing the item from `alloc`: `alloc` error: used import from `alloc` instead of `core` - --> tests/ui/std_instead_of_core.rs:67:9 + --> tests/ui/std_instead_of_core.rs:66:9 | LL | use alloc::slice::from_ref; | ^^^^^ help: consider importing the item from `core`: `core` @@ -86,13 +86,13 @@ LL | use alloc::slice::from_ref; = help: to override `-D warnings` add `#[allow(clippy::alloc_instead_of_core)]` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:82:9 + --> tests/ui/std_instead_of_core.rs:81:9 | LL | std::intrinsics::copy(a, b, 1); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:91:17 + --> tests/ui/std_instead_of_core.rs:90:17 | LL | fn msrv_1_77(_: std::net::IpAddr) {} | ^^^ help: consider importing the item from `core`: `core` diff --git a/tests/ui/std_instead_of_core_unfixable.rs b/tests/ui/std_instead_of_core_unfixable.rs new file mode 100644 index 00000000000..957f472a454 --- /dev/null +++ b/tests/ui/std_instead_of_core_unfixable.rs @@ -0,0 +1,18 @@ +//@no-rustfix + +#![warn(clippy::std_instead_of_core)] +#![warn(clippy::std_instead_of_alloc)] +#![allow(unused_imports)] + +#[rustfmt::skip] +fn issue14982() { + use std::{collections::HashMap, hash::Hash}; + //~^ std_instead_of_core +} + +#[rustfmt::skip] +fn issue15143() { + use std::{error::Error, vec::Vec, fs::File}; + //~^ std_instead_of_core + //~| std_instead_of_alloc +} diff --git a/tests/ui/std_instead_of_core_unfixable.stderr b/tests/ui/std_instead_of_core_unfixable.stderr new file mode 100644 index 00000000000..0cdec56c992 --- /dev/null +++ b/tests/ui/std_instead_of_core_unfixable.stderr @@ -0,0 +1,30 @@ +error: used import from `std` instead of `core` + --> tests/ui/std_instead_of_core_unfixable.rs:9:43 + | +LL | use std::{collections::HashMap, hash::Hash}; + | ^^^^ + | + = help: consider importing the item from `core` + = note: `-D clippy::std-instead-of-core` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` + +error: used import from `std` instead of `core` + --> tests/ui/std_instead_of_core_unfixable.rs:15:22 + | +LL | use std::{error::Error, vec::Vec, fs::File}; + | ^^^^^ + | + = help: consider importing the item from `core` + +error: used import from `std` instead of `alloc` + --> tests/ui/std_instead_of_core_unfixable.rs:15:34 + | +LL | use std::{error::Error, vec::Vec, fs::File}; + | ^^^ + | + = help: consider importing the item from `alloc` + = note: `-D clippy::std-instead-of-alloc` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/string_to_string.rs b/tests/ui/string_to_string.rs deleted file mode 100644 index 7c5bd8a897b..00000000000 --- a/tests/ui/string_to_string.rs +++ /dev/null @@ -1,21 +0,0 @@ -#![warn(clippy::string_to_string)] -#![allow(clippy::redundant_clone, clippy::unnecessary_literal_unwrap)] - -fn main() { - let mut message = String::from("Hello"); - let mut v = message.to_string(); - //~^ string_to_string - - let variable1 = String::new(); - let v = &variable1; - let variable2 = Some(v); - let _ = variable2.map(|x| { - println!(); - x.to_string() - }); - //~^^ string_to_string - - let x = Some(String::new()); - let _ = x.unwrap_or_else(|| v.to_string()); - //~^ string_to_string -} diff --git a/tests/ui/string_to_string.stderr b/tests/ui/string_to_string.stderr deleted file mode 100644 index 99eea06f18e..00000000000 --- a/tests/ui/string_to_string.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error: `to_string()` called on a `String` - --> tests/ui/string_to_string.rs:6:17 - | -LL | let mut v = message.to_string(); - | ^^^^^^^^^^^^^^^^^^^ - | - = help: consider using `.clone()` - = note: `-D clippy::string-to-string` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::string_to_string)]` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string.rs:14:9 - | -LL | x.to_string() - | ^^^^^^^^^^^^^ - | - = help: consider using `.clone()` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string.rs:19:33 - | -LL | let _ = x.unwrap_or_else(|| v.to_string()); - | ^^^^^^^^^^^^^ - | - = help: consider using `.clone()` - -error: aborting due to 3 previous errors - diff --git a/tests/ui/string_to_string_in_map.fixed b/tests/ui/string_to_string_in_map.fixed deleted file mode 100644 index efc085539f1..00000000000 --- a/tests/ui/string_to_string_in_map.fixed +++ /dev/null @@ -1,20 +0,0 @@ -#![deny(clippy::string_to_string)] -#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)] - -fn main() { - let variable1 = String::new(); - let v = &variable1; - let variable2 = Some(v); - let _ = variable2.cloned(); - //~^ string_to_string - let _ = variable2.cloned(); - //~^ string_to_string - #[rustfmt::skip] - let _ = variable2.cloned(); - //~^ string_to_string - - let _ = vec![String::new()].iter().cloned().collect::<Vec<_>>(); - //~^ string_to_string - let _ = vec![String::new()].iter().cloned().collect::<Vec<_>>(); - //~^ string_to_string -} diff --git a/tests/ui/string_to_string_in_map.rs b/tests/ui/string_to_string_in_map.rs deleted file mode 100644 index 5bf1d7ba5a2..00000000000 --- a/tests/ui/string_to_string_in_map.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![deny(clippy::string_to_string)] -#![allow(clippy::unnecessary_literal_unwrap, clippy::useless_vec, clippy::iter_cloned_collect)] - -fn main() { - let variable1 = String::new(); - let v = &variable1; - let variable2 = Some(v); - let _ = variable2.map(String::to_string); - //~^ string_to_string - let _ = variable2.map(|x| x.to_string()); - //~^ string_to_string - #[rustfmt::skip] - let _ = variable2.map(|x| { x.to_string() }); - //~^ string_to_string - - let _ = vec![String::new()].iter().map(String::to_string).collect::<Vec<_>>(); - //~^ string_to_string - let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::<Vec<_>>(); - //~^ string_to_string -} diff --git a/tests/ui/string_to_string_in_map.stderr b/tests/ui/string_to_string_in_map.stderr deleted file mode 100644 index 35aeed656ee..00000000000 --- a/tests/ui/string_to_string_in_map.stderr +++ /dev/null @@ -1,38 +0,0 @@ -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:8:23 - | -LL | let _ = variable2.map(String::to_string); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` - | -note: the lint level is defined here - --> tests/ui/string_to_string_in_map.rs:1:9 - | -LL | #![deny(clippy::string_to_string)] - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:10:23 - | -LL | let _ = variable2.map(|x| x.to_string()); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:13:23 - | -LL | let _ = variable2.map(|x| { x.to_string() }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:16:40 - | -LL | let _ = vec![String::new()].iter().map(String::to_string).collect::<Vec<_>>(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` - -error: `to_string()` called on a `String` - --> tests/ui/string_to_string_in_map.rs:18:40 - | -LL | let _ = vec![String::new()].iter().map(|x| x.to_string()).collect::<Vec<_>>(); - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `cloned()` - -error: aborting due to 5 previous errors - diff --git a/tests/ui/strlen_on_c_strings.fixed b/tests/ui/strlen_on_c_strings.fixed index 31ed1cf03a2..17c1b541f77 100644 --- a/tests/ui/strlen_on_c_strings.fixed +++ b/tests/ui/strlen_on_c_strings.fixed @@ -1,7 +1,5 @@ #![warn(clippy::strlen_on_c_strings)] #![allow(dead_code, clippy::manual_c_str_literals)] -#![feature(rustc_private)] -extern crate libc; #[allow(unused)] use libc::strlen; diff --git a/tests/ui/strlen_on_c_strings.rs b/tests/ui/strlen_on_c_strings.rs index 0f3798c9fd8..c641422f5df 100644 --- a/tests/ui/strlen_on_c_strings.rs +++ b/tests/ui/strlen_on_c_strings.rs @@ -1,7 +1,5 @@ #![warn(clippy::strlen_on_c_strings)] #![allow(dead_code, clippy::manual_c_str_literals)] -#![feature(rustc_private)] -extern crate libc; #[allow(unused)] use libc::strlen; diff --git a/tests/ui/strlen_on_c_strings.stderr b/tests/ui/strlen_on_c_strings.stderr index b8619fa2df3..84a93b99ee3 100644 --- a/tests/ui/strlen_on_c_strings.stderr +++ b/tests/ui/strlen_on_c_strings.stderr @@ -1,5 +1,5 @@ error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:13:13 + --> tests/ui/strlen_on_c_strings.rs:11:13 | LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstring.as_bytes().len()` @@ -8,37 +8,37 @@ LL | let _ = unsafe { libc::strlen(cstring.as_ptr()) }; = help: to override `-D warnings` add `#[allow(clippy::strlen_on_c_strings)]` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:18:13 + --> tests/ui/strlen_on_c_strings.rs:16:13 | LL | let _ = unsafe { libc::strlen(cstr.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:21:13 + --> tests/ui/strlen_on_c_strings.rs:19:13 | LL | let _ = unsafe { strlen(cstr.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `cstr.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:25:22 + --> tests/ui/strlen_on_c_strings.rs:23:22 | LL | let _ = unsafe { strlen((*pcstr).as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(*pcstr).to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:31:22 + --> tests/ui/strlen_on_c_strings.rs:29:22 | LL | let _ = unsafe { strlen(unsafe_identity(cstr).as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe_identity(cstr).to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:33:13 + --> tests/ui/strlen_on_c_strings.rs:31:13 | LL | let _ = unsafe { strlen(unsafe { unsafe_identity(cstr) }.as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unsafe { unsafe_identity(cstr) }.to_bytes().len()` error: using `libc::strlen` on a `CString` or `CStr` value - --> tests/ui/strlen_on_c_strings.rs:37:22 + --> tests/ui/strlen_on_c_strings.rs:35:22 | LL | let _ = unsafe { strlen(f(cstr).as_ptr()) }; | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `f(cstr).to_bytes().len()` diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index 28a3b551116..072e7b27b0d 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -1,6 +1,6 @@ //@aux-build:proc_macro_suspicious_else_formatting.rs -#![warn(clippy::suspicious_else_formatting)] +#![warn(clippy::suspicious_else_formatting, clippy::possible_missing_else)] #![allow( clippy::if_same_then_else, clippy::let_unit_value, @@ -20,12 +20,12 @@ fn main() { // weird `else` formatting: if foo() { } { - //~^ suspicious_else_formatting + //~^ possible_missing_else } if foo() { } if foo() { - //~^ suspicious_else_formatting + //~^ possible_missing_else } let _ = { // if as the last expression @@ -33,7 +33,7 @@ fn main() { if foo() { } if foo() { - //~^ suspicious_else_formatting + //~^ possible_missing_else } else { } @@ -42,7 +42,7 @@ fn main() { let _ = { // if in the middle of a block if foo() { } if foo() { - //~^ suspicious_else_formatting + //~^ possible_missing_else } else { } diff --git a/tests/ui/suspicious_else_formatting.stderr b/tests/ui/suspicious_else_formatting.stderr index affd20b22d9..04555c6edbd 100644 --- a/tests/ui/suspicious_else_formatting.stderr +++ b/tests/ui/suspicious_else_formatting.stderr @@ -5,8 +5,8 @@ LL | } { | ^ | = note: to remove this lint, add the missing `else` or add a new line before the next block - = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::suspicious_else_formatting)]` + = note: `-D clippy::possible-missing-else` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::possible_missing_else)]` error: this looks like an `else if` but the `else` is missing --> tests/ui/suspicious_else_formatting.rs:27:6 @@ -41,6 +41,8 @@ LL | | { | |____^ | = note: to remove this lint, remove the `else` or remove the new line between `else` and `{..}` + = note: `-D clippy::suspicious-else-formatting` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::suspicious_else_formatting)]` error: this is an `else if` but the formatting might hide it --> tests/ui/suspicious_else_formatting.rs:67:6 diff --git a/tests/ui/swap_with_temporary.fixed b/tests/ui/swap_with_temporary.fixed index 4007d998ba0..4b4b0d4aebd 100644 --- a/tests/ui/swap_with_temporary.fixed +++ b/tests/ui/swap_with_temporary.fixed @@ -72,3 +72,49 @@ fn dont_lint_those(s: &mut S, v: &mut [String], w: Option<&mut String>) { swap(&mut s.t, v.get_mut(0).unwrap()); swap(w.unwrap(), &mut s.t); } + +fn issue15166() { + use std::sync::Mutex; + + struct A { + thing: Mutex<Vec<u8>>, + } + + impl A { + fn a(&self) { + let mut new_vec = vec![42]; + // Do not lint here, as neither `new_vec` nor the result of `.lock().unwrap()` are temporaries + swap(&mut new_vec, &mut self.thing.lock().unwrap()); + for v in new_vec { + // Do something with v + } + // Here `vec![42]` is temporary though, and a proper dereference will have to be used in the fix + *self.thing.lock().unwrap() = vec![42]; + //~^ ERROR: swapping with a temporary value is inefficient + } + } +} + +fn multiple_deref() { + let mut v1 = &mut &mut &mut vec![42]; + ***v1 = vec![]; + //~^ ERROR: swapping with a temporary value is inefficient + + struct Wrapper<T: ?Sized>(T); + impl<T: ?Sized> std::ops::Deref for Wrapper<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl<T: ?Sized> std::ops::DerefMut for Wrapper<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + use std::sync::Mutex; + let mut v1 = Mutex::new(Wrapper(Wrapper(vec![42]))); + ***v1.lock().unwrap() = vec![]; + //~^ ERROR: swapping with a temporary value is inefficient +} diff --git a/tests/ui/swap_with_temporary.rs b/tests/ui/swap_with_temporary.rs index d403c086c0f..8e35e6144d9 100644 --- a/tests/ui/swap_with_temporary.rs +++ b/tests/ui/swap_with_temporary.rs @@ -72,3 +72,49 @@ fn dont_lint_those(s: &mut S, v: &mut [String], w: Option<&mut String>) { swap(&mut s.t, v.get_mut(0).unwrap()); swap(w.unwrap(), &mut s.t); } + +fn issue15166() { + use std::sync::Mutex; + + struct A { + thing: Mutex<Vec<u8>>, + } + + impl A { + fn a(&self) { + let mut new_vec = vec![42]; + // Do not lint here, as neither `new_vec` nor the result of `.lock().unwrap()` are temporaries + swap(&mut new_vec, &mut self.thing.lock().unwrap()); + for v in new_vec { + // Do something with v + } + // Here `vec![42]` is temporary though, and a proper dereference will have to be used in the fix + swap(&mut vec![42], &mut self.thing.lock().unwrap()); + //~^ ERROR: swapping with a temporary value is inefficient + } + } +} + +fn multiple_deref() { + let mut v1 = &mut &mut &mut vec![42]; + swap(&mut ***v1, &mut vec![]); + //~^ ERROR: swapping with a temporary value is inefficient + + struct Wrapper<T: ?Sized>(T); + impl<T: ?Sized> std::ops::Deref for Wrapper<T> { + type Target = T; + fn deref(&self) -> &Self::Target { + &self.0 + } + } + impl<T: ?Sized> std::ops::DerefMut for Wrapper<T> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } + } + + use std::sync::Mutex; + let mut v1 = Mutex::new(Wrapper(Wrapper(vec![42]))); + swap(&mut vec![], &mut v1.lock().unwrap()); + //~^ ERROR: swapping with a temporary value is inefficient +} diff --git a/tests/ui/swap_with_temporary.stderr b/tests/ui/swap_with_temporary.stderr index 59355771a96..5ca4fccd37a 100644 --- a/tests/ui/swap_with_temporary.stderr +++ b/tests/ui/swap_with_temporary.stderr @@ -96,5 +96,41 @@ note: this expression returns a temporary value LL | swap(mac!(refmut y), &mut func()); | ^^^^^^ -error: aborting due to 8 previous errors +error: swapping with a temporary value is inefficient + --> tests/ui/swap_with_temporary.rs:92:13 + | +LL | swap(&mut vec![42], &mut self.thing.lock().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `*self.thing.lock().unwrap() = vec![42]` + | +note: this expression returns a temporary value + --> tests/ui/swap_with_temporary.rs:92:23 + | +LL | swap(&mut vec![42], &mut self.thing.lock().unwrap()); + | ^^^^^^^^ + +error: swapping with a temporary value is inefficient + --> tests/ui/swap_with_temporary.rs:100:5 + | +LL | swap(&mut ***v1, &mut vec![]); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `***v1 = vec![]` + | +note: this expression returns a temporary value + --> tests/ui/swap_with_temporary.rs:100:27 + | +LL | swap(&mut ***v1, &mut vec![]); + | ^^^^^^ + +error: swapping with a temporary value is inefficient + --> tests/ui/swap_with_temporary.rs:118:5 + | +LL | swap(&mut vec![], &mut v1.lock().unwrap()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use assignment instead: `***v1.lock().unwrap() = vec![]` + | +note: this expression returns a temporary value + --> tests/ui/swap_with_temporary.rs:118:15 + | +LL | swap(&mut vec![], &mut v1.lock().unwrap()); + | ^^^^^^ + +error: aborting due to 11 previous errors diff --git a/tests/ui/track-diagnostics-clippy.rs b/tests/ui/track-diagnostics-clippy.rs new file mode 100644 index 00000000000..3bae23f1984 --- /dev/null +++ b/tests/ui/track-diagnostics-clippy.rs @@ -0,0 +1,23 @@ +//@compile-flags: -Z track-diagnostics +//@no-rustfix + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@normalize-stderr-test: ".rs:\d+:\d+" -> ".rs:LL:CC" +//@normalize-stderr-test: "src/tools/clippy/" -> "" + +#![warn(clippy::let_and_return, clippy::unnecessary_cast)] + +fn main() { + // Check the provenance of a lint sent through `LintContext::span_lint()` + let a = 3u32; + let b = a as u32; + //~^ unnecessary_cast + + // Check the provenance of a lint sent through `TyCtxt::node_span_lint()` + let c = { + let d = 42; + d + //~^ let_and_return + }; +} diff --git a/tests/ui/track-diagnostics-clippy.stderr b/tests/ui/track-diagnostics-clippy.stderr new file mode 100644 index 00000000000..d5533877b45 --- /dev/null +++ b/tests/ui/track-diagnostics-clippy.stderr @@ -0,0 +1,29 @@ +error: casting to the same type is unnecessary (`u32` -> `u32`) + --> tests/ui/track-diagnostics-clippy.rs:LL:CC + | +LL | let b = a as u32; + | ^^^^^^^^ help: try: `a` + | + = note: -Ztrack-diagnostics: created at clippy_lints/src/casts/unnecessary_cast.rs:LL:CC + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_cast)]` + +error: returning the result of a `let` binding from a block + --> tests/ui/track-diagnostics-clippy.rs:LL:CC + | +LL | let d = 42; + | ----------- unnecessary `let` binding +LL | d + | ^ + | + = note: -Ztrack-diagnostics: created at clippy_lints/src/returns.rs:LL:CC + = note: `-D clippy::let-and-return` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::let_and_return)]` +help: return the expression directly + | +LL ~ +LL ~ 42 + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/track-diagnostics.rs b/tests/ui/track-diagnostics.rs index 723ea23e9a6..0fbde867390 100644 --- a/tests/ui/track-diagnostics.rs +++ b/tests/ui/track-diagnostics.rs @@ -8,5 +8,6 @@ struct A; struct B; const S: A = B; //~^ ERROR: mismatched types +//~| NOTE: created at fn main() {} diff --git a/tests/ui/track-diagnostics.stderr b/tests/ui/track-diagnostics.stderr index 83451fb658d..45262ba618f 100644 --- a/tests/ui/track-diagnostics.stderr +++ b/tests/ui/track-diagnostics.stderr @@ -3,7 +3,8 @@ error[E0308]: mismatched types | LL | const S: A = B; | ^ expected `A`, found `B` --Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC + | + = note: -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs:LL:CC error: aborting due to 1 previous error diff --git a/tests/ui/trait_duplication_in_bounds.fixed b/tests/ui/trait_duplication_in_bounds.fixed index 666ff78b218..88ba5f810b4 100644 --- a/tests/ui/trait_duplication_in_bounds.fixed +++ b/tests/ui/trait_duplication_in_bounds.fixed @@ -167,11 +167,10 @@ where } // #13476 -#[const_trait] -trait ConstTrait {} -const fn const_trait_bounds_good<T: ConstTrait + ~const ConstTrait>() {} +const trait ConstTrait {} +const fn const_trait_bounds_good<T: ConstTrait + [const] ConstTrait>() {} -const fn const_trait_bounds_bad<T: ~const ConstTrait>() {} +const fn const_trait_bounds_bad<T: [const] ConstTrait>() {} //~^ trait_duplication_in_bounds fn projections<T, U, V>() diff --git a/tests/ui/trait_duplication_in_bounds.rs b/tests/ui/trait_duplication_in_bounds.rs index a1a86fe058e..19a4e70e294 100644 --- a/tests/ui/trait_duplication_in_bounds.rs +++ b/tests/ui/trait_duplication_in_bounds.rs @@ -167,11 +167,10 @@ where } // #13476 -#[const_trait] -trait ConstTrait {} -const fn const_trait_bounds_good<T: ConstTrait + ~const ConstTrait>() {} +const trait ConstTrait {} +const fn const_trait_bounds_good<T: ConstTrait + [const] ConstTrait>() {} -const fn const_trait_bounds_bad<T: ~const ConstTrait + ~const ConstTrait>() {} +const fn const_trait_bounds_bad<T: [const] ConstTrait + [const] ConstTrait>() {} //~^ trait_duplication_in_bounds fn projections<T, U, V>() diff --git a/tests/ui/trait_duplication_in_bounds.stderr b/tests/ui/trait_duplication_in_bounds.stderr index d76b4e45848..a56a683de97 100644 --- a/tests/ui/trait_duplication_in_bounds.stderr +++ b/tests/ui/trait_duplication_in_bounds.stderr @@ -59,19 +59,19 @@ LL | fn bad_trait_object(arg0: &(dyn Any + Send + Send)) { | ^^^^^^^^^^^^^^^^^ help: try: `Any + Send` error: these bounds contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:174:36 + --> tests/ui/trait_duplication_in_bounds.rs:173:36 | -LL | const fn const_trait_bounds_bad<T: ~const ConstTrait + ~const ConstTrait>() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `~const ConstTrait` +LL | const fn const_trait_bounds_bad<T: [const] ConstTrait + [const] ConstTrait>() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `[const] ConstTrait` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:181:8 + --> tests/ui/trait_duplication_in_bounds.rs:180:8 | LL | T: IntoIterator<Item = U::Owned> + IntoIterator<Item = U::Owned>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `IntoIterator<Item = U::Owned>` error: these where clauses contain repeated elements - --> tests/ui/trait_duplication_in_bounds.rs:203:8 + --> tests/ui/trait_duplication_in_bounds.rs:202:8 | LL | T: AssocConstTrait<ASSOC = 0> + AssocConstTrait<ASSOC = 0>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `AssocConstTrait<ASSOC = 0>` diff --git a/tests/ui/trivially_copy_pass_by_ref.fixed b/tests/ui/trivially_copy_pass_by_ref.fixed index af7d82130f0..1a07f119398 100644 --- a/tests/ui/trivially_copy_pass_by_ref.fixed +++ b/tests/ui/trivially_copy_pass_by_ref.fixed @@ -41,6 +41,7 @@ fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { &foo.0 } +#[allow(mismatched_lifetime_syntaxes)] fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef { FooRef { foo } } diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index 00e11a1ea28..07b1842bbf8 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -41,6 +41,7 @@ fn good_return_explicit_lt_ref<'a>(foo: &'a Foo) -> &'a u32 { &foo.0 } +#[allow(mismatched_lifetime_syntaxes)] fn good_return_implicit_lt_struct(foo: &Foo) -> FooRef { FooRef { foo } } diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index f101ac5ccd6..36247d3fe0b 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,5 +1,5 @@ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:53:11 + --> tests/ui/trivially_copy_pass_by_ref.rs:54:11 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` @@ -11,103 +11,103 @@ LL | #![deny(clippy::trivially_copy_pass_by_ref)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:53:20 + --> tests/ui/trivially_copy_pass_by_ref.rs:54:20 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:53:29 + --> tests/ui/trivially_copy_pass_by_ref.rs:54:29 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:63:12 + --> tests/ui/trivially_copy_pass_by_ref.rs:64:12 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^^ help: consider passing by value instead: `self` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:63:22 + --> tests/ui/trivially_copy_pass_by_ref.rs:64:22 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:63:31 + --> tests/ui/trivially_copy_pass_by_ref.rs:64:31 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:63:40 + --> tests/ui/trivially_copy_pass_by_ref.rs:64:40 | LL | fn bad(&self, x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:69:16 + --> tests/ui/trivially_copy_pass_by_ref.rs:70:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:69:25 + --> tests/ui/trivially_copy_pass_by_ref.rs:70:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:69:34 + --> tests/ui/trivially_copy_pass_by_ref.rs:70:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:74:35 + --> tests/ui/trivially_copy_pass_by_ref.rs:75:35 | LL | fn bad_issue7518(self, other: &Self) {} | ^^^^^ help: consider passing by value instead: `Self` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:87:16 + --> tests/ui/trivially_copy_pass_by_ref.rs:88:16 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:87:25 + --> tests/ui/trivially_copy_pass_by_ref.rs:88:25 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:87:34 + --> tests/ui/trivially_copy_pass_by_ref.rs:88:34 | LL | fn bad2(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `Baz` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:94:33 + --> tests/ui/trivially_copy_pass_by_ref.rs:95:33 | LL | fn trait_method(&self, foo: &Foo); | ^^^^ help: consider passing by value instead: `Foo` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:132:21 + --> tests/ui/trivially_copy_pass_by_ref.rs:133:21 | LL | fn foo_never(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:138:15 + --> tests/ui/trivially_copy_pass_by_ref.rs:139:15 | LL | fn foo(x: &i32) { | ^^^^ help: consider passing by value instead: `i32` error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> tests/ui/trivially_copy_pass_by_ref.rs:164:36 + --> tests/ui/trivially_copy_pass_by_ref.rs:165:36 | LL | fn unrelated_lifetimes<'a, 'b>(_x: &'a u32, y: &'b u32) -> &'b u32 { | ^^^^^^^ help: consider passing by value instead: `u32` diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index 22a6a26dab6..4208efad677 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -151,3 +151,27 @@ fn main() { bad(); ok(); } + +fn issue14857() { + let fn_take_unit = |_: ()| {}; + fn some_other_fn(_: &i32) {} + + macro_rules! mac { + (def) => { + Default::default() + }; + (func $f:expr) => { + $f() + }; + (nonempty_block $e:expr) => {{ + some_other_fn(&$e); + $e + }}; + } + fn_take_unit(mac!(def)); + //~^ unit_arg + fn_take_unit(mac!(func Default::default)); + //~^ unit_arg + fn_take_unit(mac!(nonempty_block Default::default())); + //~^ unit_arg +} diff --git a/tests/ui/unit_arg.stderr b/tests/ui/unit_arg.stderr index 6c333d9792d..0dcfb02b9fa 100644 --- a/tests/ui/unit_arg.stderr +++ b/tests/ui/unit_arg.stderr @@ -199,5 +199,26 @@ LL ~ foo(1); LL + Some(()) | -error: aborting due to 10 previous errors +error: passing a unit value to a function + --> tests/ui/unit_arg.rs:171:5 + | +LL | fn_take_unit(mac!(def)); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + +error: passing a unit value to a function + --> tests/ui/unit_arg.rs:173:5 + | +LL | fn_take_unit(mac!(func Default::default)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + +error: passing a unit value to a function + --> tests/ui/unit_arg.rs:175:5 + | +LL | fn_take_unit(mac!(nonempty_block Default::default())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + +error: aborting due to 13 previous errors diff --git a/tests/ui/unit_arg_empty_blocks.fixed b/tests/ui/unit_arg_empty_blocks.fixed deleted file mode 100644 index b045a33608d..00000000000 --- a/tests/ui/unit_arg_empty_blocks.fixed +++ /dev/null @@ -1,34 +0,0 @@ -#![warn(clippy::unit_arg)] -#![allow(unused_must_use, unused_variables)] -#![allow(clippy::no_effect, clippy::uninlined_format_args)] - -use std::fmt::Debug; - -fn foo<T: Debug>(t: T) { - println!("{:?}", t); -} - -fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) { - println!("{:?}, {:?}, {:?}", t1, t2, t3); -} - -fn bad() { - foo(()); - //~^ unit_arg - foo3((), 2, 2); - //~^ unit_arg - foo(0); - taking_two_units((), ()); - //~^ unit_arg - foo(0); - foo(1); - taking_three_units((), (), ()); - //~^ unit_arg -} - -fn taking_two_units(a: (), b: ()) {} -fn taking_three_units(a: (), b: (), c: ()) {} - -fn main() { - bad(); -} diff --git a/tests/ui/unit_arg_empty_blocks.rs b/tests/ui/unit_arg_empty_blocks.rs deleted file mode 100644 index ab305913f3f..00000000000 --- a/tests/ui/unit_arg_empty_blocks.rs +++ /dev/null @@ -1,31 +0,0 @@ -#![warn(clippy::unit_arg)] -#![allow(unused_must_use, unused_variables)] -#![allow(clippy::no_effect, clippy::uninlined_format_args)] - -use std::fmt::Debug; - -fn foo<T: Debug>(t: T) { - println!("{:?}", t); -} - -fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) { - println!("{:?}, {:?}, {:?}", t1, t2, t3); -} - -fn bad() { - foo({}); - //~^ unit_arg - foo3({}, 2, 2); - //~^ unit_arg - taking_two_units({}, foo(0)); - //~^ unit_arg - taking_three_units({}, foo(0), foo(1)); - //~^ unit_arg -} - -fn taking_two_units(a: (), b: ()) {} -fn taking_three_units(a: (), b: (), c: ()) {} - -fn main() { - bad(); -} diff --git a/tests/ui/unit_arg_empty_blocks.stderr b/tests/ui/unit_arg_empty_blocks.stderr deleted file mode 100644 index 2c686d58ecc..00000000000 --- a/tests/ui/unit_arg_empty_blocks.stderr +++ /dev/null @@ -1,46 +0,0 @@ -error: passing a unit value to a function - --> tests/ui/unit_arg_empty_blocks.rs:16:5 - | -LL | foo({}); - | ^^^^--^ - | | - | help: use a unit literal instead: `()` - | - = note: `-D clippy::unit-arg` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::unit_arg)]` - -error: passing a unit value to a function - --> tests/ui/unit_arg_empty_blocks.rs:18:5 - | -LL | foo3({}, 2, 2); - | ^^^^^--^^^^^^^ - | | - | help: use a unit literal instead: `()` - -error: passing unit values to a function - --> tests/ui/unit_arg_empty_blocks.rs:20:5 - | -LL | taking_two_units({}, foo(0)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: move the expression in front of the call and replace it with the unit literal `()` - | -LL ~ foo(0); -LL ~ taking_two_units((), ()); - | - -error: passing unit values to a function - --> tests/ui/unit_arg_empty_blocks.rs:22:5 - | -LL | taking_three_units({}, foo(0), foo(1)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: move the expressions in front of the call and replace them with the unit literal `()` - | -LL ~ foo(0); -LL + foo(1); -LL ~ taking_three_units((), (), ()); - | - -error: aborting due to 4 previous errors - diff --git a/tests/ui/unit_arg_fixable.fixed b/tests/ui/unit_arg_fixable.fixed new file mode 100644 index 00000000000..03353a14081 --- /dev/null +++ b/tests/ui/unit_arg_fixable.fixed @@ -0,0 +1,78 @@ +#![warn(clippy::unit_arg)] +#![allow(unused_must_use, unused_variables)] +#![allow(clippy::no_effect, clippy::uninlined_format_args)] + +use std::fmt::Debug; + +fn foo<T: Debug>(t: T) { + println!("{:?}", t); +} + +fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) { + println!("{:?}, {:?}, {:?}", t1, t2, t3); +} + +fn bad() { + foo(()); + //~^ unit_arg + foo3((), 2, 2); + //~^ unit_arg + foo(0); + taking_two_units((), ()); + //~^ unit_arg + foo(0); + foo(1); + taking_three_units((), (), ()); + //~^ unit_arg +} + +fn taking_two_units(a: (), b: ()) {} +fn taking_three_units(a: (), b: (), c: ()) {} + +fn main() { + bad(); +} + +fn issue14857() { + let fn_take_unit = |_: ()| {}; + fn_take_unit(()); + //~^ unit_arg + + fn some_other_fn(_: &i32) {} + + macro_rules! another_mac { + () => { + some_other_fn(&Default::default()) + }; + ($e:expr) => { + some_other_fn(&$e) + }; + } + + another_mac!(); + fn_take_unit(()); + //~^ unit_arg + another_mac!(1); + fn_take_unit(()); + //~^ unit_arg + + macro_rules! mac { + (nondef $e:expr) => { + $e + }; + (empty_block) => {{}}; + } + fn_take_unit(mac!(nondef ())); + //~^ unit_arg + mac!(empty_block); + fn_take_unit(()); + //~^ unit_arg + + fn def<T: Default>() -> T { + Default::default() + } + + let _: () = def(); + fn_take_unit(()); + //~^ unit_arg +} diff --git a/tests/ui/unit_arg_fixable.rs b/tests/ui/unit_arg_fixable.rs new file mode 100644 index 00000000000..03fd96efdf9 --- /dev/null +++ b/tests/ui/unit_arg_fixable.rs @@ -0,0 +1,71 @@ +#![warn(clippy::unit_arg)] +#![allow(unused_must_use, unused_variables)] +#![allow(clippy::no_effect, clippy::uninlined_format_args)] + +use std::fmt::Debug; + +fn foo<T: Debug>(t: T) { + println!("{:?}", t); +} + +fn foo3<T1: Debug, T2: Debug, T3: Debug>(t1: T1, t2: T2, t3: T3) { + println!("{:?}, {:?}, {:?}", t1, t2, t3); +} + +fn bad() { + foo({}); + //~^ unit_arg + foo3({}, 2, 2); + //~^ unit_arg + taking_two_units({}, foo(0)); + //~^ unit_arg + taking_three_units({}, foo(0), foo(1)); + //~^ unit_arg +} + +fn taking_two_units(a: (), b: ()) {} +fn taking_three_units(a: (), b: (), c: ()) {} + +fn main() { + bad(); +} + +fn issue14857() { + let fn_take_unit = |_: ()| {}; + fn_take_unit(Default::default()); + //~^ unit_arg + + fn some_other_fn(_: &i32) {} + + macro_rules! another_mac { + () => { + some_other_fn(&Default::default()) + }; + ($e:expr) => { + some_other_fn(&$e) + }; + } + + fn_take_unit(another_mac!()); + //~^ unit_arg + fn_take_unit(another_mac!(1)); + //~^ unit_arg + + macro_rules! mac { + (nondef $e:expr) => { + $e + }; + (empty_block) => {{}}; + } + fn_take_unit(mac!(nondef Default::default())); + //~^ unit_arg + fn_take_unit(mac!(empty_block)); + //~^ unit_arg + + fn def<T: Default>() -> T { + Default::default() + } + + fn_take_unit(def()); + //~^ unit_arg +} diff --git a/tests/ui/unit_arg_fixable.stderr b/tests/ui/unit_arg_fixable.stderr new file mode 100644 index 00000000000..ccd5aa8322f --- /dev/null +++ b/tests/ui/unit_arg_fixable.stderr @@ -0,0 +1,110 @@ +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:16:5 + | +LL | foo({}); + | ^^^^--^ + | | + | help: use a unit literal instead: `()` + | + = note: `-D clippy::unit-arg` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unit_arg)]` + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:18:5 + | +LL | foo3({}, 2, 2); + | ^^^^^--^^^^^^^ + | | + | help: use a unit literal instead: `()` + +error: passing unit values to a function + --> tests/ui/unit_arg_fixable.rs:20:5 + | +LL | taking_two_units({}, foo(0)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expression in front of the call and replace it with the unit literal `()` + | +LL ~ foo(0); +LL ~ taking_two_units((), ()); + | + +error: passing unit values to a function + --> tests/ui/unit_arg_fixable.rs:22:5 + | +LL | taking_three_units({}, foo(0), foo(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expressions in front of the call and replace them with the unit literal `()` + | +LL ~ foo(0); +LL + foo(1); +LL ~ taking_three_units((), (), ()); + | + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:35:5 + | +LL | fn_take_unit(Default::default()); + | ^^^^^^^^^^^^^------------------^ + | | + | help: use a unit literal instead: `()` + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:49:5 + | +LL | fn_take_unit(another_mac!()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expression in front of the call and replace it with the unit literal `()` + | +LL ~ another_mac!(); +LL ~ fn_take_unit(()); + | + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:51:5 + | +LL | fn_take_unit(another_mac!(1)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expression in front of the call and replace it with the unit literal `()` + | +LL ~ another_mac!(1); +LL ~ fn_take_unit(()); + | + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:60:5 + | +LL | fn_take_unit(mac!(nondef Default::default())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^------------------^^ + | | + | help: use a unit literal instead: `()` + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:62:5 + | +LL | fn_take_unit(mac!(empty_block)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: move the expression in front of the call and replace it with the unit literal `()` + | +LL ~ mac!(empty_block); +LL ~ fn_take_unit(()); + | + +error: passing a unit value to a function + --> tests/ui/unit_arg_fixable.rs:69:5 + | +LL | fn_take_unit(def()); + | ^^^^^^^^^^^^^^^^^^^ + | +help: move the expression in front of the call and replace it with the unit literal `()` + | +LL ~ let _: () = def(); +LL ~ fn_take_unit(()); + | + +error: aborting due to 10 previous errors + diff --git a/tests/ui/unnecessary_clippy_cfg.rs b/tests/ui/unnecessary_clippy_cfg.rs index e7e01248dfb..65f67df7913 100644 --- a/tests/ui/unnecessary_clippy_cfg.rs +++ b/tests/ui/unnecessary_clippy_cfg.rs @@ -1,5 +1,6 @@ //@no-rustfix +#![allow(clippy::duplicated_attributes)] #![warn(clippy::unnecessary_clippy_cfg)] #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] //~^ unnecessary_clippy_cfg @@ -7,7 +8,6 @@ //~^ unnecessary_clippy_cfg #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] //~^ unnecessary_clippy_cfg -//~| duplicated_attributes #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] //~^ unnecessary_clippy_cfg @@ -17,7 +17,6 @@ //~^ unnecessary_clippy_cfg #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] //~^ unnecessary_clippy_cfg -//~| duplicated_attributes #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] //~^ unnecessary_clippy_cfg diff --git a/tests/ui/unnecessary_clippy_cfg.stderr b/tests/ui/unnecessary_clippy_cfg.stderr index f66c6894954..4f638d5c513 100644 --- a/tests/ui/unnecessary_clippy_cfg.stderr +++ b/tests/ui/unnecessary_clippy_cfg.stderr @@ -1,5 +1,5 @@ error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:4:1 + --> tests/ui/unnecessary_clippy_cfg.rs:5:1 | LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#![deny(clippy::non_minimal_cfg)]` @@ -8,7 +8,7 @@ LL | #![cfg_attr(clippy, deny(clippy::non_minimal_cfg))] = help: to override `-D warnings` add `#[allow(clippy::unnecessary_clippy_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:6:37 + --> tests/ui/unnecessary_clippy_cfg.rs:7:37 | LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] = note: write instead: `#![deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:8:37 + --> tests/ui/unnecessary_clippy_cfg.rs:9:37 | LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,46 +52,10 @@ LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] = note: write instead: `#[deny(clippy::non_minimal_cfg)]` error: no need to put clippy lints behind a `clippy` cfg - --> tests/ui/unnecessary_clippy_cfg.rs:21:1 + --> tests/ui/unnecessary_clippy_cfg.rs:20:1 | LL | #[cfg_attr(clippy, deny(clippy::non_minimal_cfg))] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `#[deny(clippy::non_minimal_cfg)]` -error: duplicated attribute - --> tests/ui/unnecessary_clippy_cfg.rs:8:26 - | -LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^ - | -note: first defined here - --> tests/ui/unnecessary_clippy_cfg.rs:6:26 - | -LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^ -help: remove this attribute - --> tests/ui/unnecessary_clippy_cfg.rs:8:26 - | -LL | #![cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^ - = note: `-D clippy::duplicated-attributes` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(clippy::duplicated_attributes)]` - -error: duplicated attribute - --> tests/ui/unnecessary_clippy_cfg.rs:18:25 - | -LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^ - | -note: first defined here - --> tests/ui/unnecessary_clippy_cfg.rs:16:25 - | -LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^ -help: remove this attribute - --> tests/ui/unnecessary_clippy_cfg.rs:18:25 - | -LL | #[cfg_attr(clippy, deny(dead_code, clippy::non_minimal_cfg))] - | ^^^^^^^^^ - -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/unnecessary_map_or.fixed b/tests/ui/unnecessary_map_or.fixed index 3c724397284..10552431d65 100644 --- a/tests/ui/unnecessary_map_or.fixed +++ b/tests/ui/unnecessary_map_or.fixed @@ -130,3 +130,33 @@ fn issue14201(a: Option<String>, b: Option<String>, s: &String) -> bool { //~^ unnecessary_map_or x && y } + +fn issue14714() { + assert!(Some("test") == Some("test")); + //~^ unnecessary_map_or + + // even though we're in a macro context, we still need to parenthesise because of the `then` + assert!((Some("test") == Some("test")).then(|| 1).is_some()); + //~^ unnecessary_map_or + + // method lints don't fire on macros + macro_rules! m { + ($x:expr) => { + // should become !($x == Some(1)) + let _ = !$x.map_or(false, |v| v == 1); + // should become $x == Some(1) + let _ = $x.map_or(false, |v| v == 1); + }; + } + m!(Some(5)); +} + +fn issue15180() { + let s = std::sync::Mutex::new(Some("foo")); + _ = s.lock().unwrap().is_some_and(|s| s == "foo"); + //~^ unnecessary_map_or + + let s = &&&&Some("foo"); + _ = s.is_some_and(|s| s == "foo"); + //~^ unnecessary_map_or +} diff --git a/tests/ui/unnecessary_map_or.rs b/tests/ui/unnecessary_map_or.rs index e734a27bada..4b406ec2998 100644 --- a/tests/ui/unnecessary_map_or.rs +++ b/tests/ui/unnecessary_map_or.rs @@ -134,3 +134,33 @@ fn issue14201(a: Option<String>, b: Option<String>, s: &String) -> bool { //~^ unnecessary_map_or x && y } + +fn issue14714() { + assert!(Some("test").map_or(false, |x| x == "test")); + //~^ unnecessary_map_or + + // even though we're in a macro context, we still need to parenthesise because of the `then` + assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some()); + //~^ unnecessary_map_or + + // method lints don't fire on macros + macro_rules! m { + ($x:expr) => { + // should become !($x == Some(1)) + let _ = !$x.map_or(false, |v| v == 1); + // should become $x == Some(1) + let _ = $x.map_or(false, |v| v == 1); + }; + } + m!(Some(5)); +} + +fn issue15180() { + let s = std::sync::Mutex::new(Some("foo")); + _ = s.lock().unwrap().map_or(false, |s| s == "foo"); + //~^ unnecessary_map_or + + let s = &&&&Some("foo"); + _ = s.map_or(false, |s| s == "foo"); + //~^ unnecessary_map_or +} diff --git a/tests/ui/unnecessary_map_or.stderr b/tests/ui/unnecessary_map_or.stderr index 0f9466a6a6b..b8a22346c37 100644 --- a/tests/ui/unnecessary_map_or.stderr +++ b/tests/ui/unnecessary_map_or.stderr @@ -326,5 +326,53 @@ LL - let y = b.map_or(true, |b| b == *s); LL + let y = b.is_none_or(|b| b == *s); | -error: aborting due to 26 previous errors +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:139:13 + | +LL | assert!(Some("test").map_or(false, |x| x == "test")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use a standard comparison instead + | +LL - assert!(Some("test").map_or(false, |x| x == "test")); +LL + assert!(Some("test") == Some("test")); + | + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:143:13 + | +LL | assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use a standard comparison instead + | +LL - assert!(Some("test").map_or(false, |x| x == "test").then(|| 1).is_some()); +LL + assert!((Some("test") == Some("test")).then(|| 1).is_some()); + | + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:160:9 + | +LL | _ = s.lock().unwrap().map_or(false, |s| s == "foo"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use is_some_and instead + | +LL - _ = s.lock().unwrap().map_or(false, |s| s == "foo"); +LL + _ = s.lock().unwrap().is_some_and(|s| s == "foo"); + | + +error: this `map_or` can be simplified + --> tests/ui/unnecessary_map_or.rs:164:9 + | +LL | _ = s.map_or(false, |s| s == "foo"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use is_some_and instead + | +LL - _ = s.map_or(false, |s| s == "foo"); +LL + _ = s.is_some_and(|s| s == "foo"); + | + +error: aborting due to 30 previous errors diff --git a/tests/ui/unnecessary_operation.fixed b/tests/ui/unnecessary_operation.fixed index 645b56fe95e..db5409bc491 100644 --- a/tests/ui/unnecessary_operation.fixed +++ b/tests/ui/unnecessary_operation.fixed @@ -78,25 +78,25 @@ fn main() { //~^ unnecessary_operation get_number(); //~^ unnecessary_operation - 5;get_number(); + 5; get_number(); //~^ unnecessary_operation get_number(); //~^ unnecessary_operation get_number(); //~^ unnecessary_operation - 5;6;get_number(); + 5; 6; get_number(); //~^ unnecessary_operation get_number(); //~^ unnecessary_operation get_number(); //~^ unnecessary_operation - 5;get_number(); + 5; get_number(); //~^ unnecessary_operation - 42;get_number(); + 42; get_number(); //~^ unnecessary_operation assert!([42, 55].len() > get_usize()); //~^ unnecessary_operation - 42;get_number(); + 42; get_number(); //~^ unnecessary_operation get_number(); //~^ unnecessary_operation @@ -144,3 +144,16 @@ const fn foo() { assert!([42, 55].len() > get_usize()); //~^ unnecessary_operation } + +fn issue15173() { + // No lint as `Box::new(None)` alone would be ambiguous + Box::new(None) as Box<Option<i32>>; +} + +#[expect(clippy::redundant_closure_call)] +fn issue15173_original<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) { + Box::new(move |value| { + (|_| handler.clone()())(value); + None + }) as Box<dyn Fn(i32) -> Option<i32>>; +} diff --git a/tests/ui/unnecessary_operation.rs b/tests/ui/unnecessary_operation.rs index 97e90269c5c..a3e6c6288ad 100644 --- a/tests/ui/unnecessary_operation.rs +++ b/tests/ui/unnecessary_operation.rs @@ -150,3 +150,16 @@ const fn foo() { [42, 55][get_usize()]; //~^ unnecessary_operation } + +fn issue15173() { + // No lint as `Box::new(None)` alone would be ambiguous + Box::new(None) as Box<Option<i32>>; +} + +#[expect(clippy::redundant_closure_call)] +fn issue15173_original<MsU>(handler: impl FnOnce() -> MsU + Clone + 'static) { + Box::new(move |value| { + (|_| handler.clone()())(value); + None + }) as Box<dyn Fn(i32) -> Option<i32>>; +} diff --git a/tests/ui/unnecessary_operation.stderr b/tests/ui/unnecessary_operation.stderr index 0fda1dfde19..3439ba2e33e 100644 --- a/tests/ui/unnecessary_operation.stderr +++ b/tests/ui/unnecessary_operation.stderr @@ -35,7 +35,7 @@ error: unnecessary operation --> tests/ui/unnecessary_operation.rs:81:5 | LL | 5 + get_number(); - | ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` + | ^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5; get_number();` error: unnecessary operation --> tests/ui/unnecessary_operation.rs:83:5 @@ -53,7 +53,7 @@ error: unnecessary operation --> tests/ui/unnecessary_operation.rs:87:5 | LL | (5, 6, get_number()); - | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;6;get_number();` + | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5; 6; get_number();` error: unnecessary operation --> tests/ui/unnecessary_operation.rs:89:5 @@ -71,13 +71,13 @@ error: unnecessary operation --> tests/ui/unnecessary_operation.rs:93:5 | LL | 5..get_number(); - | ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5;get_number();` + | ^^^^^^^^^^^^^^^^ help: statement can be reduced to: `5; get_number();` error: unnecessary operation --> tests/ui/unnecessary_operation.rs:95:5 | LL | [42, get_number()]; - | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` + | ^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42; get_number();` error: unnecessary operation --> tests/ui/unnecessary_operation.rs:97:5 @@ -89,7 +89,7 @@ error: unnecessary operation --> tests/ui/unnecessary_operation.rs:99:5 | LL | (42, get_number()).1; - | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42;get_number();` + | ^^^^^^^^^^^^^^^^^^^^^ help: statement can be reduced to: `42; get_number();` error: unnecessary operation --> tests/ui/unnecessary_operation.rs:101:5 diff --git a/tests/ui/unnecessary_os_str_debug_formatting.rs b/tests/ui/unnecessary_os_str_debug_formatting.rs index 6652efd9ae1..66590be3d05 100644 --- a/tests/ui/unnecessary_os_str_debug_formatting.rs +++ b/tests/ui/unnecessary_os_str_debug_formatting.rs @@ -21,3 +21,16 @@ fn main() { let _: String = format!("{:?}", os_str); //~ unnecessary_debug_formatting let _: String = format!("{:?}", os_string); //~ unnecessary_debug_formatting } + +#[clippy::msrv = "1.86"] +fn msrv_1_86() { + let os_str = OsStr::new("test"); + println!("{:?}", os_str); +} + +#[clippy::msrv = "1.87"] +fn msrv_1_87() { + let os_str = OsStr::new("test"); + println!("{:?}", os_str); + //~^ unnecessary_debug_formatting +} diff --git a/tests/ui/unnecessary_os_str_debug_formatting.stderr b/tests/ui/unnecessary_os_str_debug_formatting.stderr index 382e59b0461..f04d2d5bdc8 100644 --- a/tests/ui/unnecessary_os_str_debug_formatting.stderr +++ b/tests/ui/unnecessary_os_str_debug_formatting.stderr @@ -54,5 +54,14 @@ LL | let _: String = format!("{:?}", os_string); = help: use `Display` formatting and change this to `os_string.display()` = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed -error: aborting due to 6 previous errors +error: unnecessary `Debug` formatting in `println!` args + --> tests/ui/unnecessary_os_str_debug_formatting.rs:34:22 + | +LL | println!("{:?}", os_str); + | ^^^^^^ + | + = help: use `Display` formatting and change this to `os_str.display()` + = note: switching to `Display` formatting will change how the value is shown; escaped characters will no longer be escaped and surrounding quotes will be removed + +error: aborting due to 7 previous errors diff --git a/tests/ui/unnecessary_safety_comment.stderr b/tests/ui/unnecessary_safety_comment.stderr index b56e8b35493..732e6767c17 100644 --- a/tests/ui/unnecessary_safety_comment.stderr +++ b/tests/ui/unnecessary_safety_comment.stderr @@ -1,4 +1,4 @@ -error: constant item has unnecessary safety comment +error: constant has unnecessary safety comment --> tests/ui/unnecessary_safety_comment.rs:6:5 | LL | const CONST: u32 = 0; @@ -12,7 +12,7 @@ LL | // SAFETY: = note: `-D clippy::unnecessary-safety-comment` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_safety_comment)]` -error: static item has unnecessary safety comment +error: static has unnecessary safety comment --> tests/ui/unnecessary_safety_comment.rs:10:5 | LL | static STATIC: u32 = 0; diff --git a/tests/ui/unnecessary_semicolon.edition2021.fixed b/tests/ui/unnecessary_semicolon.edition2021.fixed index f10d804c8cc..797f1505f49 100644 --- a/tests/ui/unnecessary_semicolon.edition2021.fixed +++ b/tests/ui/unnecessary_semicolon.edition2021.fixed @@ -63,3 +63,12 @@ fn issue14100() -> bool { // cast into the `bool` function return type. if return true {}; } + +fn issue15426(x: u32) { + // removing the `;` would turn the stmt into an expr, but attrs aren't allowed on exprs + #[rustfmt::skip] + match x { + 0b00 => {} 0b01 => {} + 0b11 => {} _ => {} + }; +} diff --git a/tests/ui/unnecessary_semicolon.edition2024.fixed b/tests/ui/unnecessary_semicolon.edition2024.fixed index 32a3bb9b408..d2609cea000 100644 --- a/tests/ui/unnecessary_semicolon.edition2024.fixed +++ b/tests/ui/unnecessary_semicolon.edition2024.fixed @@ -63,3 +63,12 @@ fn issue14100() -> bool { // cast into the `bool` function return type. if return true {}; } + +fn issue15426(x: u32) { + // removing the `;` would turn the stmt into an expr, but attrs aren't allowed on exprs + #[rustfmt::skip] + match x { + 0b00 => {} 0b01 => {} + 0b11 => {} _ => {} + }; +} diff --git a/tests/ui/unnecessary_semicolon.rs b/tests/ui/unnecessary_semicolon.rs index 91b28218022..55f1ec84cb0 100644 --- a/tests/ui/unnecessary_semicolon.rs +++ b/tests/ui/unnecessary_semicolon.rs @@ -63,3 +63,12 @@ fn issue14100() -> bool { // cast into the `bool` function return type. if return true {}; } + +fn issue15426(x: u32) { + // removing the `;` would turn the stmt into an expr, but attrs aren't allowed on exprs + #[rustfmt::skip] + match x { + 0b00 => {} 0b01 => {} + 0b11 => {} _ => {} + }; +} diff --git a/tests/ui/unnecessary_sort_by.stderr b/tests/ui/unnecessary_sort_by.stderr index 9a38d3746da..a066554037f 100644 --- a/tests/ui/unnecessary_sort_by.stderr +++ b/tests/ui/unnecessary_sort_by.stderr @@ -7,7 +7,7 @@ LL | vec.sort_by(|a, b| a.cmp(b)); = note: `-D clippy::unnecessary-sort-by` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unnecessary_sort_by)]` -error: consider using `sort` +error: consider using `sort_unstable` --> tests/ui/unnecessary_sort_by.rs:14:5 | LL | vec.sort_unstable_by(|a, b| a.cmp(b)); @@ -19,7 +19,7 @@ error: consider using `sort_by_key` LL | vec.sort_by(|a, b| (a + 5).abs().cmp(&(b + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (a + 5).abs())` -error: consider using `sort_by_key` +error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:18:5 | LL | vec.sort_unstable_by(|a, b| id(-a).cmp(&id(-b))); @@ -31,7 +31,7 @@ error: consider using `sort_by_key` LL | vec.sort_by(|a, b| (b + 5).abs().cmp(&(a + 5).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|b| std::cmp::Reverse((b + 5).abs()))` -error: consider using `sort_by_key` +error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:24:5 | LL | vec.sort_unstable_by(|a, b| id(-b).cmp(&id(-a))); @@ -43,7 +43,7 @@ error: consider using `sort_by_key` LL | vec.sort_by(|a, b| (***a).abs().cmp(&(***b).abs())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec.sort_by_key(|a| (***a).abs())` -error: consider using `sort_by_key` +error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:37:5 | LL | vec.sort_unstable_by(|a, b| (***a).abs().cmp(&(***b).abs())); @@ -55,7 +55,7 @@ error: consider using `sort_by_key` LL | args.sort_by(|a, b| a.name().cmp(&b.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|a| a.name())` -error: consider using `sort_by_key` +error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:99:9 | LL | args.sort_unstable_by(|a, b| a.name().cmp(&b.name())); @@ -67,7 +67,7 @@ error: consider using `sort_by_key` LL | args.sort_by(|a, b| b.name().cmp(&a.name())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `args.sort_by_key(|b| std::cmp::Reverse(b.name()))` -error: consider using `sort_by_key` +error: consider using `sort_unstable_by_key` --> tests/ui/unnecessary_sort_by.rs:104:9 | LL | args.sort_unstable_by(|a, b| b.name().cmp(&a.name())); diff --git a/tests/ui/unnested_or_patterns.fixed b/tests/ui/unnested_or_patterns.fixed index 2081772d06b..339d4a95084 100644 --- a/tests/ui/unnested_or_patterns.fixed +++ b/tests/ui/unnested_or_patterns.fixed @@ -9,6 +9,11 @@ )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] +struct S { + x: u8, + y: u8, +} + fn main() { // Should be ignored by this lint, as nesting requires more characters. if let &0 | &2 = &0 {} @@ -45,10 +50,6 @@ fn main() { //~^ unnested_or_patterns if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} //~^ unnested_or_patterns - struct S { - x: u8, - y: u8, - } if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} //~^ unnested_or_patterns if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} @@ -77,3 +78,19 @@ mod issue9952 { fn or_in_param((x | x | x): i32) {} //~^ unnested_or_patterns } + +fn issue15219() { + struct Foo { + x: u8, + } + + // the original repro + if let Foo { x } | Foo { x } = (Foo { x: 0 }) {} + + // also works with more fields + if let S { x, y } | S { x, y } = (S { x: 0, y: 0 }) {} + + // `y` not triggering the lint doesn't stop the `x` from getting flagged + if let S { y, x: 0 | 1 } = (S { x: 0, y: 1 }) {} + //~^ unnested_or_patterns +} diff --git a/tests/ui/unnested_or_patterns.rs b/tests/ui/unnested_or_patterns.rs index 6bf8fce3661..f5c99183b0c 100644 --- a/tests/ui/unnested_or_patterns.rs +++ b/tests/ui/unnested_or_patterns.rs @@ -9,6 +9,11 @@ )] #![allow(unreachable_patterns, irrefutable_let_patterns, unused)] +struct S { + x: u8, + y: u8, +} + fn main() { // Should be ignored by this lint, as nesting requires more characters. if let &0 | &2 = &0 {} @@ -45,10 +50,6 @@ fn main() { //~^ unnested_or_patterns if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} //~^ unnested_or_patterns - struct S { - x: u8, - y: u8, - } if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} //~^ unnested_or_patterns if let S { x: 0, y, .. } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} @@ -77,3 +78,19 @@ mod issue9952 { fn or_in_param((x | (x | x)): i32) {} //~^ unnested_or_patterns } + +fn issue15219() { + struct Foo { + x: u8, + } + + // the original repro + if let Foo { x } | Foo { x } = (Foo { x: 0 }) {} + + // also works with more fields + if let S { x, y } | S { x, y } = (S { x: 0, y: 0 }) {} + + // `y` not triggering the lint doesn't stop the `x` from getting flagged + if let S { y, x: 0 } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + //~^ unnested_or_patterns +} diff --git a/tests/ui/unnested_or_patterns.stderr b/tests/ui/unnested_or_patterns.stderr index c805dc992b1..d2b617c322c 100644 --- a/tests/ui/unnested_or_patterns.stderr +++ b/tests/ui/unnested_or_patterns.stderr @@ -1,5 +1,5 @@ error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:16:12 + --> tests/ui/unnested_or_patterns.rs:21:12 | LL | if let box 0 | box 2 = Box::new(0) {} | ^^^^^^^^^^^^^ @@ -13,7 +13,7 @@ LL + if let box (0 | 2) = Box::new(0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:18:12 + --> tests/ui/unnested_or_patterns.rs:23:12 | LL | if let box ((0 | 1)) | box (2 | 3) | box 4 = Box::new(0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -25,7 +25,7 @@ LL + if let box (0 | 1 | 2 | 3 | 4) = Box::new(0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:21:12 + --> tests/ui/unnested_or_patterns.rs:26:12 | LL | if let Some(1) | C0 | Some(2) = None {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -37,7 +37,7 @@ LL + if let Some(1 | 2) | C0 = None {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:23:12 + --> tests/ui/unnested_or_patterns.rs:28:12 | LL | if let &mut 0 | &mut 2 = &mut 0 {} | ^^^^^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL + if let &mut (0 | 2) = &mut 0 {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:25:12 + --> tests/ui/unnested_or_patterns.rs:30:12 | LL | if let x @ 0 | x @ 2 = 0 {} | ^^^^^^^^^^^^^ @@ -61,7 +61,7 @@ LL + if let x @ (0 | 2) = 0 {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:27:12 + --> tests/ui/unnested_or_patterns.rs:32:12 | LL | if let (0, 1) | (0, 2) | (0, 3) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -73,7 +73,7 @@ LL + if let (0, 1 | 2 | 3) = (0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:29:12 + --> tests/ui/unnested_or_patterns.rs:34:12 | LL | if let (1, 0) | (2, 0) | (3, 0) = (0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +85,7 @@ LL + if let (1 | 2 | 3, 0) = (0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:31:12 + --> tests/ui/unnested_or_patterns.rs:36:12 | LL | if let (x, ..) | (x, 1) | (x, 2) = (0, 1) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -97,7 +97,7 @@ LL + if let (x, ..) | (x, 1 | 2) = (0, 1) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:33:12 + --> tests/ui/unnested_or_patterns.rs:38:12 | LL | if let [0] | [1] = [0] {} | ^^^^^^^^^ @@ -109,7 +109,7 @@ LL + if let [0 | 1] = [0] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:35:12 + --> tests/ui/unnested_or_patterns.rs:40:12 | LL | if let [x, 0] | [x, 1] = [0, 1] {} | ^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL + if let [x, 0 | 1] = [0, 1] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:37:12 + --> tests/ui/unnested_or_patterns.rs:42:12 | LL | if let [x, 0] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -133,7 +133,7 @@ LL + if let [x, 0 | 1 | 2] = [0, 1] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:39:12 + --> tests/ui/unnested_or_patterns.rs:44:12 | LL | if let [x, ..] | [x, 1] | [x, 2] = [0, 1] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -145,7 +145,7 @@ LL + if let [x, ..] | [x, 1 | 2] = [0, 1] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:42:12 + --> tests/ui/unnested_or_patterns.rs:47:12 | LL | if let TS(0, x) | TS(1, x) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^ @@ -157,7 +157,7 @@ LL + if let TS(0 | 1, x) = TS(0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:44:12 + --> tests/ui/unnested_or_patterns.rs:49:12 | LL | if let TS(1, 0) | TS(2, 0) | TS(3, 0) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -169,7 +169,7 @@ LL + if let TS(1 | 2 | 3, 0) = TS(0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:46:12 + --> tests/ui/unnested_or_patterns.rs:51:12 | LL | if let TS(x, ..) | TS(x, 1) | TS(x, 2) = TS(0, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -181,7 +181,7 @@ LL + if let TS(x, ..) | TS(x, 1 | 2) = TS(0, 0) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:52:12 + --> tests/ui/unnested_or_patterns.rs:53:12 | LL | if let S { x: 0, y } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -193,7 +193,7 @@ LL + if let S { x: 0 | 1, y } = (S { x: 0, y: 1 }) {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:64:12 + --> tests/ui/unnested_or_patterns.rs:65:12 | LL | if let [1] | [53] = [0] {} | ^^^^^^^^^^ @@ -205,7 +205,7 @@ LL + if let [1 | 53] = [0] {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:70:13 + --> tests/ui/unnested_or_patterns.rs:71:13 | LL | let (0 | (1 | _)) = 0; | ^^^^^^^^^^^^^ @@ -217,7 +217,7 @@ LL + let (0 | 1 | _) = 0; | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:73:16 + --> tests/ui/unnested_or_patterns.rs:74:16 | LL | if let (0 | (1 | _)) = 0 {} | ^^^^^^^^^^^^^ @@ -229,7 +229,7 @@ LL + if let (0 | 1 | _) = 0 {} | error: unnested or-patterns - --> tests/ui/unnested_or_patterns.rs:77:20 + --> tests/ui/unnested_or_patterns.rs:78:20 | LL | fn or_in_param((x | (x | x)): i32) {} | ^^^^^^^^^^^^^ @@ -240,5 +240,17 @@ LL - fn or_in_param((x | (x | x)): i32) {} LL + fn or_in_param((x | x | x): i32) {} | -error: aborting due to 20 previous errors +error: unnested or-patterns + --> tests/ui/unnested_or_patterns.rs:94:12 + | +LL | if let S { y, x: 0 } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: nest the patterns + | +LL - if let S { y, x: 0 } | S { y, x: 1 } = (S { x: 0, y: 1 }) {} +LL + if let S { y, x: 0 | 1 } = (S { x: 0, y: 1 }) {} + | + +error: aborting due to 21 previous errors diff --git a/tests/ui/unsafe_derive_deserialize.rs b/tests/ui/unsafe_derive_deserialize.rs index 14371bc203b..d0022f3b6d9 100644 --- a/tests/ui/unsafe_derive_deserialize.rs +++ b/tests/ui/unsafe_derive_deserialize.rs @@ -82,3 +82,32 @@ impl H { } fn main() {} + +mod issue15120 { + macro_rules! uns { + ($e:expr) => { + unsafe { $e } + }; + } + + #[derive(serde::Deserialize)] + struct Foo; + + impl Foo { + fn foo(&self) { + // Do not lint if `unsafe` comes from the `core::pin::pin!()` macro + std::pin::pin!(()); + } + } + + //~v unsafe_derive_deserialize + #[derive(serde::Deserialize)] + struct Bar; + + impl Bar { + fn bar(&self) { + // Lint if `unsafe` comes from the another macro + _ = uns!(42); + } + } +} diff --git a/tests/ui/unsafe_derive_deserialize.stderr b/tests/ui/unsafe_derive_deserialize.stderr index f2d4429f707..4b5dd6e61fc 100644 --- a/tests/ui/unsafe_derive_deserialize.stderr +++ b/tests/ui/unsafe_derive_deserialize.stderr @@ -36,5 +36,14 @@ LL | #[derive(Deserialize)] = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 4 previous errors +error: you are deriving `serde::Deserialize` on a type that has methods using `unsafe` + --> tests/ui/unsafe_derive_deserialize.rs:104:14 + | +LL | #[derive(serde::Deserialize)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider implementing `serde::Deserialize` manually. See https://serde.rs/impl-deserialize.html + = note: this error originates in the derive macro `serde::Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 5 previous errors diff --git a/tests/ui/unused_async.rs b/tests/ui/unused_async.rs index 433459253dd..7a0be825a2d 100644 --- a/tests/ui/unused_async.rs +++ b/tests/ui/unused_async.rs @@ -127,3 +127,13 @@ mod issue14704 { async fn cancel(self: Arc<Self>) {} } } + +mod issue15305 { + async fn todo_task() -> Result<(), String> { + todo!("Implement task"); + } + + async fn unimplemented_task() -> Result<(), String> { + unimplemented!("Implement task"); + } +} diff --git a/tests/ui/unused_trait_names.fixed b/tests/ui/unused_trait_names.fixed index 17e32ddfd9d..6abbed01bb0 100644 --- a/tests/ui/unused_trait_names.fixed +++ b/tests/ui/unused_trait_names.fixed @@ -200,11 +200,11 @@ fn msrv_1_33() { MyStruct.do_things(); } +// Linting inside macro expansion is no longer supported mod lint_inside_macro_expansion_bad { macro_rules! foo { () => { - use std::any::Any as _; - //~^ unused_trait_names + use std::any::Any; fn bar() { "bar".type_id(); } diff --git a/tests/ui/unused_trait_names.rs b/tests/ui/unused_trait_names.rs index 3cf8597e535..4a06f062dc3 100644 --- a/tests/ui/unused_trait_names.rs +++ b/tests/ui/unused_trait_names.rs @@ -200,11 +200,11 @@ fn msrv_1_33() { MyStruct.do_things(); } +// Linting inside macro expansion is no longer supported mod lint_inside_macro_expansion_bad { macro_rules! foo { () => { use std::any::Any; - //~^ unused_trait_names fn bar() { "bar".type_id(); } diff --git a/tests/ui/unused_trait_names.stderr b/tests/ui/unused_trait_names.stderr index 3183289d853..28067e17414 100644 --- a/tests/ui/unused_trait_names.stderr +++ b/tests/ui/unused_trait_names.stderr @@ -58,16 +58,5 @@ error: importing trait that is only used anonymously LL | use simple_trait::{MyStruct, MyTrait}; | ^^^^^^^ help: use: `MyTrait as _` -error: importing trait that is only used anonymously - --> tests/ui/unused_trait_names.rs:206:27 - | -LL | use std::any::Any; - | ^^^ help: use: `Any as _` -... -LL | foo!(); - | ------ in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 10 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/unwrap_in_result.rs b/tests/ui/unwrap_in_result.rs index 4e872c67b42..70c28fe54f3 100644 --- a/tests/ui/unwrap_in_result.rs +++ b/tests/ui/unwrap_in_result.rs @@ -1,4 +1,5 @@ #![warn(clippy::unwrap_in_result)] +#![allow(clippy::ok_expect)] struct A; @@ -20,10 +21,9 @@ impl A { // should be detected fn bad_divisible_by_3(i_str: String) -> Result<bool, String> { - //~^ unwrap_in_result - // checks whether a string represents a number divisible by 3 let i = i_str.parse::<i32>().unwrap(); + //~^ unwrap_in_result if i % 3 == 0 { Ok(true) } else { @@ -32,9 +32,8 @@ impl A { } fn example_option_expect(i_str: String) -> Option<bool> { + let i = i_str.parse::<i32>().ok().expect("not a number"); //~^ unwrap_in_result - - let i = i_str.parse::<i32>().expect("not a number"); if i % 3 == 0 { return Some(true); } @@ -42,13 +41,66 @@ impl A { } fn in_closure(a: Option<bool>) -> Option<bool> { - //~^ unwrap_in_result + // No lint inside a closure let c = || a.unwrap(); - Some(c()) + + // But lint outside + let a = c().then_some(true); + let _ = a.unwrap(); + //~^ unwrap_in_result + + None } + + const fn in_const_inside_fn() -> bool { + const A: bool = { + const fn inner(b: Option<bool>) -> Option<bool> { + Some(b.unwrap()) + //~^ unwrap_in_result + } + + // No lint inside `const` + inner(Some(true)).unwrap() + }; + A + } + + fn in_static_inside_fn() -> bool { + static A: bool = { + const fn inner(b: Option<bool>) -> Option<bool> { + Some(b.unwrap()) + //~^ unwrap_in_result + } + + // No lint inside `static` + inner(Some(true)).unwrap() + }; + A + } +} + +macro_rules! mac { + () => { + Option::unwrap(Some(3)) + }; +} + +fn type_relative_unwrap() -> Option<()> { + _ = Option::unwrap(Some(3)); + //~^ unwrap_in_result + + // Do not lint macro output + _ = mac!(); + + None } -fn main() { - A::bad_divisible_by_3("3".to_string()); - A::good_divisible_by_3("3".to_string()); +fn main() -> Result<(), ()> { + A::bad_divisible_by_3("3".to_string()).unwrap(); + //~^ unwrap_in_result + A::good_divisible_by_3("3".to_string()).unwrap(); + //~^ unwrap_in_result + Result::unwrap(A::good_divisible_by_3("3".to_string())); + //~^ unwrap_in_result + Ok(()) } diff --git a/tests/ui/unwrap_in_result.stderr b/tests/ui/unwrap_in_result.stderr index 5e3eab813e0..804b44246dc 100644 --- a/tests/ui/unwrap_in_result.stderr +++ b/tests/ui/unwrap_in_result.stderr @@ -1,55 +1,107 @@ -error: used unwrap or expect in a function that returns result or option - --> tests/ui/unwrap_in_result.rs:22:5 - | -LL | / fn bad_divisible_by_3(i_str: String) -> Result<bool, String> { -... | -LL | | } - | |_____^ - | - = help: unwrap and expect should not be used in a function that returns result or option -note: potential non-recoverable error(s) - --> tests/ui/unwrap_in_result.rs:26:17 +error: `unwrap` used in a function that returns a `Result` + --> tests/ui/unwrap_in_result.rs:25:17 | LL | let i = i_str.parse::<i32>().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: in this function signature + --> tests/ui/unwrap_in_result.rs:23:45 + | +LL | fn bad_divisible_by_3(i_str: String) -> Result<bool, String> { + | ^^^^^^^^^^^^^^^^^^^^ + = help: consider using the `?` operator or calling the `.map_err()` method = note: `-D clippy::unwrap-in-result` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::unwrap_in_result)]` -error: used unwrap or expect in a function that returns result or option - --> tests/ui/unwrap_in_result.rs:34:5 +error: `expect` used in a function that returns an `Option` + --> tests/ui/unwrap_in_result.rs:35:17 + | +LL | let i = i_str.parse::<i32>().ok().expect("not a number"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: in this function signature + --> tests/ui/unwrap_in_result.rs:34:48 + | +LL | fn example_option_expect(i_str: String) -> Option<bool> { + | ^^^^^^^^^^^^ + = help: consider using the `?` operator + +error: `unwrap` used in a function that returns an `Option` + --> tests/ui/unwrap_in_result.rs:49:17 + | +LL | let _ = a.unwrap(); + | ^^^^^^^^^^ + | +note: in this function signature + --> tests/ui/unwrap_in_result.rs:43:39 + | +LL | fn in_closure(a: Option<bool>) -> Option<bool> { + | ^^^^^^^^^^^^ + = help: consider using the `?` operator + +error: `unwrap` used in a function that returns an `Option` + --> tests/ui/unwrap_in_result.rs:58:22 | -LL | / fn example_option_expect(i_str: String) -> Option<bool> { -LL | | -LL | | -LL | | let i = i_str.parse::<i32>().expect("not a number"); -... | -LL | | None -LL | | } - | |_____^ +LL | Some(b.unwrap()) + | ^^^^^^^^^^ | - = help: unwrap and expect should not be used in a function that returns result or option -note: potential non-recoverable error(s) - --> tests/ui/unwrap_in_result.rs:37:17 +note: in this function signature + --> tests/ui/unwrap_in_result.rs:57:48 | -LL | let i = i_str.parse::<i32>().expect("not a number"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const fn inner(b: Option<bool>) -> Option<bool> { + | ^^^^^^^^^^^^ + = help: consider using the `?` operator -error: used unwrap or expect in a function that returns result or option - --> tests/ui/unwrap_in_result.rs:44:5 +error: `unwrap` used in a function that returns an `Option` + --> tests/ui/unwrap_in_result.rs:71:22 | -LL | / fn in_closure(a: Option<bool>) -> Option<bool> { -LL | | -LL | | let c = || a.unwrap(); -LL | | Some(c()) -LL | | } - | |_____^ +LL | Some(b.unwrap()) + | ^^^^^^^^^^ | - = help: unwrap and expect should not be used in a function that returns result or option -note: potential non-recoverable error(s) - --> tests/ui/unwrap_in_result.rs:46:20 +note: in this function signature + --> tests/ui/unwrap_in_result.rs:70:48 + | +LL | const fn inner(b: Option<bool>) -> Option<bool> { + | ^^^^^^^^^^^^ + = help: consider using the `?` operator + +error: `unwrap` used in a function that returns an `Option` + --> tests/ui/unwrap_in_result.rs:89:9 + | +LL | _ = Option::unwrap(Some(3)); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: in this function signature + --> tests/ui/unwrap_in_result.rs:88:30 + | +LL | fn type_relative_unwrap() -> Option<()> { + | ^^^^^^^^^^ + = help: consider using the `?` operator + +error: `unwrap` used in a function that returns a `Result` + --> tests/ui/unwrap_in_result.rs:99:5 + | +LL | A::bad_divisible_by_3("3".to_string()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: in this function signature + --> tests/ui/unwrap_in_result.rs:98:14 + | +LL | fn main() -> Result<(), ()> { + | ^^^^^^^^^^^^^^ + = help: consider using the `?` operator or calling the `.map_err()` method + +error: `unwrap` used in a function that returns a `Result` + --> tests/ui/unwrap_in_result.rs:101:5 + | +LL | A::good_divisible_by_3("3".to_string()).unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: `unwrap` used in a function that returns a `Result` + --> tests/ui/unwrap_in_result.rs:103:5 | -LL | let c = || a.unwrap(); - | ^^^^^^^^^^ +LL | Result::unwrap(A::good_divisible_by_3("3".to_string())); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index f15e5e0a5bb..cccb6bffabb 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -69,7 +69,7 @@ mod lifetimes { impl<'a> Foo<'a> { // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> // Foo<'b>` - fn foo(s: &str) -> Foo { + fn foo(s: &str) -> Foo<'_> { Foo { foo_str: s } } // cannot replace with `Self`, because that's `Foo<'a>` diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index b6376938611..09288677aa7 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -69,7 +69,7 @@ mod lifetimes { impl<'a> Foo<'a> { // Cannot use `Self` as return type, because the function is actually `fn foo<'b>(s: &'b str) -> // Foo<'b>` - fn foo(s: &str) -> Foo { + fn foo(s: &str) -> Foo<'_> { Foo { foo_str: s } } // cannot replace with `Self`, because that's `Foo<'a>` diff --git a/tests/ui/used_underscore_items.rs b/tests/ui/used_underscore_items.rs index 7e8289f1406..aecdd32693c 100644 --- a/tests/ui/used_underscore_items.rs +++ b/tests/ui/used_underscore_items.rs @@ -62,13 +62,13 @@ fn main() { //~^ used_underscore_items } -// should not lint exteranl crate. +// should not lint external crate. // user cannot control how others name their items fn external_item_call() { let foo_struct3 = external_item::_ExternalStruct {}; foo_struct3._foo(); - external_item::_exernal_foo(); + external_item::_external_foo(); } // should not lint foreign functions. diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index a96c8f46f55..be4fb55ddfb 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -13,7 +13,7 @@ #[allow(unused_imports)] #[allow(unused_extern_crates)] #[macro_use] -extern crate rustc_middle; +extern crate regex as regex_crate; #[macro_use] extern crate proc_macro_derive; @@ -146,3 +146,15 @@ pub mod unknown_namespace { #[allow(rustc::non_glob_import_of_type_ir_inherent)] use some_module::SomeType; } + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/15316 +pub mod redundant_imports_issue { + macro_rules! empty { + () => {}; + } + + #[expect(redundant_imports)] + pub(crate) use empty; + + empty!(); +} diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index b26410134bb..5a1bcf97a5b 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -13,7 +13,7 @@ #[allow(unused_imports)] #[allow(unused_extern_crates)] #[macro_use] -extern crate rustc_middle; +extern crate regex as regex_crate; #[macro_use] extern crate proc_macro_derive; @@ -146,3 +146,15 @@ pub mod unknown_namespace { #[allow(rustc::non_glob_import_of_type_ir_inherent)] use some_module::SomeType; } + +// Regression test for https://github.com/rust-lang/rust-clippy/issues/15316 +pub mod redundant_imports_issue { + macro_rules! empty { + () => {}; + } + + #[expect(redundant_imports)] + pub(crate) use empty; + + empty!(); +} diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed index f360a8afadf..55742459c92 100644 --- a/tests/ui/vec.fixed +++ b/tests/ui/vec.fixed @@ -242,3 +242,12 @@ fn issue_12101() { for a in &[1, 2] {} //~^ useless_vec } + +fn issue_14531() { + // The lint used to suggest using an array rather than a reference to a slice. + + fn requires_ref_slice(v: &[()]) {} + let v = &[]; + //~^ useless_vec + requires_ref_slice(v); +} diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index a779d33557c..fbf7131323c 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -242,3 +242,12 @@ fn issue_12101() { for a in &(vec![1, 2]) {} //~^ useless_vec } + +fn issue_14531() { + // The lint used to suggest using an array rather than a reference to a slice. + + fn requires_ref_slice(v: &[()]) {} + let v = &vec![]; + //~^ useless_vec + requires_ref_slice(v); +} diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 806d6617200..d16c8a8944a 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -127,5 +127,11 @@ error: useless use of `vec!` LL | for a in &(vec![1, 2]) {} | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` -error: aborting due to 21 previous errors +error: useless use of `vec!` + --> tests/ui/vec.rs:250:13 + | +LL | let v = &vec![]; + | ^^^^^^^ help: you can use a slice directly: `&[]` + +error: aborting due to 22 previous errors diff --git a/tests/ui/wildcard_enum_match_arm.fixed b/tests/ui/wildcard_enum_match_arm.fixed index 141ff6eb2ac..5f738a254dc 100644 --- a/tests/ui/wildcard_enum_match_arm.fixed +++ b/tests/ui/wildcard_enum_match_arm.fixed @@ -91,6 +91,21 @@ fn main() { } { + pub enum Enum { + A, + B, + C(u8), + D(u8, u8), + E { e: u8 }, + }; + match Enum::A { + Enum::A => (), + Enum::B | Enum::C(_) | Enum::D(..) | Enum::E { .. } => (), + //~^ wildcard_enum_match_arm + } + } + + { #![allow(clippy::manual_non_exhaustive)] pub enum Enum { A, @@ -105,3 +120,17 @@ fn main() { } } } + +fn issue15091() { + enum Foo { + A, + B, + C, + } + + match Foo::A { + Foo::A => {}, + r#type @ Foo::B | r#type @ Foo::C => {}, + //~^ wildcard_enum_match_arm + } +} diff --git a/tests/ui/wildcard_enum_match_arm.rs b/tests/ui/wildcard_enum_match_arm.rs index a13684e9100..4bc4bfdcb79 100644 --- a/tests/ui/wildcard_enum_match_arm.rs +++ b/tests/ui/wildcard_enum_match_arm.rs @@ -91,6 +91,21 @@ fn main() { } { + pub enum Enum { + A, + B, + C(u8), + D(u8, u8), + E { e: u8 }, + }; + match Enum::A { + Enum::A => (), + _ => (), + //~^ wildcard_enum_match_arm + } + } + + { #![allow(clippy::manual_non_exhaustive)] pub enum Enum { A, @@ -105,3 +120,17 @@ fn main() { } } } + +fn issue15091() { + enum Foo { + A, + B, + C, + } + + match Foo::A { + Foo::A => {}, + r#type => {}, + //~^ wildcard_enum_match_arm + } +} diff --git a/tests/ui/wildcard_enum_match_arm.stderr b/tests/ui/wildcard_enum_match_arm.stderr index 088c6b7b284..d0929989494 100644 --- a/tests/ui/wildcard_enum_match_arm.stderr +++ b/tests/ui/wildcard_enum_match_arm.stderr @@ -38,7 +38,19 @@ error: wildcard match will also match any future added variants --> tests/ui/wildcard_enum_match_arm.rs:103:13 | LL | _ => (), + | ^ help: try: `Enum::B | Enum::C(_) | Enum::D(..) | Enum::E { .. }` + +error: wildcard match will also match any future added variants + --> tests/ui/wildcard_enum_match_arm.rs:118:13 + | +LL | _ => (), | ^ help: try: `Enum::B | Enum::__Private` -error: aborting due to 6 previous errors +error: wildcard match will also match any future added variants + --> tests/ui/wildcard_enum_match_arm.rs:133:9 + | +LL | r#type => {}, + | ^^^^^^ help: try: `r#type @ Foo::B | r#type @ Foo::C` + +error: aborting due to 8 previous errors diff --git a/tests/ui/zero_ptr.fixed b/tests/ui/zero_ptr.fixed index f2375d57f3a..f9d9d2db176 100644 --- a/tests/ui/zero_ptr.fixed +++ b/tests/ui/zero_ptr.fixed @@ -16,3 +16,11 @@ fn main() { let z = 0; let _ = z as *const usize; // this is currently not caught } + +const fn in_const_context() { + #[clippy::msrv = "1.23"] + let _: *const usize = 0 as *const _; + #[clippy::msrv = "1.24"] + let _: *const usize = std::ptr::null(); + //~^ zero_ptr +} diff --git a/tests/ui/zero_ptr.rs b/tests/ui/zero_ptr.rs index ee01e426a43..41455fee5b5 100644 --- a/tests/ui/zero_ptr.rs +++ b/tests/ui/zero_ptr.rs @@ -16,3 +16,11 @@ fn main() { let z = 0; let _ = z as *const usize; // this is currently not caught } + +const fn in_const_context() { + #[clippy::msrv = "1.23"] + let _: *const usize = 0 as *const _; + #[clippy::msrv = "1.24"] + let _: *const usize = 0 as *const _; + //~^ zero_ptr +} diff --git a/tests/ui/zero_ptr.stderr b/tests/ui/zero_ptr.stderr index 8dc781f3625..81269de6c60 100644 --- a/tests/ui/zero_ptr.stderr +++ b/tests/ui/zero_ptr.stderr @@ -31,5 +31,11 @@ error: `0 as *mut _` detected LL | foo(0 as *const _, 0 as *mut _); | ^^^^^^^^^^^ help: try: `std::ptr::null_mut()` -error: aborting due to 5 previous errors +error: `0 as *const _` detected + --> tests/ui/zero_ptr.rs:24:27 + | +LL | let _: *const usize = 0 as *const _; + | ^^^^^^^^^^^^^ help: try: `std::ptr::null()` + +error: aborting due to 6 previous errors diff --git a/tests/ui/zero_sized_hashmap_values.rs b/tests/ui/zero_sized_hashmap_values.rs index dcbfd16843d..ee2fd19b5ee 100644 --- a/tests/ui/zero_sized_hashmap_values.rs +++ b/tests/ui/zero_sized_hashmap_values.rs @@ -92,6 +92,14 @@ fn issue14822() { //~^ zero_sized_map_values } +fn issue15429() { + struct E<'a>(&'a [E<'a>]); + + // The assertion error happens when the type being evaluated has escaping bound vars + // as it cannot be wrapped in a dummy binder during size computation. + type F = dyn for<'a> FnOnce(HashMap<u32, E<'a>>) -> u32; +} + fn main() { let _: HashMap<String, ()> = HashMap::new(); //~^ zero_sized_map_values diff --git a/tests/ui/zero_sized_hashmap_values.stderr b/tests/ui/zero_sized_hashmap_values.stderr index d29491fa05c..52ffef280c1 100644 --- a/tests/ui/zero_sized_hashmap_values.stderr +++ b/tests/ui/zero_sized_hashmap_values.stderr @@ -89,7 +89,7 @@ LL | type D = HashMap<u32, S<E>>; = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:96:34 + --> tests/ui/zero_sized_hashmap_values.rs:104:34 | LL | let _: HashMap<String, ()> = HashMap::new(); | ^^^^^^^ @@ -97,7 +97,7 @@ LL | let _: HashMap<String, ()> = HashMap::new(); = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:96:12 + --> tests/ui/zero_sized_hashmap_values.rs:104:12 | LL | let _: HashMap<String, ()> = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^ @@ -105,7 +105,7 @@ LL | let _: HashMap<String, ()> = HashMap::new(); = help: consider using a set instead error: map with zero-sized value type - --> tests/ui/zero_sized_hashmap_values.rs:102:12 + --> tests/ui/zero_sized_hashmap_values.rs:110:12 | LL | let _: HashMap<_, _> = std::iter::empty::<(String, ())>().collect(); | ^^^^^^^^^^^^^ diff --git a/tests/versioncheck.rs b/tests/versioncheck.rs index f6fc2354ca0..b0179387b2b 100644 --- a/tests/versioncheck.rs +++ b/tests/versioncheck.rs @@ -27,6 +27,7 @@ fn consistent_clippy_crate_versions() { "clippy_config/Cargo.toml", "clippy_lints/Cargo.toml", "clippy_utils/Cargo.toml", + "declare_clippy_lint/Cargo.toml", ]; for path in paths { |
