diff options
| author | Jane Lusby <jlusby@yaah.dev> | 2020-04-15 08:24:13 -0700 |
|---|---|---|
| committer | Jane Lusby <jlusby@yaah.dev> | 2020-04-15 08:24:13 -0700 |
| commit | 0441525690640ff374313fa5651a97829b0ea85a (patch) | |
| tree | d1d4ecade6f2c3be990bb73dba38350818f7b427 | |
| parent | 680cc2f25848721eca3a2332c48b13c02e027dbc (diff) | |
| parent | c496f4e63f5621872060b21793c5ec4ddf0e4a35 (diff) | |
| download | rust-0441525690640ff374313fa5651a97829b0ea85a.tar.gz rust-0441525690640ff374313fa5651a97829b0ea85a.zip | |
Merge remote-tracking branch 'upstream/master' into clippy-fix
256 files changed, 2940 insertions, 2072 deletions
diff --git a/.gitattributes b/.gitattributes index 796afdbde90..90cf33053c7 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,3 @@ -[attr]rust text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4 - * text=auto eol=lf -*.rs rust +*.rs text eol=lf whitespace=tab-in-indent,trailing-space,tabwidth=4 *.fixed linguist-language=Rust diff --git a/.github/deploy.sh b/.github/deploy.sh index 9ef9678ee92..3f425e5b725 100644 --- a/.github/deploy.sh +++ b/.github/deploy.sh @@ -17,6 +17,11 @@ if [[ -n $TAG_NAME ]]; then ln -s "$TAG_NAME" out/stable fi +if [[ $BETA = "true" ]]; then + echo "Update documentation for the beta release" + cp -r out/master out/beta +fi + # Generate version index that is shown as root index page cp util/gh-pages/versions.html out/index.html @@ -35,12 +40,15 @@ fi if [[ -n $TAG_NAME ]]; then # Add the new dir - git add $TAG_NAME + git add "$TAG_NAME" # Update the symlink git add stable # Update versions file git add versions.json git commit -m "Add documentation for ${TAG_NAME} release: ${SHA}" +elif [[ $BETA = "true" ]]; then + git add beta + git commit -m "Automatic deploy to GitHub Pages (beta): ${SHA}" else git add . git commit -m "Automatic deploy to GitHub Pages: ${SHA}" diff --git a/.github/workflows/clippy_bors.yml b/.github/workflows/clippy_bors.yml index 6675a1029bb..3b1774e03bc 100644 --- a/.github/workflows/clippy_bors.yml +++ b/.github/workflows/clippy_bors.yml @@ -234,7 +234,8 @@ jobs: - 'rust-lang/cargo' - 'rust-lang/rls' - 'rust-lang/chalk' - - 'rust-lang/rustfmt' + # FIXME: Disabled until https://github.com/rust-lang/rust/issues/71077 is fixed + # - 'rust-lang/rustfmt' - 'Marwes/combine' - 'Geal/nom' - 'rust-lang/stdarch' diff --git a/.github/workflows/clippy_dev.yml b/.github/workflows/clippy_dev.yml index 9ca2e630cbb..ffb88cdb4d9 100644 --- a/.github/workflows/clippy_dev.yml +++ b/.github/workflows/clippy_dev.yml @@ -38,8 +38,8 @@ jobs: run: cargo build --features deny-warnings working-directory: clippy_dev - - name: Test limit-stderr-length - run: cargo dev --limit-stderr-length + - name: Test limit_stderr_length + run: cargo dev limit_stderr_length - name: Test update_lints run: cargo dev update_lints --check diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 5b7bec81999..10033daf0ae 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -4,6 +4,7 @@ on: push: branches: - master + - beta tags: - rust-1.** @@ -34,6 +35,9 @@ jobs: run: | TAG=$(basename ${{ github.ref }}) echo "::set-env name=TAG_NAME::$TAG" + - name: Set beta to true + if: github.ref == 'refs/heads/beta' + run: echo "::set-env name=BETA::true" - name: Deploy run: | eval "$(ssh-agent -s)" diff --git a/CHANGELOG.md b/CHANGELOG.md index 81a1e276a88..b7ac3cace20 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1271,6 +1271,7 @@ Released 2018-09-13 [`float_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_arithmetic [`float_cmp`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp [`float_cmp_const`]: https://rust-lang.github.io/rust-clippy/master/index.html#float_cmp_const +[`fn_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_address_comparisons [`fn_params_excessive_bools`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_params_excessive_bools [`fn_to_numeric_cast`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast [`fn_to_numeric_cast_with_truncation`]: https://rust-lang.github.io/rust-clippy/master/index.html#fn_to_numeric_cast_with_truncation @@ -1432,6 +1433,7 @@ Released 2018-09-13 [`range_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one [`range_step_by_zero`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_step_by_zero [`range_zip_with_len`]: https://rust-lang.github.io/rust-clippy/master/index.html#range_zip_with_len +[`redundant_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation [`redundant_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_clone [`redundant_closure`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure [`redundant_closure_call`]: https://rust-lang.github.io/rust-clippy/master/index.html#redundant_closure_call @@ -1446,6 +1448,7 @@ Released 2018-09-13 [`replace_consts`]: https://rust-lang.github.io/rust-clippy/master/index.html#replace_consts [`rest_pat_in_fully_bound_structs`]: https://rust-lang.github.io/rust-clippy/master/index.html#rest_pat_in_fully_bound_structs [`result_expect_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_expect_used +[`result_map_or_into_option`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_or_into_option [`result_map_unit_fn`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unit_fn [`result_map_unwrap_or_else`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_map_unwrap_or_else [`result_unwrap_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#result_unwrap_used @@ -1540,6 +1543,7 @@ Released 2018-09-13 [`vec_box`]: https://rust-lang.github.io/rust-clippy/master/index.html#vec_box [`verbose_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_bit_mask [`verbose_file_reads`]: https://rust-lang.github.io/rust-clippy/master/index.html#verbose_file_reads +[`vtable_address_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#vtable_address_comparisons [`while_immutable_condition`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_immutable_condition [`while_let_loop`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_loop [`while_let_on_iterator`]: https://rust-lang.github.io/rust-clippy/master/index.html#while_let_on_iterator diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b1f9be44b73..50a5ee8bbf3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,8 @@ High level approach: ### Finding something to fix/improve -All issues on Clippy are mentored, if you want help with a bug just ask @Manishearth, @llogiq, @mcarton or @oli-obk. +All issues on Clippy are mentored, if you want help with a bug just ask +@Manishearth, @flip1995, @phansch or @yaahc. Some issues are easier than others. The [`good first issue`] label can be used to find the easy issues. If you want to work on an issue, please leave a comment so that we can assign it to you! @@ -70,7 +71,7 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us [`T-AST`]: https://github.com/rust-lang/rust-clippy/labels/T-AST [`T-middle`]: https://github.com/rust-lang/rust-clippy/labels/T-middle [`E-medium`]: https://github.com/rust-lang/rust-clippy/labels/E-medium -[`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty +[`ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty [nodes in the AST docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/ [deep-nesting]: https://github.com/rust-lang/rust-clippy/blob/557f6848bd5b7183f55c1e1522a326e9e1df6030/clippy_lints/src/mem_forget.rs#L29-L43 [if_chain]: https://docs.rs/if_chain/*/if_chain @@ -78,8 +79,7 @@ an AST expression). `match_def_path()` in Clippy's `utils` module can also be us ## Writing code -Have a look at the [docs for writing lints][adding_lints] for more details. [Llogiq's blog post on lints] -is also a nice primer to lint-writing, though it does get into advanced stuff and may be a bit outdated. +Have a look at the [docs for writing lints][adding_lints] for more details. If you want to add a new lint or change existing ones apart from bugfixing, it's also a good idea to give the [stability guarantees][rfc_stability] and @@ -87,7 +87,6 @@ also a good idea to give the [stability guarantees][rfc_stability] and quick read. [adding_lints]: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md -[Llogiq's blog post on lints]: https://llogiq.github.io/2015/06/04/workflows.html [clippy_rfc]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md [rfc_stability]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#stability-guarantees [rfc_lint_cats]: https://github.com/rust-lang/rfcs/blob/master/text/2476-clippy-uno.md#lint-audit-and-categories @@ -223,7 +222,7 @@ You can find the Clippy bors queue [here][homu_queue]. If you have @bors permissions, you can find an overview of the available commands [here][homu_instructions]. -[triage]: https://forge.rust-lang.org/triage-procedure.html +[triage]: https://forge.rust-lang.org/release/triage-procedure.html [l-crash]: https://github.com/rust-lang/rust-clippy/labels/L-crash%20%3Aboom%3A [l-bug]: https://github.com/rust-lang/rust-clippy/labels/L-bug%20%3Abeetle%3A [homu]: https://github.com/rust-lang/homu diff --git a/Cargo.toml b/Cargo.toml index 8421670a1a4..7b07fde4399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ lazy_static = "1.0" [dev-dependencies] cargo_metadata = "0.9.0" -compiletest_rs = { version = "0.4.0", features = ["tmp"] } +compiletest_rs = { version = "0.5.0", features = ["tmp"] } tester = "0.7" lazy_static = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } diff --git a/README.md b/README.md index ebdab4c6a1a..2a30f5e8e53 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 362 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are over 350 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you: @@ -90,14 +90,6 @@ Note that this is still experimental and only supported on the nightly channel: cargo fix -Z unstable-options --clippy ``` -#### Running only a single lint - -If you care only about the warnings of a single lint and want to ignore everything else, you -can first deny all the clippy lints and then explicitly enable the lint(s) you care about: -```` -cargo clippy -- -Aclippy::all -Wclippy::useless_format -```` - ### Running Clippy from the command line without installing it To have cargo compile your crate with Clippy without Clippy installation @@ -183,6 +175,8 @@ If you do not want to include your lint levels in your code, you can globally en flags to Clippy during the run: `cargo clippy -- -A clippy::lint_name` will run Clippy with `lint_name` disabled and `cargo clippy -- -W clippy::lint_name` will run it with that enabled. This also works with lint groups. For example you can run Clippy with warnings for all lints enabled: `cargo clippy -- -W clippy::pedantic` +If you care only about a single lint, you can allow all others and then explicitly reenable +the lint(s) you are interested in: `cargo clippy -- -Aclippy::all -Wclippy::useless_format -Wclippy::...` ## Contributing diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index c8aa1e79f34..c861efc8afb 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] bytecount = "0.6" clap = "2.33" -itertools = "0.8" +itertools = "0.9" regex = "1" lazy_static = "1.0" shell-escape = "0.1" diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index a6043c4be0d..6ae3f58c1f2 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -1,4 +1,4 @@ -use clippy_dev::clippy_project_root; +use crate::clippy_project_root; use shell_escape::escape; use std::ffi::OsStr; use std::io; diff --git a/clippy_dev/src/lib.rs b/clippy_dev/src/lib.rs index 6fe7bb155ac..1f8510f43a6 100644 --- a/clippy_dev/src/lib.rs +++ b/clippy_dev/src/lib.rs @@ -9,6 +9,11 @@ use std::fs; use std::path::{Path, PathBuf}; use walkdir::WalkDir; +pub mod fmt; +pub mod new_lint; +pub mod stderr_length_check; +pub mod update_lints; + lazy_static! { static ref DEC_CLIPPY_LINT_RE: Regex = Regex::new( r#"(?x) @@ -57,110 +62,89 @@ impl Lint { } /// Returns all non-deprecated lints and non-internal lints - pub fn usable_lints(lints: impl Iterator<Item = Self>) -> impl Iterator<Item = Self> { - lints.filter(|l| l.deprecation.is_none() && !l.is_internal()) + #[must_use] + pub fn usable_lints(lints: &[Self]) -> Vec<Self> { + lints + .iter() + .filter(|l| l.deprecation.is_none() && !l.group.starts_with("internal")) + .cloned() + .collect() } /// Returns all internal lints (not `internal_warn` lints) - pub fn internal_lints(lints: impl Iterator<Item = Self>) -> impl Iterator<Item = Self> { - lints.filter(|l| l.group == "internal") + #[must_use] + pub fn internal_lints(lints: &[Self]) -> Vec<Self> { + lints.iter().filter(|l| l.group == "internal").cloned().collect() } - /// Returns the lints in a `HashMap`, grouped by the different lint groups + /// Returns all deprecated lints #[must_use] - pub fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> { - lints.map(|lint| (lint.group.to_string(), lint)).into_group_map() + pub fn deprecated_lints(lints: &[Self]) -> Vec<Self> { + lints.iter().filter(|l| l.deprecation.is_some()).cloned().collect() } + /// Returns the lints in a `HashMap`, grouped by the different lint groups #[must_use] - pub fn is_internal(&self) -> bool { - self.group.starts_with("internal") + pub fn by_lint_group(lints: impl Iterator<Item = Self>) -> HashMap<String, Vec<Self>> { + lints.map(|lint| (lint.group.to_string(), lint)).into_group_map() } } /// Generates the Vec items for `register_lint_group` calls in `clippy_lints/src/lib.rs`. #[must_use] -pub fn gen_lint_group_list(lints: Vec<Lint>) -> Vec<String> { +pub fn gen_lint_group_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { lints - .into_iter() - .filter_map(|l| { - if l.deprecation.is_some() { - None - } else { - Some(format!(" LintId::of(&{}::{}),", l.module, l.name.to_uppercase())) - } - }) + .map(|l| format!(" LintId::of(&{}::{}),", l.module, l.name.to_uppercase())) .sorted() .collect::<Vec<String>>() } /// Generates the `pub mod module_name` list in `clippy_lints/src/lib.rs`. #[must_use] -pub fn gen_modules_list(lints: Vec<Lint>) -> Vec<String> { +pub fn gen_modules_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { lints - .into_iter() - .filter_map(|l| { - if l.is_internal() || l.deprecation.is_some() { - None - } else { - Some(l.module) - } - }) + .map(|l| &l.module) .unique() - .map(|module| format!("pub mod {};", module)) + .map(|module| format!("mod {};", module)) .sorted() .collect::<Vec<String>>() } /// Generates the list of lint links at the bottom of the README #[must_use] -pub fn gen_changelog_lint_list(lints: Vec<Lint>) -> Vec<String> { - let mut lint_list_sorted: Vec<Lint> = lints; - lint_list_sorted.sort_by_key(|l| l.name.clone()); - lint_list_sorted - .iter() - .filter_map(|l| { - if l.is_internal() { - None - } else { - Some(format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name)) - } - }) +pub fn gen_changelog_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { + lints + .sorted_by_key(|l| &l.name) + .map(|l| format!("[`{}`]: {}#{}", l.name, DOCS_LINK, l.name)) .collect() } /// Generates the `register_removed` code in `./clippy_lints/src/lib.rs`. #[must_use] -pub fn gen_deprecated(lints: &[Lint]) -> Vec<String> { +pub fn gen_deprecated<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { lints - .iter() - .filter_map(|l| { - l.clone().deprecation.map(|depr_text| { - vec![ - " store.register_removed(".to_string(), - format!(" \"clippy::{}\",", l.name), - format!(" \"{}\",", depr_text), - " );".to_string(), - ] - }) + .flat_map(|l| { + l.deprecation + .clone() + .map(|depr_text| { + vec![ + " store.register_removed(".to_string(), + format!(" \"clippy::{}\",", l.name), + format!(" \"{}\",", depr_text), + " );".to_string(), + ] + }) + .expect("only deprecated lints should be passed") }) - .flatten() .collect::<Vec<String>>() } #[must_use] -pub fn gen_register_lint_list(lints: &[Lint]) -> Vec<String> { +pub fn gen_register_lint_list<'a>(lints: impl Iterator<Item = &'a Lint>) -> Vec<String> { let pre = " store.register_lints(&[".to_string(); let post = " ]);".to_string(); let mut inner = lints - .iter() - .filter_map(|l| { - if !l.is_internal() && l.deprecation.is_none() { - Some(format!(" &{}::{},", l.module, l.name.to_uppercase())) - } else { - None - } - }) + .map(|l| format!(" &{}::{},", l.module, l.name.to_uppercase())) .sorted() .collect::<Vec<String>>(); inner.insert(0, pre); @@ -434,7 +418,7 @@ fn test_usable_lints() { None, "module_name", )]; - assert_eq!(expected, Lint::usable_lints(lints.into_iter()).collect::<Vec<Lint>>()); + assert_eq!(expected, Lint::usable_lints(&lints)); } #[test] @@ -464,13 +448,12 @@ fn test_gen_changelog_lint_list() { let lints = vec![ Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), - Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), ]; let expected = vec![ format!("[`should_assert_eq`]: {}#should_assert_eq", DOCS_LINK.to_string()), format!("[`should_assert_eq2`]: {}#should_assert_eq2", DOCS_LINK.to_string()), ]; - assert_eq!(expected, gen_changelog_lint_list(lints)); + assert_eq!(expected, gen_changelog_lint_list(lints.iter())); } #[test] @@ -490,7 +473,6 @@ fn test_gen_deprecated() { Some("will be removed"), "module_name", ), - Lint::new("should_assert_eq2", "group2", "abc", None, "module_name"), ]; let expected: Vec<String> = vec![ " store.register_removed(", @@ -505,22 +487,24 @@ fn test_gen_deprecated() { .into_iter() .map(String::from) .collect(); - assert_eq!(expected, gen_deprecated(&lints)); + assert_eq!(expected, gen_deprecated(lints.iter())); +} + +#[test] +#[should_panic] +fn test_gen_deprecated_fail() { + let lints = vec![Lint::new("should_assert_eq2", "group2", "abc", None, "module_name")]; + let _ = gen_deprecated(lints.iter()); } #[test] fn test_gen_modules_list() { let lints = vec![ Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"), Lint::new("incorrect_stuff", "group3", "abc", None, "another_module"), - Lint::new("incorrect_internal", "internal_style", "abc", None, "module_name"), - ]; - let expected = vec![ - "pub mod another_module;".to_string(), - "pub mod module_name;".to_string(), ]; - assert_eq!(expected, gen_modules_list(lints)); + let expected = vec!["mod another_module;".to_string(), "mod module_name;".to_string()]; + assert_eq!(expected, gen_modules_list(lints.iter())); } #[test] @@ -528,7 +512,6 @@ fn test_gen_lint_group_list() { let lints = vec![ Lint::new("abc", "group1", "abc", None, "module_name"), Lint::new("should_assert_eq", "group1", "abc", None, "module_name"), - Lint::new("should_assert_eq2", "group2", "abc", Some("abc"), "deprecated"), Lint::new("internal", "internal_style", "abc", None, "module_name"), ]; let expected = vec![ @@ -536,5 +519,5 @@ fn test_gen_lint_group_list() { " LintId::of(&module_name::INTERNAL),".to_string(), " LintId::of(&module_name::SHOULD_ASSERT_EQ),".to_string(), ]; - assert_eq!(expected, gen_lint_group_list(lints)); + assert_eq!(expected, gen_lint_group_list(lints.iter())); } diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 901e663ded3..d99235f7c07 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -1,21 +1,7 @@ #![cfg_attr(feature = "deny-warnings", deny(warnings))] use clap::{App, Arg, SubCommand}; -use clippy_dev::{ - gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list, - replace_region_in_file, Lint, DOCS_LINK, -}; -use std::path::Path; - -mod fmt; -mod new_lint; -mod stderr_length_check; - -#[derive(Clone, Copy, PartialEq)] -enum UpdateMode { - Check, - Change, -} +use clippy_dev::{fmt, new_lint, stderr_length_check, update_lints}; fn main() { let matches = App::new("Clippy developer tooling") @@ -97,28 +83,23 @@ fn main() { .takes_value(true), ), ) - .arg( - Arg::with_name("limit-stderr-length") - .long("limit-stderr-length") - .help("Ensures that stderr files do not grow longer than a certain amount of lines."), + .subcommand( + SubCommand::with_name("limit_stderr_length") + .about("Ensures that stderr files do not grow longer than a certain amount of lines."), ) .get_matches(); - if matches.is_present("limit-stderr-length") { - stderr_length_check::check(); - } - match matches.subcommand() { ("fmt", Some(matches)) => { fmt::run(matches.is_present("check"), matches.is_present("verbose")); }, ("update_lints", Some(matches)) => { if matches.is_present("print-only") { - print_lints(); + update_lints::print_lints(); } else if matches.is_present("check") { - update_lints(UpdateMode::Check); + update_lints::run(update_lints::UpdateMode::Check); } else { - update_lints(UpdateMode::Change); + update_lints::run(update_lints::UpdateMode::Change); } }, ("new_lint", Some(matches)) => { @@ -127,168 +108,13 @@ fn main() { matches.value_of("name"), matches.value_of("category"), ) { - Ok(_) => update_lints(UpdateMode::Change), + Ok(_) => update_lints::run(update_lints::UpdateMode::Change), Err(e) => eprintln!("Unable to create lint: {}", e), } }, - _ => {}, - } -} - -fn print_lints() { - let lint_list = gather_all(); - let usable_lints: Vec<Lint> = Lint::usable_lints(lint_list).collect(); - let usable_lint_count = usable_lints.len(); - let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter()); - - for (lint_group, mut lints) in grouped_by_lint_group { - if lint_group == "Deprecated" { - continue; - } - println!("\n## {}", lint_group); - - lints.sort_by_key(|l| l.name.clone()); - - for lint in lints { - println!( - "* [{}]({}#{}) ({})", - lint.name, - clippy_dev::DOCS_LINK, - lint.name, - lint.desc - ); - } - } - - println!("there are {} lints", usable_lint_count); -} - -#[allow(clippy::too_many_lines)] -fn update_lints(update_mode: UpdateMode) { - let lint_list: Vec<Lint> = gather_all().collect(); - - let internal_lints = Lint::internal_lints(lint_list.clone().into_iter()); - - let usable_lints: Vec<Lint> = Lint::usable_lints(lint_list.clone().into_iter()).collect(); - let usable_lint_count = usable_lints.len(); - - let mut sorted_usable_lints = usable_lints.clone(); - sorted_usable_lints.sort_by_key(|lint| lint.name.clone()); - - let mut file_change = replace_region_in_file( - Path::new("src/lintlist/mod.rs"), - "begin lint list", - "end lint list", - false, - update_mode == UpdateMode::Change, - || { - format!( - "pub const ALL_LINTS: [Lint; {}] = {:#?};", - sorted_usable_lints.len(), - sorted_usable_lints - ) - .lines() - .map(ToString::to_string) - .collect::<Vec<_>>() - }, - ) - .changed; - - file_change |= replace_region_in_file( - Path::new("README.md"), - &format!(r#"\[There are \d+ lints included in this crate!\]\({}\)"#, DOCS_LINK), - "", - true, - update_mode == UpdateMode::Change, - || { - vec", - usable_lint_count, DOCS_LINK - )] + ("limit_stderr_length", _) => { + stderr_length_check::check(); }, - ) - .changed; - - file_change |= replace_region_in_file( - Path::new("CHANGELOG.md"), - "<!-- begin autogenerated links to lint list -->", - "<!-- end autogenerated links to lint list -->", - false, - update_mode == UpdateMode::Change, - || gen_changelog_lint_list(lint_list.clone()), - ) - .changed; - - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - "begin deprecated lints", - "end deprecated lints", - false, - update_mode == UpdateMode::Change, - || gen_deprecated(&lint_list), - ) - .changed; - - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - "begin register lints", - "end register lints", - false, - update_mode == UpdateMode::Change, - || gen_register_lint_list(&lint_list), - ) - .changed; - - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - "begin lints modules", - "end lints modules", - false, - update_mode == UpdateMode::Change, - || gen_modules_list(lint_list.clone()), - ) - .changed; - - // Generate lists of lints in the clippy::all lint group - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - r#"store.register_group\(true, "clippy::all""#, - r#"\]\);"#, - false, - update_mode == UpdateMode::Change, - || { - // clippy::all should only include the following lint groups: - let all_group_lints = usable_lints - .clone() - .into_iter() - .filter(|l| { - l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf" - }) - .collect(); - - gen_lint_group_list(all_group_lints) - }, - ) - .changed; - - // Generate the list of lints for all other lint groups - for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) { - file_change |= replace_region_in_file( - Path::new("clippy_lints/src/lib.rs"), - &format!("store.register_group\\(true, \"clippy::{}\"", lint_group), - r#"\]\);"#, - false, - update_mode == UpdateMode::Change, - || gen_lint_group_list(lints.clone()), - ) - .changed; - } - - if update_mode == UpdateMode::Check && file_change { - println!( - "Not all lints defined properly. \ - Please run `cargo dev update_lints` to make sure all lints are defined properly." - ); - std::process::exit(1); + _ => {}, } } diff --git a/clippy_dev/src/new_lint.rs b/clippy_dev/src/new_lint.rs index 9e2a4617cde..44b2a5383d2 100644 --- a/clippy_dev/src/new_lint.rs +++ b/clippy_dev/src/new_lint.rs @@ -1,10 +1,15 @@ -use clippy_dev::clippy_project_root; +use crate::clippy_project_root; use std::fs::{File, OpenOptions}; use std::io; use std::io::prelude::*; use std::io::ErrorKind; use std::path::Path; +/// Creates files required to implement and test a new lint and runs `update_lints`. +/// +/// # Errors +/// +/// This function errors, if the files couldn't be created pub fn create(pass: Option<&str>, lint_name: Option<&str>, category: Option<&str>) -> Result<(), io::Error> { let pass = pass.expect("`pass` argument is validated by clap"); let lint_name = lint_name.expect("`name` argument is validated by clap"); diff --git a/clippy_dev/src/stderr_length_check.rs b/clippy_dev/src/stderr_length_check.rs index c511733f7bf..e02b6f7da5f 100644 --- a/clippy_dev/src/stderr_length_check.rs +++ b/clippy_dev/src/stderr_length_check.rs @@ -1,11 +1,9 @@ +use crate::clippy_project_root; use std::ffi::OsStr; use std::fs; use std::path::{Path, PathBuf}; - use walkdir::WalkDir; -use clippy_dev::clippy_project_root; - // The maximum length allowed for stderr files. // // We limit this because small files are easier to deal with than bigger files. diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs new file mode 100644 index 00000000000..a9a70929942 --- /dev/null +++ b/clippy_dev/src/update_lints.rs @@ -0,0 +1,162 @@ +use crate::{ + gather_all, gen_changelog_lint_list, gen_deprecated, gen_lint_group_list, gen_modules_list, gen_register_lint_list, + replace_region_in_file, Lint, DOCS_LINK, +}; +use std::path::Path; + +#[derive(Clone, Copy, PartialEq)] +pub enum UpdateMode { + Check, + Change, +} + +#[allow(clippy::too_many_lines)] +pub fn run(update_mode: UpdateMode) { + let lint_list: Vec<Lint> = gather_all().collect(); + + let internal_lints = Lint::internal_lints(&lint_list); + let deprecated_lints = Lint::deprecated_lints(&lint_list); + let usable_lints = Lint::usable_lints(&lint_list); + let mut sorted_usable_lints = usable_lints.clone(); + sorted_usable_lints.sort_by_key(|lint| lint.name.clone()); + + let usable_lint_count = round_to_fifty(usable_lints.len()); + + let mut file_change = replace_region_in_file( + Path::new("src/lintlist/mod.rs"), + "begin lint list", + "end lint list", + false, + update_mode == UpdateMode::Change, + || { + format!("pub static ref ALL_LINTS: Vec<Lint> = vec!{:#?};", sorted_usable_lints) + .lines() + .map(ToString::to_string) + .collect::<Vec<_>>() + }, + ) + .changed; + + file_change |= replace_region_in_file( + Path::new("README.md"), + &format!( + r#"\[There are over \d+ lints included in this crate!\]\({}\)"#, + DOCS_LINK + ), + "", + true, + update_mode == UpdateMode::Change, + || { + vec", + usable_lint_count, DOCS_LINK + )] + }, + ) + .changed; + + file_change |= replace_region_in_file( + Path::new("CHANGELOG.md"), + "<!-- begin autogenerated links to lint list -->", + "<!-- end autogenerated links to lint list -->", + false, + update_mode == UpdateMode::Change, + || gen_changelog_lint_list(usable_lints.iter().chain(deprecated_lints.iter())), + ) + .changed; + + file_change |= replace_region_in_file( + Path::new("clippy_lints/src/lib.rs"), + "begin deprecated lints", + "end deprecated lints", + false, + update_mode == UpdateMode::Change, + || gen_deprecated(deprecated_lints.iter()), + ) + .changed; + + file_change |= replace_region_in_file( + Path::new("clippy_lints/src/lib.rs"), + "begin register lints", + "end register lints", + false, + update_mode == UpdateMode::Change, + || gen_register_lint_list(usable_lints.iter().chain(internal_lints.iter())), + ) + .changed; + + file_change |= replace_region_in_file( + Path::new("clippy_lints/src/lib.rs"), + "begin lints modules", + "end lints modules", + false, + update_mode == UpdateMode::Change, + || gen_modules_list(usable_lints.iter()), + ) + .changed; + + // Generate lists of lints in the clippy::all lint group + file_change |= replace_region_in_file( + Path::new("clippy_lints/src/lib.rs"), + r#"store.register_group\(true, "clippy::all""#, + r#"\]\);"#, + false, + update_mode == UpdateMode::Change, + || { + // clippy::all should only include the following lint groups: + let all_group_lints = usable_lints.iter().filter(|l| { + l.group == "correctness" || l.group == "style" || l.group == "complexity" || l.group == "perf" + }); + + gen_lint_group_list(all_group_lints) + }, + ) + .changed; + + // Generate the list of lints for all other lint groups + for (lint_group, lints) in Lint::by_lint_group(usable_lints.into_iter().chain(internal_lints)) { + file_change |= replace_region_in_file( + Path::new("clippy_lints/src/lib.rs"), + &format!("store.register_group\\(true, \"clippy::{}\"", lint_group), + r#"\]\);"#, + false, + update_mode == UpdateMode::Change, + || gen_lint_group_list(lints.iter()), + ) + .changed; + } + + if update_mode == UpdateMode::Check && file_change { + println!( + "Not all lints defined properly. \ + Please run `cargo dev update_lints` to make sure all lints are defined properly." + ); + std::process::exit(1); + } +} + +pub fn print_lints() { + let lint_list: Vec<Lint> = gather_all().collect(); + let usable_lints = Lint::usable_lints(&lint_list); + let usable_lint_count = usable_lints.len(); + let grouped_by_lint_group = Lint::by_lint_group(usable_lints.into_iter()); + + for (lint_group, mut lints) in grouped_by_lint_group { + if lint_group == "Deprecated" { + continue; + } + println!("\n## {}", lint_group); + + lints.sort_by_key(|l| l.name.clone()); + + for lint in lints { + println!("* [{}]({}#{}) ({})", lint.name, DOCS_LINK, lint.name, lint.desc); + } + } + + println!("there are {} lints", usable_lint_count); +} + +fn round_to_fifty(count: usize) -> usize { + count / 50 * 50 +} diff --git a/clippy_lints/src/as_conversions.rs b/clippy_lints/src/as_conversions.rs index 1ec3377193e..4d8bbcd3102 100644 --- a/clippy_lints/src/as_conversions.rs +++ b/clippy_lints/src/as_conversions.rs @@ -1,6 +1,6 @@ -use rustc::lint::in_external_macro; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index b6fb6fdd2cc..c60577e8b2d 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -3,11 +3,11 @@ use crate::utils::{ }; use crate::utils::{higher, sugg}; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -77,7 +77,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for AssignOps { }, hir::ExprKind::Assign(assignee, e, _) => { if let hir::ExprKind::Binary(op, l, r) = &e.kind { - #[allow(clippy::cognitive_complexity)] let lint = |assignee: &hir::Expr<'_>, rhs: &hir::Expr<'_>| { let ty = cx.tables.expr_ty(assignee); let rty = cx.tables.expr_ty(rhs); diff --git a/clippy_lints/src/atomic_ordering.rs b/clippy_lints/src/atomic_ordering.rs index 871ca029b1a..d9ff1fe0a1d 100644 --- a/clippy_lints/src/atomic_ordering.rs +++ b/clippy_lints/src/atomic_ordering.rs @@ -1,9 +1,9 @@ use crate::utils::{match_def_path, span_lint_and_help}; use if_chain::if_chain; -use rustc::ty; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index 35cde05e7f5..a406b141c36 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -6,8 +6,6 @@ use crate::utils::{ span_lint_and_then, without_block_comments, }; use if_chain::if_chain; -use rustc::lint::in_external_macro; -use rustc::ty; use rustc_ast::ast::{AttrKind, AttrStyle, Attribute, Lit, LitKind, MetaItemKind, NestedMetaItem}; use rustc_ast::util::lev_distance::find_best_match_for_name; use rustc_errors::Applicability; @@ -15,6 +13,8 @@ use rustc_hir::{ Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind, }; use rustc_lint::{CheckLintNameResult, EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; diff --git a/clippy_lints/src/bit_mask.rs b/clippy_lints/src/bit_mask.rs index 78053542349..db7b5e54a2d 100644 --- a/clippy_lints/src/bit_mask.rs +++ b/clippy_lints/src/bit_mask.rs @@ -87,7 +87,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # let x = 1; - /// if x & 0x1111 == 0 { } + /// if x & 0b1111 == 0 { } /// ``` pub VERBOSE_BIT_MASK, style, diff --git a/clippy_lints/src/block_in_if_condition.rs b/clippy_lints/src/block_in_if_condition.rs index 1972c53d648..9e533eaa32c 100644 --- a/clippy_lints/src/block_in_if_condition.rs +++ b/clippy_lints/src/block_in_if_condition.rs @@ -1,10 +1,10 @@ use crate::utils::{differing_macro_contexts, higher, snippet_block_with_applicability, span_lint, span_lint_and_sugg}; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{BlockCheckMode, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index b580240be17..f16d10fde92 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -1,14 +1,14 @@ use crate::utils::{ - get_trait_def_id, implements_trait, in_macro, match_type, paths, snippet_opt, span_lint_and_sugg, + get_trait_def_id, implements_trait, in_macro, is_type_diagnostic_item, paths, snippet_opt, span_lint_and_sugg, span_lint_and_then, SpanlessEq, }; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -249,7 +249,9 @@ fn simplify_not(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> Option<String> { }, ExprKind::MethodCall(path, _, args) if args.len() == 1 => { let type_of_receiver = cx.tables.expr_ty(&args[0]); - if !match_type(cx, type_of_receiver, &paths::OPTION) && !match_type(cx, type_of_receiver, &paths::RESULT) { + if !is_type_diagnostic_item(cx, type_of_receiver, sym!(option_type)) + && !is_type_diagnostic_item(cx, type_of_receiver, sym!(result_type)) + { return None; } METHODS_WITH_NEGATION diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 9c06eb962d7..91d3e47d787 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -3,11 +3,11 @@ use crate::utils::{ span_lint_and_sugg, walk_ptrs_ty, }; use if_chain::if_chain; -use rustc::ty; use rustc_ast::ast::{Name, UintTy}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 23992ae89a7..d9776dd50a8 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -1,11 +1,11 @@ //! lint on manually implemented checked conversions that could be transformed into `try_from` use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::{BinOp, BinOpKind, Expr, ExprKind, QPath, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::{snippet_with_applicability, span_lint_and_sugg, SpanlessEq}; @@ -21,7 +21,7 @@ declare_clippy_lint! { /// ```rust /// # let foo: u32 = 5; /// # let _ = - /// foo <= i32::max_value() as u32 + /// foo <= i32::MAX as u32 /// # ; /// ``` /// @@ -179,7 +179,7 @@ impl ConversionType { } } -/// Check for `expr <= (to_type::max_value() as from_type)` +/// Check for `expr <= (to_type::MAX as from_type)` fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { if_chain! { if let ExprKind::Binary(ref op, ref left, ref right) = &expr.kind; @@ -194,7 +194,7 @@ fn check_upper_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { } } -/// Check for `expr >= 0|(to_type::min_value() as from_type)` +/// Check for `expr >= 0|(to_type::MIN as from_type)` fn check_lower_bound<'tcx>(expr: &'tcx Expr<'tcx>) -> Option<Conversion<'tcx>> { fn check_function<'a>(candidate: &'a Expr<'a>, check: &'a Expr<'a>) -> Option<Conversion<'a>> { (check_lower_bound_zero(candidate, check)).or_else(|| (check_lower_bound_min(candidate, check))) @@ -222,7 +222,7 @@ fn check_lower_bound_zero<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> O } } -/// Check for `expr >= (to_type::min_value() as from_type)` +/// Check for `expr >= (to_type::MIN as from_type)` fn check_lower_bound_min<'a>(candidate: &'a Expr<'_>, check: &'a Expr<'_>) -> Option<Conversion<'a>> { if let Some((from, to)) = get_types_from_cast(check, MIN_VALUE, SINTS) { Conversion::try_new(candidate, from, to) diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index fcab4590188..93a394b79e5 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -1,15 +1,15 @@ //! calculate cognitive complexity and warn about overly complex functions -use rustc::hir::map::Map; use rustc_ast::ast::Attribute; use rustc_hir::intravisit::{walk_expr, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_span::BytePos; -use crate::utils::{match_type, paths, snippet_opt, span_lint_and_help, LimitStack}; +use crate::utils::{is_type_diagnostic_item, snippet_opt, span_lint_and_help, LimitStack}; declare_clippy_lint! { /// **What it does:** Checks for methods with high cognitive complexity. @@ -22,7 +22,7 @@ declare_clippy_lint! { /// /// **Example:** No. You'll see it when you get the warning. pub COGNITIVE_COMPLEXITY, - complexity, + nursery, "functions that should be split up into multiple functions" } @@ -61,7 +61,7 @@ impl CognitiveComplexity { helper.visit_expr(expr); let CCHelper { cc, returns } = helper; let ret_ty = cx.tables.node_type(expr.hir_id); - let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) { + let ret_adjust = if is_type_diagnostic_item(cx, ret_ty, sym!(result_type)) { returns } else { #[allow(clippy::integer_division)] diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index fc26755a375..b9160712915 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -2,14 +2,14 @@ use crate::utils::{clip, higher, sext, unsext}; use if_chain::if_chain; -use rustc::ty::subst::{Subst, SubstsRef}; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc::{bug, span_bug}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_data_structures::sync::Lrc; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{BinOp, BinOpKind, Block, Expr, ExprKind, HirId, QPath, UnOp}; use rustc_lint::LateContext; +use rustc_middle::ty::subst::{Subst, SubstsRef}; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_middle::{bug, span_bug}; use rustc_span::symbol::Symbol; use std::cmp::Ordering::{self, Equal}; use std::convert::TryInto; @@ -268,6 +268,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } }, + ExprKind::Index(ref arr, ref index) => self.index(arr, index), // TODO: add other expressions. _ => None, } @@ -333,7 +334,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { .tcx .const_eval_resolve(self.param_env, def_id, substs, None, None) .ok() - .map(|val| rustc::ty::Const::from_value(self.lcx.tcx, val, ty))?; + .map(|val| rustc_middle::ty::Const::from_value(self.lcx.tcx, val, ty))?; let result = miri_to_const(&result); if result.is_some() { self.needed_resolution = true; @@ -345,6 +346,31 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } } + fn index(&mut self, lhs: &'_ Expr<'_>, index: &'_ Expr<'_>) -> Option<Constant> { + let lhs = self.expr(lhs); + let index = self.expr(index); + + match (lhs, index) { + (Some(Constant::Vec(vec)), Some(Constant::Int(index))) => match vec[index as usize] { + Constant::F32(x) => Some(Constant::F32(x)), + Constant::F64(x) => Some(Constant::F64(x)), + _ => None, + }, + (Some(Constant::Vec(vec)), _) => { + if !vec.is_empty() && vec.iter().all(|x| *x == vec[0]) { + match vec[0] { + Constant::F32(x) => Some(Constant::F32(x)), + Constant::F64(x) => Some(Constant::F64(x)), + _ => None, + } + } else { + None + } + }, + _ => None, + } + } + /// A block can only yield a constant if it only has one constant expression. fn block(&mut self, block: &Block<'_>) -> Option<Constant> { if block.stmts.is_empty() { @@ -460,7 +486,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { } pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { - use rustc::mir::interpret::{ConstValue, Scalar}; + use rustc_middle::mir::interpret::{ConstValue, Scalar}; match result.val { ty::ConstKind::Value(ConstValue::Scalar(Scalar::Raw { data: d, .. })) => match result.ty.kind { ty::Bool => Some(Constant::Bool(d == 1)), @@ -492,6 +518,41 @@ pub fn miri_to_const(result: &ty::Const<'_>) -> Option<Constant> { }, _ => None, }, + ty::ConstKind::Value(ConstValue::ByRef { alloc, offset: _ }) => match result.ty.kind { + ty::Array(sub_type, len) => match sub_type.kind { + ty::Float(FloatTy::F32) => match miri_to_const(len) { + Some(Constant::Int(len)) => alloc + .inspect_with_undef_and_ptr_outside_interpreter(0..(4 * len as usize)) + .to_owned() + .chunks(4) + .map(|chunk| { + Some(Constant::F32(f32::from_le_bytes( + chunk.try_into().expect("this shouldn't happen"), + ))) + }) + .collect::<Option<Vec<Constant>>>() + .map(Constant::Vec), + _ => None, + }, + ty::Float(FloatTy::F64) => match miri_to_const(len) { + Some(Constant::Int(len)) => alloc + .inspect_with_undef_and_ptr_outside_interpreter(0..(8 * len as usize)) + .to_owned() + .chunks(8) + .map(|chunk| { + Some(Constant::F64(f64::from_le_bytes( + chunk.try_into().expect("this shouldn't happen"), + ))) + }) + .collect::<Option<Vec<Constant>>>() + .map(Constant::Vec), + _ => None, + }, + // FIXME: implement other array type conversions. + _ => None, + }, + _ => None, + }, // FIXME: implement other conversions. _ => None, } diff --git a/clippy_lints/src/copies.rs b/clippy_lints/src/copies.rs index 996f80a757e..383ee1164a2 100644 --- a/clippy_lints/src/copies.rs +++ b/clippy_lints/src/copies.rs @@ -1,9 +1,9 @@ use crate::utils::{get_parent_expr, higher, if_sequence, same_tys, snippet, span_lint_and_note, span_lint_and_then}; use crate::utils::{SpanlessEq, SpanlessHash}; -use rustc::ty::Ty; use rustc_data_structures::fx::FxHashMap; use rustc_hir::{Arm, Block, Expr, ExprKind, MatchSource, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; use std::collections::hash_map::Entry; diff --git a/clippy_lints/src/default_trait_access.rs b/clippy_lints/src/default_trait_access.rs index f99e6d96e03..635d609c382 100644 --- a/clippy_lints/src/default_trait_access.rs +++ b/clippy_lints/src/default_trait_access.rs @@ -1,8 +1,8 @@ use if_chain::if_chain; -use rustc::ty; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::{any_parent_is_automatically_derived, match_def_path, paths, span_lint_and_sugg}; diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 93c19bf9550..6e8ca647dd7 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -147,3 +147,11 @@ declare_deprecated_lint! { pub UNUSED_LABEL, "this lint has been uplifted to rustc and is now called `unused_labels`" } + +declare_deprecated_lint! { + /// **What it does:** Nothing. This lint has been deprecated. + /// + /// **Deprecation reason:** Associated-constants are now preferred. + pub REPLACE_CONSTS, + "associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants" +} diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index f130a69778f..a24cfa89ec2 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -1,9 +1,9 @@ use crate::utils::paths; use crate::utils::{is_automatically_derived, is_copy, match_path, span_lint_and_then}; use if_chain::if_chain; -use rustc::ty::{self, Ty}; use rustc_hir::{Item, ItemKind, TraitRef}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -94,7 +94,8 @@ fn check_hash_peq<'a, 'tcx>( if_chain! { if match_path(&trait_ref.path, &paths::HASH); if let Some(peq_trait_def_id) = cx.tcx.lang_items().eq_trait(); - if !&trait_ref.trait_def_id().is_local(); + if let Some(def_id) = &trait_ref.trait_def_id(); + if !def_id.is_local(); then { // Look for the PartialEq implementations for `ty` cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 63b8d519c9d..926bd8ed001 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -1,12 +1,12 @@ -use crate::utils::{implements_trait, is_entrypoint_fn, match_type, paths, return_ty, span_lint}; +use crate::utils::{implements_trait, is_entrypoint_fn, is_type_diagnostic_item, return_ty, span_lint}; use if_chain::if_chain; use itertools::Itertools; -use rustc::lint::in_external_macro; -use rustc::ty; use rustc_ast::ast::{AttrKind, Attribute}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{BytePos, MultiSpan, Span}; use rustc_span::Pos; @@ -217,7 +217,7 @@ fn lint_for_missing_headers<'a, 'tcx>( ); } if !headers.errors { - if match_type(cx, return_ty(cx, hir_id), &paths::RESULT) { + if is_type_diagnostic_item(cx, return_ty(cx, hir_id), sym!(result_type)) { span_lint( cx, MISSING_ERRORS_DOC, @@ -229,13 +229,13 @@ fn lint_for_missing_headers<'a, 'tcx>( if let Some(body_id) = body_id; if let Some(future) = cx.tcx.lang_items().future_trait(); let def_id = cx.tcx.hir().body_owner_def_id(body_id); - let mir = cx.tcx.optimized_mir(def_id); + let mir = cx.tcx.optimized_mir(def_id.to_def_id()); let ret_ty = mir.return_ty(); if implements_trait(cx, ret_ty, future, &[]); if let ty::Opaque(_, subs) = ret_ty.kind; if let Some(gen) = subs.types().next(); if let ty::Generator(_, subs, _) = gen.kind; - if match_type(cx, subs.as_generator().return_ty(), &paths::RESULT); + if is_type_diagnostic_item(cx, subs.as_generator().return_ty(), sym!(result_type)); then { span_lint( cx, diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index bd9bdfef090..9a60b2f027a 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -1,8 +1,8 @@ use crate::utils::{is_copy, match_def_path, paths, qpath_res, span_lint_and_note}; use if_chain::if_chain; -use rustc::ty; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index ccaa35350cc..fb10ca48074 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -1,8 +1,8 @@ //! Lint on if expressions with an else if, but without a final else branch. -use rustc::lint::in_external_macro; use rustc_ast::ast::{Expr, ExprKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 88647be0264..65c9d08a6bd 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -2,11 +2,11 @@ use crate::utils::SpanlessEq; use crate::utils::{get_item_name, higher, match_type, paths, snippet, snippet_opt}; use crate::utils::{snippet_with_applicability, span_lint_and_then, walk_ptrs_ty}; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{BorrowKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 5bc8a446cf0..a1fed3fb6e2 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -3,11 +3,11 @@ use crate::consts::{miri_to_const, Constant}; use crate::utils::span_lint; -use rustc::ty; -use rustc::ty::util::IntTypeExt; use rustc_ast::ast::{IntTy, UintTy}; use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_middle::ty::util::IntTypeExt; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::convert::TryFrom; @@ -46,12 +46,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { for var in def.variants { if let Some(anon_const) = &var.disr_expr { let def_id = cx.tcx.hir().body_owner_def_id(anon_const.body); - let mut ty = cx.tcx.type_of(def_id); + let mut ty = cx.tcx.type_of(def_id.to_def_id()); let constant = cx .tcx - .const_eval_poly(def_id) + .const_eval_poly(def_id.to_def_id()) .ok() - .map(|val| rustc::ty::Const::from_value(cx.tcx, val, ty)); + .map(|val| rustc_middle::ty::Const::from_value(cx.tcx, val, ty)); if let Some(Constant::Int(val)) = constant.and_then(miri_to_const) { if let ty::Adt(adt, _) = ty.kind { if adt.is_enum() { diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index db55e5ed141..1ec60a0e6e6 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,11 +1,11 @@ -use rustc::ty::layout::LayoutOf; -use rustc::ty::{self, Ty}; use rustc_hir::intravisit; use rustc_hir::{self, Body, FnDecl, HirId, HirIdSet, ItemKind, Node}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; +use rustc_target::abi::LayoutOf; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use crate::utils::span_lint; @@ -92,7 +92,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { } // TODO: Replace with Map::is_argument(..) when it's fixed -fn is_argument(map: rustc::hir::map::Map<'_>, id: HirId) -> bool { +fn is_argument(map: rustc_middle::hir::map::Map<'_>, id: HirId) -> bool { match map.find(id) { Some(Node::Binding(_)) => (), _ => return false, diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index c84ea44901c..1a1a40902c2 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -1,9 +1,9 @@ use if_chain::if_chain; -use rustc::lint::in_external_macro; -use rustc::ty::{self, Ty}; use rustc_errors::Applicability; use rustc_hir::{def_id, Expr, ExprKind, Param, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::{ diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 9cf0d3ba26f..48b761260a5 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -1,10 +1,10 @@ use crate::utils::{get_parent_expr, span_lint, span_lint_and_note}; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::ty; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{def, BinOpKind, Block, Expr, ExprKind, Guard, HirId, Local, Node, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/fallible_impl_from.rs b/clippy_lints/src/fallible_impl_from.rs index 06608772c8a..8e45a09b489 100644 --- a/clippy_lints/src/fallible_impl_from.rs +++ b/clippy_lints/src/fallible_impl_from.rs @@ -1,10 +1,12 @@ -use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT, OPTION, RESULT}; -use crate::utils::{is_expn_of, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty}; +use crate::utils::paths::{BEGIN_PANIC, BEGIN_PANIC_FMT, FROM_TRAIT}; +use crate::utils::{ + is_expn_of, is_type_diagnostic_item, match_def_path, method_chain_args, span_lint_and_then, walk_ptrs_ty, +}; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::ty::{self, Ty}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; @@ -76,7 +78,9 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it // check for `unwrap` if let Some(arglists) = method_chain_args(expr, &["unwrap"]) { let reciever_ty = walk_ptrs_ty(self.tables.expr_ty(&arglists[0][0])); - if match_type(self.lcx, reciever_ty, &OPTION) || match_type(self.lcx, reciever_ty, &RESULT) { + if is_type_diagnostic_item(self.lcx, reciever_ty, sym!(option_type)) + || is_type_diagnostic_item(self.lcx, reciever_ty, sym!(result_type)) + { self.result.push(expr.span); } } @@ -124,10 +128,3 @@ fn lint_impl_body<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, impl_span: Span, impl_it } } } - -fn match_type(cx: &LateContext<'_, '_>, ty: Ty<'_>, path: &[&str]) -> bool { - match ty.kind { - ty::Adt(adt, _) => match_def_path(cx, adt.did, path), - _ => false, - } -} diff --git a/clippy_lints/src/float_literal.rs b/clippy_lints/src/float_literal.rs index 55a9f61242b..3a52b1d3fc2 100644 --- a/clippy_lints/src/float_literal.rs +++ b/clippy_lints/src/float_literal.rs @@ -1,12 +1,12 @@ use crate::utils::{numeric_literal, span_lint_and_sugg}; use if_chain::if_chain; -use rustc::ty; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use std::{f32, f64, fmt}; +use std::fmt; declare_clippy_lint! { /// **What it does:** Checks for float literals with a precision greater diff --git a/clippy_lints/src/floating_point_arithmetic.rs b/clippy_lints/src/floating_point_arithmetic.rs index cee14dc893b..86317fb8bd5 100644 --- a/clippy_lints/src/floating_point_arithmetic.rs +++ b/clippy_lints/src/floating_point_arithmetic.rs @@ -4,10 +4,10 @@ use crate::consts::{ }; use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq}; use if_chain::if_chain; -use rustc::ty; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index 10bc2f12f25..30795f537ea 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -91,7 +91,7 @@ fn on_argumentv1_new<'a, 'tcx>( if pats.len() == 1; then { let ty = walk_ptrs_ty(cx.tables.pat_ty(&pats[0])); - if ty.kind != rustc::ty::Str && !match_type(cx, ty, &paths::STRING) { + if ty.kind != rustc_middle::ty::Str && !match_type(cx, ty, &paths::STRING) { return None; } if let ExprKind::Lit(ref lit) = format_args.kind { diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index a05f911c4c5..8f5f82b0a2c 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -1,8 +1,8 @@ use crate::utils::{differing_macro_contexts, snippet_opt, span_lint_and_help, span_lint_and_note}; use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_ast::ast::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; use rustc_lint::{EarlyContext, EarlyLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 697486c1af0..cf1b65a0166 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -3,9 +3,6 @@ use crate::utils::{ must_use_attr, qpath_res, return_ty, snippet, snippet_opt, span_lint, span_lint_and_help, span_lint_and_then, trait_ref_of_method, type_is_unsafe_function, }; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; -use rustc::ty::{self, Ty}; use rustc_ast::ast::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -13,6 +10,9 @@ use rustc_hir as hir; use rustc_hir::intravisit; use rustc_hir::{def::Res, def_id::DefId}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use rustc_target::spec::abi::Abi; diff --git a/clippy_lints/src/get_last_with_len.rs b/clippy_lints/src/get_last_with_len.rs index e4bad5ca5c5..c32e0a2290d 100644 --- a/clippy_lints/src/get_last_with_len.rs +++ b/clippy_lints/src/get_last_with_len.rs @@ -8,7 +8,6 @@ use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; -use rustc_span::symbol::Symbol; declare_clippy_lint! { /// **What it does:** Checks for using `x.get(x.len() - 1)` instead of @@ -51,12 +50,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen { if let ExprKind::MethodCall(ref path, _, ref args) = expr.kind; // Method name is "get" - if path.ident.name == Symbol::intern("get"); + if path.ident.name == sym!(get); // Argument 0 (the struct we're calling the method on) is a vector if let Some(struct_calling_on) = args.get(0); let struct_ty = cx.tables.expr_ty(struct_calling_on); - if is_type_diagnostic_item(cx, struct_ty, Symbol::intern("vec_type")); + if is_type_diagnostic_item(cx, struct_ty, sym!(vec_type)); // Argument to "get" is a subtraction if let Some(get_index_arg) = args.get(1); @@ -71,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for GetLastWithLen { // LHS of subtraction is "x.len()" if let ExprKind::MethodCall(arg_lhs_path, _, lhs_args) = &lhs.kind; - if arg_lhs_path.ident.name == Symbol::intern("len"); + if arg_lhs_path.ident.name == sym!(len); if let Some(arg_lhs_struct) = lhs_args.get(0); // The two vectors referenced (x in x.get(...) and in x.len()) diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index abd546870aa..088e4ab1921 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -1,6 +1,6 @@ -use rustc::ty; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/if_let_some_result.rs b/clippy_lints/src/if_let_some_result.rs index 33e2471d5b8..9b13f760924 100644 --- a/clippy_lints/src/if_let_some_result.rs +++ b/clippy_lints/src/if_let_some_result.rs @@ -1,7 +1,7 @@ -use crate::utils::{match_type, method_chain_args, paths, snippet_with_applicability, span_lint_and_sugg}; +use crate::utils::{is_type_diagnostic_item, method_chain_args, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{print, Expr, ExprKind, MatchSource, PatKind, QPath}; +use rustc_hir::{Expr, ExprKind, MatchSource, PatKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -45,8 +45,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OkIfLet { if let ExprKind::MethodCall(_, ok_span, ref result_types) = op.kind; //check is expr.ok() has type Result<T,E>.ok() if let PatKind::TupleStruct(QPath::Resolved(_, ref x), ref y, _) = body[0].pat.kind; //get operation if method_chain_args(op, &["ok"]).is_some(); //test to see if using ok() methoduse std::marker::Sized; - let is_result_type = match_type(cx, cx.tables.expr_ty(&result_types[0]), &paths::RESULT); - if print::to_string(print::NO_ANN, |s| s.print_path(x, false)) == "Some" && is_result_type; + if is_type_diagnostic_item(cx, cx.tables.expr_ty(&result_types[0]), sym!(result_type)); + if rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(x, false)) == "Some"; then { let mut applicability = Applicability::MachineApplicable; diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 9b6e243f5f0..271df5b03e3 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -1,9 +1,9 @@ //! lint on if branches that could be swapped so no `!` operation is necessary //! on the condition -use rustc::lint::in_external_macro; use rustc_ast::ast::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::span_lint_and_help; diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index d968a928c33..8b87f4c896a 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -135,11 +135,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); // Building MIR for `fn`s with unsatisfiable preds results in ICE. - if fn_has_unsatisfiable_preds(cx, def_id) { + if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) { return; } - let mir = cx.tcx.optimized_mir(def_id); + let mir = cx.tcx.optimized_mir(def_id.to_def_id()); // checking return type through MIR, HIR is not able to determine inferred closure return types // make sure it's not a macro diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 65d2dd58106..a2b1085a36e 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -2,10 +2,10 @@ use crate::consts::{constant, Constant}; use crate::utils::{higher, span_lint, span_lint_and_help}; -use rustc::ty; use rustc_ast::ast::RangeLimits; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/large_enum_variant.rs b/clippy_lints/src/large_enum_variant.rs index 39c8c4cfa69..00bbba64841 100644 --- a/clippy_lints/src/large_enum_variant.rs +++ b/clippy_lints/src/large_enum_variant.rs @@ -1,21 +1,24 @@ //! lint when there is a large size difference between variants on an enum use crate::utils::{snippet_opt, span_lint_and_then}; -use rustc::ty::layout::LayoutOf; use rustc_errors::Applicability; use rustc_hir::{Item, ItemKind, VariantData}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; +use rustc_target::abi::LayoutOf; declare_clippy_lint! { /// **What it does:** Checks for large size differences between variants on /// `enum`s. /// /// **Why is this bad?** Enum size is bounded by the largest variant. Having a - /// large variant - /// can penalize the memory layout of that enum. + /// large variant can penalize the memory layout of that enum. /// - /// **Known problems:** None. + /// **Known problems:** This lint obviously cannot take the distribution of + /// variants in your running program into account. It is possible that the + /// smaller variants make up less than 1% of all instances, in which case + /// the overhead is negligible and the boxing is counter-productive. Always + /// measure the change this lint suggests. /// /// **Example:** /// ```rust @@ -52,8 +55,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let ty = cx.tcx.type_of(did); let adt = ty.ty_adt_def().expect("already checked whether this is an enum"); - let mut smallest_variant: Option<(_, _)> = None; let mut largest_variant: Option<(_, _)> = None; + let mut second_variant: Option<(_, _)> = None; for (i, variant) in adt.variants.iter().enumerate() { let size: u64 = variant @@ -69,12 +72,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { let grouped = (size, (i, variant)); - update_if(&mut smallest_variant, grouped, |a, b| b.0 <= a.0); - update_if(&mut largest_variant, grouped, |a, b| b.0 >= a.0); + if grouped.0 >= largest_variant.map_or(0, |x| x.0) { + second_variant = largest_variant; + largest_variant = Some(grouped); + } } - if let (Some(smallest), Some(largest)) = (smallest_variant, largest_variant) { - let difference = largest.0 - smallest.0; + if let (Some(largest), Some(second)) = (largest_variant, second_variant) { + let difference = largest.0 - second.0; if difference > self.maximum_size_difference_allowed { let (i, variant) = largest.1; @@ -114,16 +119,3 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LargeEnumVariant { } } } - -fn update_if<T, F>(old: &mut Option<T>, new: T, f: F) -where - F: Fn(&T, &T) -> bool, -{ - if let Some(ref mut val) = *old { - if f(val, &new) { - *val = new; - } - } else { - *old = Some(new); - } -} diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs index e08042bcbb2..f67fce9697a 100644 --- a/clippy_lints/src/large_stack_arrays.rs +++ b/clippy_lints/src/large_stack_arrays.rs @@ -1,7 +1,7 @@ -use rustc::mir::interpret::ConstValue; -use rustc::ty::{self, ConstKind}; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::mir::interpret::ConstValue; +use rustc_middle::ty::{self, ConstKind}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use if_chain::if_chain; diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 00cfb3b718d..5d94013cb65 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -1,11 +1,11 @@ use crate::utils::{get_item_name, snippet_with_applicability, span_lint, span_lint_and_sugg, walk_ptrs_ty}; -use rustc::ty; use rustc_ast::ast::{LitKind, Name}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def_id::DefId; use rustc_hir::{AssocItemKind, BinOpKind, Expr, ExprKind, ImplItemRef, Item, ItemKind, TraitItemRef}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{Span, Spanned}; @@ -121,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LenZero { fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_items: &[TraitItemRef]) { fn is_named_self(cx: &LateContext<'_, '_>, item: &TraitItemRef, name: &str) -> bool { item.ident.name.as_str() == name - && if let AssocItemKind::Method { has_self } = item.kind { + && if let AssocItemKind::Fn { has_self } = item.kind { has_self && { let did = cx.tcx.hir().local_def_id(item.id.hir_id); cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 @@ -149,8 +149,8 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i .iter() .flat_map(|&i| cx.tcx.associated_items(i).in_definition_order()) .any(|i| { - i.kind == ty::AssocKind::Method - && i.method_has_self_argument + i.kind == ty::AssocKind::Fn + && i.fn_has_self_parameter && i.ident.name == sym!(is_empty) && cx.tcx.fn_sig(i.def_id).inputs().skip_binder().len() == 1 }); @@ -172,7 +172,7 @@ fn check_trait_items(cx: &LateContext<'_, '_>, visited_trait: &Item<'_>, trait_i fn check_impl_items(cx: &LateContext<'_, '_>, item: &Item<'_>, impl_items: &[ImplItemRef<'_>]) { fn is_named_self(cx: &LateContext<'_, '_>, item: &ImplItemRef<'_>, name: &str) -> bool { item.ident.name.as_str() == name - && if let AssocItemKind::Method { has_self } = item.kind { + && if let AssocItemKind::Fn { has_self } = item.kind { has_self && { let did = cx.tcx.hir().local_def_id(item.id.hir_id); cx.tcx.fn_sig(did).inputs().skip_binder().len() == 1 @@ -261,7 +261,7 @@ fn check_len( fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { /// Gets an `AssocItem` and return true if it matches `is_empty(self)`. fn is_is_empty(cx: &LateContext<'_, '_>, item: &ty::AssocItem) -> bool { - if let ty::AssocKind::Method = item.kind { + if let ty::AssocKind::Fn = item.kind { if item.ident.name.as_str() == "is_empty" { let sig = cx.tcx.fn_sig(item.def_id); let ty = sig.skip_binder(); diff --git a/clippy_lints/src/let_if_seq.rs b/clippy_lints/src/let_if_seq.rs index d5343852208..dbf86ba3124 100644 --- a/clippy_lints/src/let_if_seq.rs +++ b/clippy_lints/src/let_if_seq.rs @@ -1,12 +1,12 @@ use crate::utils::{higher, qpath_res, snippet, span_lint_and_then}; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::intravisit; use rustc_hir::BindingAnnotation; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/let_underscore.rs b/clippy_lints/src/let_underscore.rs index 5690a12141b..f8f84f3d42d 100644 --- a/clippy_lints/src/let_underscore.rs +++ b/clippy_lints/src/let_underscore.rs @@ -1,7 +1,8 @@ use if_chain::if_chain; -use rustc::lint::in_external_macro; -use rustc_hir::{PatKind, Stmt, StmtKind}; +use rustc_hir::{Local, PatKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::subst::GenericArgKind; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::{is_must_use_func_call, is_must_use_ty, match_type, paths, span_lint_and_help}; @@ -66,22 +67,28 @@ const SYNC_GUARD_PATHS: [&[&str]; 3] = [ ]; impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore { - fn check_stmt(&mut self, cx: &LateContext<'_, '_>, stmt: &Stmt<'_>) { - if in_external_macro(cx.tcx.sess, stmt.span) { + fn check_local(&mut self, cx: &LateContext<'_, '_>, local: &Local<'_>) { + if in_external_macro(cx.tcx.sess, local.span) { return; } if_chain! { - if let StmtKind::Local(ref local) = stmt.kind; if let PatKind::Wild = local.pat.kind; if let Some(ref init) = local.init; then { - let check_ty = |ty| SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, ty, path)); - if cx.tables.expr_ty(init).walk().any(check_ty) { + let init_ty = cx.tables.expr_ty(init); + let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => { + SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path)) + }, + + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }); + if contains_sync_guard { span_lint_and_help( cx, LET_UNDERSCORE_LOCK, - stmt.span, + local.span, "non-binding let on a synchronization lock", "consider using an underscore-prefixed named \ binding or dropping explicitly with `std::mem::drop`" @@ -90,7 +97,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore { span_lint_and_help( cx, LET_UNDERSCORE_MUST_USE, - stmt.span, + local.span, "non-binding let on an expression with `#[must_use]` type", "consider explicitly using expression value" ) @@ -98,7 +105,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnderscore { span_lint_and_help( cx, LET_UNDERSCORE_MUST_USE, - stmt.span, + local.span, "non-binding let on a result of a `#[must_use]` function", "consider explicitly using function result" ) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index b701f4fee31..cb9fcfca8a1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -18,8 +18,6 @@ #[allow(unused_extern_crates)] extern crate fmt_macros; #[allow(unused_extern_crates)] -extern crate rustc; -#[allow(unused_extern_crates)] extern crate rustc_ast; #[allow(unused_extern_crates)] extern crate rustc_ast_pretty; @@ -34,6 +32,8 @@ extern crate rustc_errors; #[allow(unused_extern_crates)] extern crate rustc_hir; #[allow(unused_extern_crates)] +extern crate rustc_hir_pretty; +#[allow(unused_extern_crates)] extern crate rustc_index; #[allow(unused_extern_crates)] extern crate rustc_infer; @@ -42,6 +42,8 @@ extern crate rustc_lexer; #[allow(unused_extern_crates)] extern crate rustc_lint; #[allow(unused_extern_crates)] +extern crate rustc_middle; +#[allow(unused_extern_crates)] extern crate rustc_mir; #[allow(unused_extern_crates)] extern crate rustc_parse; @@ -80,7 +82,7 @@ use rustc_session::Session; /// ``` /// # #![feature(rustc_private)] /// # #[allow(unused_extern_crates)] -/// # extern crate rustc; +/// # extern crate rustc_middle; /// # #[allow(unused_extern_crates)] /// # extern crate rustc_session; /// # #[macro_use] @@ -168,157 +170,157 @@ mod consts; mod utils; // begin lints modules, do not remove this comment, it’s used in `update_lints` -pub mod approx_const; -pub mod arithmetic; -pub mod as_conversions; -pub mod assertions_on_constants; -pub mod assign_ops; -pub mod atomic_ordering; -pub mod attrs; -pub mod bit_mask; -pub mod blacklisted_name; -pub mod block_in_if_condition; -pub mod booleans; -pub mod bytecount; -pub mod cargo_common_metadata; -pub mod checked_conversions; -pub mod cognitive_complexity; -pub mod collapsible_if; -pub mod comparison_chain; -pub mod copies; -pub mod copy_iterator; -pub mod dbg_macro; -pub mod default_trait_access; -pub mod derive; -pub mod doc; -pub mod double_comparison; -pub mod double_parens; -pub mod drop_bounds; -pub mod drop_forget_ref; -pub mod duration_subsec; -pub mod else_if_without_else; -pub mod empty_enum; -pub mod entry; -pub mod enum_clike; -pub mod enum_variants; -pub mod eq_op; -pub mod erasing_op; -pub mod escape; -pub mod eta_reduction; -pub mod eval_order_dependence; -pub mod excessive_bools; -pub mod exit; -pub mod explicit_write; -pub mod fallible_impl_from; -pub mod float_literal; -pub mod floating_point_arithmetic; -pub mod format; -pub mod formatting; -pub mod functions; -pub mod get_last_with_len; -pub mod identity_conversion; -pub mod identity_op; -pub mod if_let_some_result; -pub mod if_not_else; -pub mod implicit_return; -pub mod indexing_slicing; -pub mod infinite_iter; -pub mod inherent_impl; -pub mod inherent_to_string; -pub mod inline_fn_without_body; -pub mod int_plus_one; -pub mod integer_division; -pub mod items_after_statements; -pub mod large_enum_variant; -pub mod large_stack_arrays; -pub mod len_zero; -pub mod let_if_seq; -pub mod let_underscore; -pub mod lifetimes; -pub mod literal_representation; -pub mod loops; -pub mod macro_use; -pub mod main_recursion; -pub mod map_clone; -pub mod map_unit_fn; -pub mod matches; -pub mod mem_discriminant; -pub mod mem_forget; -pub mod mem_replace; -pub mod methods; -pub mod minmax; -pub mod misc; -pub mod misc_early; -pub mod missing_const_for_fn; -pub mod missing_doc; -pub mod missing_inline; -pub mod modulo_arithmetic; -pub mod multiple_crate_versions; -pub mod mut_key; -pub mod mut_mut; -pub mod mut_reference; -pub mod mutable_debug_assertion; -pub mod mutex_atomic; -pub mod needless_bool; -pub mod needless_borrow; -pub mod needless_borrowed_ref; -pub mod needless_continue; -pub mod needless_pass_by_value; -pub mod needless_update; -pub mod neg_cmp_op_on_partial_ord; -pub mod neg_multiply; -pub mod new_without_default; -pub mod no_effect; -pub mod non_copy_const; -pub mod non_expressive_names; -pub mod open_options; -pub mod option_env_unwrap; -pub mod overflow_check_conditional; -pub mod panic_unimplemented; -pub mod partialeq_ne_impl; -pub mod path_buf_push_overwrite; -pub mod precedence; -pub mod ptr; -pub mod ptr_offset_with_cast; -pub mod question_mark; -pub mod ranges; -pub mod redundant_clone; -pub mod redundant_field_names; -pub mod redundant_pattern_matching; -pub mod redundant_pub_crate; -pub mod redundant_static_lifetimes; -pub mod reference; -pub mod regex; -pub mod replace_consts; -pub mod returns; -pub mod serde_api; -pub mod shadow; -pub mod single_component_path_imports; -pub mod slow_vector_initialization; -pub mod strings; -pub mod suspicious_trait_impl; -pub mod swap; -pub mod tabs_in_doc_comments; -pub mod temporary_assignment; -pub mod to_digit_is_some; -pub mod trait_bounds; -pub mod transmute; -pub mod transmuting_null; -pub mod trivially_copy_pass_by_ref; -pub mod try_err; -pub mod types; -pub mod unicode; -pub mod unsafe_removed_from_name; -pub mod unused_io_amount; -pub mod unused_self; -pub mod unwrap; -pub mod use_self; -pub mod vec; -pub mod verbose_file_reads; -pub mod wildcard_dependencies; -pub mod wildcard_imports; -pub mod write; -pub mod zero_div_zero; +mod approx_const; +mod arithmetic; +mod as_conversions; +mod assertions_on_constants; +mod assign_ops; +mod atomic_ordering; +mod attrs; +mod bit_mask; +mod blacklisted_name; +mod block_in_if_condition; +mod booleans; +mod bytecount; +mod cargo_common_metadata; +mod checked_conversions; +mod cognitive_complexity; +mod collapsible_if; +mod comparison_chain; +mod copies; +mod copy_iterator; +mod dbg_macro; +mod default_trait_access; +mod derive; +mod doc; +mod double_comparison; +mod double_parens; +mod drop_bounds; +mod drop_forget_ref; +mod duration_subsec; +mod else_if_without_else; +mod empty_enum; +mod entry; +mod enum_clike; +mod enum_variants; +mod eq_op; +mod erasing_op; +mod escape; +mod eta_reduction; +mod eval_order_dependence; +mod excessive_bools; +mod exit; +mod explicit_write; +mod fallible_impl_from; +mod float_literal; +mod floating_point_arithmetic; +mod format; +mod formatting; +mod functions; +mod get_last_with_len; +mod identity_conversion; +mod identity_op; +mod if_let_some_result; +mod if_not_else; +mod implicit_return; +mod indexing_slicing; +mod infinite_iter; +mod inherent_impl; +mod inherent_to_string; +mod inline_fn_without_body; +mod int_plus_one; +mod integer_division; +mod items_after_statements; +mod large_enum_variant; +mod large_stack_arrays; +mod len_zero; +mod let_if_seq; +mod let_underscore; +mod lifetimes; +mod literal_representation; +mod loops; +mod macro_use; +mod main_recursion; +mod map_clone; +mod map_unit_fn; +mod matches; +mod mem_discriminant; +mod mem_forget; +mod mem_replace; +mod methods; +mod minmax; +mod misc; +mod misc_early; +mod missing_const_for_fn; +mod missing_doc; +mod missing_inline; +mod modulo_arithmetic; +mod multiple_crate_versions; +mod mut_key; +mod mut_mut; +mod mut_reference; +mod mutable_debug_assertion; +mod mutex_atomic; +mod needless_bool; +mod needless_borrow; +mod needless_borrowed_ref; +mod needless_continue; +mod needless_pass_by_value; +mod needless_update; +mod neg_cmp_op_on_partial_ord; +mod neg_multiply; +mod new_without_default; +mod no_effect; +mod non_copy_const; +mod non_expressive_names; +mod open_options; +mod option_env_unwrap; +mod overflow_check_conditional; +mod panic_unimplemented; +mod partialeq_ne_impl; +mod path_buf_push_overwrite; +mod precedence; +mod ptr; +mod ptr_offset_with_cast; +mod question_mark; +mod ranges; +mod redundant_clone; +mod redundant_field_names; +mod redundant_pattern_matching; +mod redundant_pub_crate; +mod redundant_static_lifetimes; +mod reference; +mod regex; +mod returns; +mod serde_api; +mod shadow; +mod single_component_path_imports; +mod slow_vector_initialization; +mod strings; +mod suspicious_trait_impl; +mod swap; +mod tabs_in_doc_comments; +mod temporary_assignment; +mod to_digit_is_some; +mod trait_bounds; +mod transmute; +mod transmuting_null; +mod trivially_copy_pass_by_ref; +mod try_err; +mod types; +mod unicode; +mod unnamed_address; +mod unsafe_removed_from_name; +mod unused_io_amount; +mod unused_self; +mod unwrap; +mod use_self; +mod vec; +mod verbose_file_reads; +mod wildcard_dependencies; +mod wildcard_imports; +mod write; +mod zero_div_zero; // end lints modules, do not remove this comment, it’s used in `update_lints` pub use crate::utils::conf::Conf; @@ -468,6 +470,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: "clippy::unused_label", "this lint has been uplifted to rustc and is now called `unused_labels`", ); + store.register_removed( + "clippy::replace_consts", + "associated-constants `MIN`/`MAX` of integers are prefer to `{min,max}_value()` and module constants", + ); // end deprecated lints, do not remove this comment, it’s used in `update_lints` // begin register lints, do not remove this comment, it’s used in `update_lints` @@ -660,6 +666,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &methods::OPTION_UNWRAP_USED, &methods::OR_FUN_CALL, &methods::RESULT_EXPECT_USED, + &methods::RESULT_MAP_OR_INTO_OPTION, &methods::RESULT_MAP_UNWRAP_OR_ELSE, &methods::RESULT_UNWRAP_USED, &methods::SEARCH_IS_SOME, @@ -753,7 +760,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: ®ex::INVALID_REGEX, ®ex::REGEX_MACRO, ®ex::TRIVIAL_REGEX, - &replace_consts::REPLACE_CONSTS, &returns::LET_AND_RETURN, &returns::NEEDLESS_RETURN, &returns::UNUSED_UNIT, @@ -806,6 +812,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &types::LET_UNIT_VALUE, &types::LINKEDLIST, &types::OPTION_OPTION, + &types::REDUNDANT_ALLOCATION, &types::TYPE_COMPLEXITY, &types::UNIT_ARG, &types::UNIT_CMP, @@ -814,12 +821,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &unicode::NON_ASCII_LITERAL, &unicode::UNICODE_NOT_NFC, &unicode::ZERO_WIDTH_SPACE, + &unnamed_address::FN_ADDRESS_COMPARISONS, + &unnamed_address::VTABLE_ADDRESS_COMPARISONS, &unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, &unused_io_amount::UNUSED_IO_AMOUNT, &unused_self::UNUSED_SELF, &unwrap::PANICKING_UNWRAP, &unwrap::UNNECESSARY_UNWRAP, &use_self::USE_SELF, + &utils::internal_lints::CLIPPY_LINTS_INTERNAL, + &utils::internal_lints::COMPILER_LINT_FUNCTIONS, + &utils::internal_lints::DEFAULT_LINT, + &utils::internal_lints::LINT_WITHOUT_LINT_PASS, + &utils::internal_lints::OUTER_EXPN_EXPN_DATA, + &utils::internal_lints::PRODUCE_ICE, &vec::USELESS_VEC, &verbose_file_reads::VERBOSE_FILE_READS, &wildcard_dependencies::WILDCARD_DEPENDENCIES, @@ -951,7 +966,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_late_pass(|| box identity_conversion::IdentityConversion::default()); store.register_late_pass(|| box types::ImplicitHasher); store.register_late_pass(|| box fallible_impl_from::FallibleImplFrom); - store.register_late_pass(|| box replace_consts::ReplaceConsts); store.register_late_pass(|| box types::UnitArg); store.register_late_pass(|| box double_comparison::DoubleComparisons); store.register_late_pass(|| box question_mark::QuestionMark); @@ -1024,6 +1038,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_early_pass(|| box macro_use::MacroUseImports); store.register_late_pass(|| box verbose_file_reads::VerboseFileReads); store.register_late_pass(|| box redundant_pub_crate::RedundantPubCrate::default()); + store.register_late_pass(|| box unnamed_address::UnnamedAddress); store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![ LintId::of(&arithmetic::FLOAT_ARITHMETIC), @@ -1062,6 +1077,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&shadow::SHADOW_REUSE), LintId::of(&shadow::SHADOW_SAME), LintId::of(&strings::STRING_ADD), + LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), LintId::of(&write::PRINT_STDOUT), LintId::of(&write::USE_DEBUG), ]); @@ -1089,6 +1105,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&items_after_statements::ITEMS_AFTER_STATEMENTS), LintId::of(&large_stack_arrays::LARGE_STACK_ARRAYS), LintId::of(&literal_representation::LARGE_DIGIT_GROUPS), + LintId::of(&literal_representation::UNREADABLE_LITERAL), LintId::of(&loops::EXPLICIT_INTO_ITER_LOOP), LintId::of(&loops::EXPLICIT_ITER_LOOP), LintId::of(¯o_use::MACRO_USE_IMPORTS), @@ -1096,6 +1113,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::FILTER_MAP), LintId::of(&methods::FILTER_MAP_NEXT), LintId::of(&methods::FIND_MAP), + LintId::of(&methods::INEFFICIENT_TO_STRING), LintId::of(&methods::MAP_FLATTEN), LintId::of(&methods::OPTION_MAP_UNWRAP_OR), LintId::of(&methods::OPTION_MAP_UNWRAP_OR_ELSE), @@ -1107,17 +1125,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&needless_pass_by_value::NEEDLESS_PASS_BY_VALUE), LintId::of(&non_expressive_names::SIMILAR_NAMES), LintId::of(&ranges::RANGE_PLUS_ONE), - LintId::of(&replace_consts::REPLACE_CONSTS), LintId::of(&shadow::SHADOW_UNRELATED), LintId::of(&strings::STRING_ADD_ASSIGN), LintId::of(&trait_bounds::TYPE_REPETITION_IN_BOUNDS), + LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF), LintId::of(&types::CAST_LOSSLESS), LintId::of(&types::CAST_POSSIBLE_TRUNCATION), LintId::of(&types::CAST_POSSIBLE_WRAP), LintId::of(&types::CAST_PRECISION_LOSS), LintId::of(&types::CAST_SIGN_LOSS), + LintId::of(&types::IMPLICIT_HASHER), LintId::of(&types::INVALID_UPCAST_COMPARISONS), + LintId::of(&types::LET_UNIT_VALUE), LintId::of(&types::LINKEDLIST), + LintId::of(&types::OPTION_OPTION), LintId::of(&unicode::NON_ASCII_LITERAL), LintId::of(&unicode::UNICODE_NOT_NFC), LintId::of(&unused_self::UNUSED_SELF), @@ -1153,7 +1174,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&booleans::LOGIC_BUG), LintId::of(&booleans::NONMINIMAL_BOOL), LintId::of(&bytecount::NAIVE_BYTECOUNT), - LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY), LintId::of(&collapsible_if::COLLAPSIBLE_IF), LintId::of(&comparison_chain::COMPARISON_CHAIN), LintId::of(&copies::IFS_SAME_COND), @@ -1210,7 +1230,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&lifetimes::NEEDLESS_LIFETIMES), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), LintId::of(&literal_representation::MISTYPED_LITERAL_SUFFIXES), - LintId::of(&literal_representation::UNREADABLE_LITERAL), LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::EXPLICIT_COUNTER_LOOP), LintId::of(&loops::FOR_KV_MAP), @@ -1250,7 +1269,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::EXPECT_FUN_CALL), LintId::of(&methods::FILTER_NEXT), LintId::of(&methods::FLAT_MAP_IDENTITY), - LintId::of(&methods::INEFFICIENT_TO_STRING), LintId::of(&methods::INTO_ITER_ON_REF), LintId::of(&methods::ITERATOR_STEP_BY_ZERO), LintId::of(&methods::ITER_CLONED_COLLECT), @@ -1264,6 +1282,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::OPTION_AS_REF_DEREF), LintId::of(&methods::OPTION_MAP_OR_NONE), LintId::of(&methods::OR_FUN_CALL), + LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION), LintId::of(&methods::SEARCH_IS_SOME), LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), LintId::of(&methods::SINGLE_CHAR_PATTERN), @@ -1356,7 +1375,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::UNSOUND_COLLECTION_TRANSMUTE), LintId::of(&transmute::WRONG_TRANSMUTE), LintId::of(&transmuting_null::TRANSMUTING_NULL), - LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF), LintId::of(&try_err::TRY_ERR), LintId::of(&types::ABSURD_EXTREME_COMPARISONS), LintId::of(&types::BORROWED_BOX), @@ -1366,21 +1384,20 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::CHAR_LIT_AS_U8), LintId::of(&types::FN_TO_NUMERIC_CAST), LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), - LintId::of(&types::IMPLICIT_HASHER), - LintId::of(&types::LET_UNIT_VALUE), - LintId::of(&types::OPTION_OPTION), + LintId::of(&types::REDUNDANT_ALLOCATION), LintId::of(&types::TYPE_COMPLEXITY), LintId::of(&types::UNIT_ARG), LintId::of(&types::UNIT_CMP), LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unicode::ZERO_WIDTH_SPACE), + LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), + LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), LintId::of(&unwrap::UNNECESSARY_UNWRAP), LintId::of(&vec::USELESS_VEC), - LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINT_LITERAL), LintId::of(&write::PRINT_WITH_NEWLINE), @@ -1418,7 +1435,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&len_zero::LEN_ZERO), LintId::of(&let_if_seq::USELESS_LET_IF_SEQ), LintId::of(&literal_representation::INCONSISTENT_DIGIT_GROUPING), - LintId::of(&literal_representation::UNREADABLE_LITERAL), LintId::of(&loops::EMPTY_LOOP), LintId::of(&loops::FOR_KV_MAP), LintId::of(&loops::NEEDLESS_RANGE_LOOP), @@ -1443,6 +1459,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&methods::NEW_RET_NO_SELF), LintId::of(&methods::OK_EXPECT), LintId::of(&methods::OPTION_MAP_OR_NONE), + LintId::of(&methods::RESULT_MAP_OR_INTO_OPTION), LintId::of(&methods::SHOULD_IMPLEMENT_TRAIT), LintId::of(&methods::STRING_EXTEND_CHARS), LintId::of(&methods::UNNECESSARY_FOLD), @@ -1478,8 +1495,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&try_err::TRY_ERR), LintId::of(&types::FN_TO_NUMERIC_CAST), LintId::of(&types::FN_TO_NUMERIC_CAST_WITH_TRUNCATION), - LintId::of(&types::IMPLICIT_HASHER), - LintId::of(&types::LET_UNIT_VALUE), LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME), LintId::of(&write::PRINTLN_EMPTY_STRING), LintId::of(&write::PRINT_LITERAL), @@ -1493,7 +1508,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&assign_ops::MISREFACTORED_ASSIGN_OP), LintId::of(&attrs::DEPRECATED_CFG_ATTR), LintId::of(&booleans::NONMINIMAL_BOOL), - LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY), LintId::of(&double_comparison::DOUBLE_COMPARISONS), LintId::of(&double_parens::DOUBLE_PARENS), LintId::of(&duration_subsec::DURATION_SUBSEC), @@ -1557,13 +1571,11 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&transmute::TRANSMUTE_PTR_TO_REF), LintId::of(&types::BORROWED_BOX), LintId::of(&types::CHAR_LIT_AS_U8), - LintId::of(&types::OPTION_OPTION), LintId::of(&types::TYPE_COMPLEXITY), LintId::of(&types::UNIT_ARG), LintId::of(&types::UNNECESSARY_CAST), LintId::of(&types::VEC_BOX), LintId::of(&unwrap::UNNECESSARY_UNWRAP), - LintId::of(&verbose_file_reads::VERBOSE_FILE_READS), LintId::of(&zero_div_zero::ZERO_DIVIDED_BY_ZERO), ]); @@ -1630,6 +1642,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&types::CAST_REF_TO_MUT), LintId::of(&types::UNIT_CMP), LintId::of(&unicode::ZERO_WIDTH_SPACE), + LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS), + LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS), LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT), LintId::of(&unwrap::PANICKING_UNWRAP), ]); @@ -1642,7 +1656,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&loops::MANUAL_MEMCPY), LintId::of(&loops::NEEDLESS_COLLECT), LintId::of(&methods::EXPECT_FUN_CALL), - LintId::of(&methods::INEFFICIENT_TO_STRING), LintId::of(&methods::ITER_NTH), LintId::of(&methods::OR_FUN_CALL), LintId::of(&methods::SINGLE_CHAR_PATTERN), @@ -1650,8 +1663,8 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mutex_atomic::MUTEX_ATOMIC), LintId::of(&redundant_clone::REDUNDANT_CLONE), LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION), - LintId::of(&trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF), LintId::of(&types::BOX_VEC), + LintId::of(&types::REDUNDANT_ALLOCATION), LintId::of(&vec::USELESS_VEC), ]); @@ -1663,6 +1676,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![ LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR), + LintId::of(&cognitive_complexity::COGNITIVE_COMPLEXITY), LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM), LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS), LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS), diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 1cdc48957e7..d80ad47ab24 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -1,5 +1,3 @@ -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{ @@ -11,13 +9,14 @@ use rustc_hir::{ ItemKind, Lifetime, LifetimeName, ParamName, QPath, TraitBoundModifier, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, WhereClause, WherePredicate, }; -use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::symbol::kw; use crate::reexport::Name; -use crate::utils::{last_path_segment, span_lint, trait_ref_of_method}; +use crate::utils::{in_macro, last_path_segment, span_lint, trait_ref_of_method}; declare_clippy_lint! { /// **What it does:** Checks for lifetime annotations which can be removed by @@ -125,7 +124,7 @@ fn check_fn_inner<'a, 'tcx>( span: Span, report_extra_lifetimes: bool, ) { - if in_external_macro(cx.sess(), span) || has_where_lifetimes(cx, &generics.where_clause) { + if in_macro(span) || has_where_lifetimes(cx, &generics.where_clause) { return; } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index 9e6b63fafd0..ec7c4531ed7 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -7,10 +7,10 @@ use crate::utils::{ snippet_opt, span_lint_and_sugg, }; use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_ast::ast::{Expr, ExprKind, Lit, LitKind}; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { @@ -27,7 +27,7 @@ declare_clippy_lint! { /// let x: u64 = 61864918973511; /// ``` pub UNREADABLE_LITERAL, - style, + pedantic, "long integer literal without underscores" } @@ -186,6 +186,9 @@ impl EarlyLintPass for LiteralDigitGrouping { } } +// Length of each UUID hyphenated group in hex digits. +const UUID_GROUP_LENS: [usize; 5] = [8, 4, 4, 4, 12]; + impl LiteralDigitGrouping { fn check_lit(cx: &EarlyContext<'_>, lit: &Lit) { if_chain! { @@ -196,6 +199,10 @@ impl LiteralDigitGrouping { return; } + if Self::is_literal_uuid_formatted(&mut num_lit) { + return; + } + let result = (|| { let integral_group_size = Self::get_group_size(num_lit.integer.split('_'))?; @@ -266,6 +273,28 @@ impl LiteralDigitGrouping { } } + /// Checks whether the numeric literal matches the formatting of a UUID. + /// + /// Returns `true` if the radix is hexadecimal, and the groups match the + /// UUID format of 8-4-4-4-12. + fn is_literal_uuid_formatted(num_lit: &mut NumericLiteral<'_>) -> bool { + if num_lit.radix != Radix::Hexadecimal { + return false; + } + + // UUIDs should not have a fraction + if num_lit.fraction.is_some() { + return false; + } + + let group_sizes: Vec<usize> = num_lit.integer.split('_').map(str::len).collect(); + if UUID_GROUP_LENS.len() == group_sizes.len() { + UUID_GROUP_LENS.iter().zip(&group_sizes).all(|(&a, &b)| a == b) + } else { + false + } + } + /// Given the sizes of the digit groups of both integral and fractional /// parts, and the length /// of both parts, determine if the digits have been grouped consistently. diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 475e60736e0..66bc1cb3dc4 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -11,10 +11,6 @@ use crate::utils::{ use crate::utils::{is_type_diagnostic_item, qpath_res, same_tys, sext, sugg}; use if_chain::if_chain; use itertools::Itertools; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; -use rustc::middle::region; -use rustc::ty::{self, Ty}; use rustc_ast::ast; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::Applicability; @@ -26,9 +22,13 @@ use rustc_hir::{ }; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::middle::region; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::{BytePos, Symbol}; +use rustc_span::BytePos; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; use std::iter::{once, Iterator}; use std::mem; @@ -654,7 +654,7 @@ fn combine_branches(b1: NeverLoopResult, b2: NeverLoopResult) -> NeverLoopResult fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult { let stmts = block.stmts.iter().map(stmt_to_expr); - let expr = once(block.expr.as_ref().map(|p| &**p)); + let expr = once(block.expr.as_deref()); let mut iter = stmts.chain(expr).filter_map(|e| e); never_loop_expr_seq(&mut iter, main_loop_id) } @@ -662,7 +662,7 @@ fn never_loop_block(block: &Block<'_>, main_loop_id: HirId) -> NeverLoopResult { fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<&'tcx Expr<'tcx>> { match stmt.kind { StmtKind::Semi(ref e, ..) | StmtKind::Expr(ref e, ..) => Some(e), - StmtKind::Local(ref local) => local.init.as_ref().map(|p| &**p), + StmtKind::Local(ref local) => local.init.as_deref(), _ => None, } } @@ -720,7 +720,7 @@ fn never_loop_expr(expr: &Expr<'_>, main_loop_id: HirId) -> NeverLoopResult { ExprKind::Struct(_, _, None) | ExprKind::Yield(_, _) | ExprKind::Closure(_, _, _, _, _) - | ExprKind::InlineAsm(_) + | ExprKind::LlvmInlineAsm(_) | ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::Err => NeverLoopResult::Otherwise, @@ -804,7 +804,7 @@ fn is_slice_like<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'_>) -> bool { _ => false, }; - is_slice || is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || match_type(cx, ty, &paths::VEC_DEQUE) + is_slice || is_type_diagnostic_item(cx, ty, sym!(vec_type)) || match_type(cx, ty, &paths::VEC_DEQUE) } fn get_fixed_offset_var<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &Expr<'_>, var: HirId) -> Option<FixedOffsetVar> { @@ -922,7 +922,7 @@ fn get_indexed_assignments<'a, 'tcx>( .chain(expr.as_ref().into_iter().map(|e| Some(get_assignment(cx, &*e, var)))) .filter_map(|op| op) .collect::<Option<Vec<_>>>() - .unwrap_or_else(|| vec![]) + .unwrap_or_default() } else { get_assignment(cx, body, var).into_iter().collect() } @@ -1392,7 +1392,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>, e /// Checks for `for` loops over `Option`s and `Result`s. fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { let ty = cx.tables.expr_ty(arg); - if match_type(cx, ty, &paths::OPTION) { + if is_type_diagnostic_item(cx, ty, sym!(option_type)) { span_lint_and_help( cx, FOR_LOOP_OVER_OPTION, @@ -1408,7 +1408,7 @@ fn check_arg_type(cx: &LateContext<'_, '_>, pat: &Pat<'_>, arg: &Expr<'_>) { snippet(cx, arg.span, "_") ), ); - } else if match_type(cx, ty, &paths::RESULT) { + } else if is_type_diagnostic_item(cx, ty, sym!(result_type)) { span_lint_and_help( cx, FOR_LOOP_OVER_RESULT, @@ -1955,7 +1955,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool { // will allow further borrows afterwards let ty = cx.tables.expr_ty(e); is_iterable_array(ty, cx) || - is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || + is_type_diagnostic_item(cx, ty, sym!(vec_type)) || match_type(cx, ty, &paths::LINKED_LIST) || match_type(cx, ty, &paths::HASHMAP) || match_type(cx, ty, &paths::HASHSET) || @@ -2465,7 +2465,7 @@ fn check_needless_collect<'a, 'tcx>(expr: &'tcx Expr<'_>, cx: &LateContext<'a, ' if let Some(GenericArg::Type(ref ty)) = generic_args.args.get(0); then { let ty = cx.tables.node_type(ty.hir_id); - if is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) || + if is_type_diagnostic_item(cx, ty, sym!(vec_type)) || match_type(cx, ty, &paths::VEC_DEQUE) || match_type(cx, ty, &paths::BTREEMAP) || match_type(cx, ty, &paths::HASHMAP) { diff --git a/clippy_lints/src/map_clone.rs b/clippy_lints/src/map_clone.rs index 72227555b25..5c5cf8015f4 100644 --- a/clippy_lints/src/map_clone.rs +++ b/clippy_lints/src/map_clone.rs @@ -1,13 +1,13 @@ use crate::utils::paths; use crate::utils::{ - is_copy, match_trait_method, match_type, remove_blocks, snippet_with_applicability, span_lint_and_sugg, + is_copy, is_type_diagnostic_item, match_trait_method, remove_blocks, snippet_with_applicability, span_lint_and_sugg, }; use if_chain::if_chain; -use rustc::ty; use rustc_ast::ast::Ident; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -52,7 +52,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MapClone { if args.len() == 2; if method.ident.as_str() == "map"; let ty = cx.tables.expr_ty(&args[0]); - if match_type(cx, ty, &paths::OPTION) || match_trait_method(cx, e, &paths::ITERATOR); + if is_type_diagnostic_item(cx, ty, sym!(option_type)) || match_trait_method(cx, e, &paths::ITERATOR); if let hir::ExprKind::Closure(_, _, body_id, _, _) = args[1].kind; let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index d7ea022d888..ba10319ff46 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -1,10 +1,9 @@ -use crate::utils::paths; -use crate::utils::{iter_input_pats, match_type, method_chain_args, snippet, span_lint_and_then}; +use crate::utils::{is_type_diagnostic_item, iter_input_pats, method_chain_args, snippet, span_lint_and_then}; use if_chain::if_chain; -use rustc::ty::{self, Ty}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -206,9 +205,9 @@ fn suggestion_msg(function_type: &str, map_type: &str) -> String { fn lint_map_unit_fn(cx: &LateContext<'_, '_>, stmt: &hir::Stmt<'_>, expr: &hir::Expr<'_>, map_args: &[hir::Expr<'_>]) { let var_arg = &map_args[0]; - let (map_type, variant, lint) = if match_type(cx, cx.tables.expr_ty(var_arg), &paths::OPTION) { + let (map_type, variant, lint) = if is_type_diagnostic_item(cx, cx.tables.expr_ty(var_arg), sym!(option_type)) { ("Option", "Some", OPTION_MAP_UNIT_FN) - } else if match_type(cx, cx.tables.expr_ty(var_arg), &paths::RESULT) { + } else if is_type_diagnostic_item(cx, cx.tables.expr_ty(var_arg), sym!(result_type)) { ("Result", "Ok", RESULT_MAP_UNIT_FN) } else { return; diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 40880f78270..206a842d21c 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -3,22 +3,22 @@ use crate::utils::paths; use crate::utils::sugg::Sugg; use crate::utils::usage::is_unused; use crate::utils::{ - expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, is_wild, - match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, snippet_block, - snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, span_lint_and_then, - walk_ptrs_ty, + expr_block, get_arg_name, get_parent_expr, in_macro, indent_of, is_allowed, is_expn_of, is_refutable, + is_type_diagnostic_item, is_wild, match_qpath, match_type, match_var, multispan_sugg, remove_blocks, snippet, + snippet_block, snippet_with_applicability, span_lint_and_help, span_lint_and_note, span_lint_and_sugg, + span_lint_and_then, walk_ptrs_ty, }; use if_chain::if_chain; -use rustc::lint::in_external_macro; -use rustc::ty::{self, Ty}; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::CtorKind; use rustc_hir::{ - print, Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat, - PatKind, QPath, RangeEnd, + Arm, BindingAnnotation, Block, BorrowKind, Expr, ExprKind, Local, MatchSource, Mutability, Node, Pat, PatKind, + QPath, RangeEnd, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; use std::cmp::Ordering; @@ -447,6 +447,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Matches { #[rustfmt::skip] fn check_single_match(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>], expr: &Expr<'_>) { if arms.len() == 2 && arms[0].guard.is_none() && arms[1].guard.is_none() { + if in_macro(expr.span) { + // Don't lint match expressions present in + // macro_rules! block + return; + } if let PatKind::Or(..) = arms[0].pat.kind { // don't lint for or patterns for now, this makes // the lint noisy in unnecessary situations @@ -536,10 +541,12 @@ fn check_single_match_opt_like( if !inner.iter().all(is_wild) { return; } - print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) + rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)) }, PatKind::Binding(BindingAnnotation::Unannotated, .., ident, None) => ident.to_string(), - PatKind::Path(ref path) => print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), + PatKind::Path(ref path) => { + rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)) + }, _ => return, }; @@ -635,10 +642,10 @@ fn check_overlapping_arms<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ex: &'tcx Expr<' fn check_wild_err_arm(cx: &LateContext<'_, '_>, ex: &Expr<'_>, arms: &[Arm<'_>]) { let ex_ty = walk_ptrs_ty(cx.tables.expr_ty(ex)); - if match_type(cx, ex_ty, &paths::RESULT) { + if is_type_diagnostic_item(cx, ex_ty, sym!(result_type)) { for arm in arms { if let PatKind::TupleStruct(ref path, ref inner, _) = arm.pat.kind { - let path_str = print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)); + let path_str = rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)); if path_str == "Err" { let mut matching_wild = inner.iter().any(is_wild); let mut ident_bind_name = String::from("_"); @@ -1190,3 +1197,40 @@ where None } + +#[test] +fn test_overlapping() { + use rustc_span::source_map::DUMMY_SP; + + let sp = |s, e| SpannedRange { + span: DUMMY_SP, + node: (s, e), + }; + + assert_eq!(None, overlapping::<u8>(&[])); + assert_eq!(None, overlapping(&[sp(1, Bound::Included(4))])); + assert_eq!( + None, + overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))]) + ); + assert_eq!( + None, + overlapping(&[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(10, Bound::Included(11)) + ],) + ); + assert_eq!( + Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))), + overlapping(&[sp(1, Bound::Included(4)), sp(3, Bound::Included(6))]) + ); + assert_eq!( + Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))), + overlapping(&[ + sp(1, Bound::Included(4)), + sp(5, Bound::Included(6)), + sp(6, Bound::Included(11)) + ],) + ); +} diff --git a/clippy_lints/src/mem_replace.rs b/clippy_lints/src/mem_replace.rs index d2b1fd3a9e6..0bd4c4805b3 100644 --- a/clippy_lints/src/mem_replace.rs +++ b/clippy_lints/src/mem_replace.rs @@ -3,12 +3,13 @@ use crate::utils::{ span_lint_and_sugg, span_lint_and_then, }; use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, QPath}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; +use rustc_span::symbol::sym; declare_clippy_lint! { /// **What it does:** Checks for `mem::replace()` on an `Option` with @@ -141,7 +142,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span if let ExprKind::Path(ref repl_func_qpath) = repl_func.kind; if let Some(repl_def_id) = cx.tables.qpath_res(repl_func_qpath, repl_func.hir_id).opt_def_id(); then { - if match_def_path(cx, repl_def_id, &paths::MEM_UNINITIALIZED) { + if cx.tcx.is_diagnostic_item(sym::mem_uninitialized, repl_def_id) { span_lint_and_help( cx, MEM_REPLACE_WITH_UNINIT, @@ -149,7 +150,7 @@ fn check_replace_with_uninit(cx: &LateContext<'_, '_>, src: &Expr<'_>, expr_span "replacing with `mem::uninitialized()`", "consider using the `take_mut` crate instead", ); - } else if match_def_path(cx, repl_def_id, &paths::MEM_ZEROED) && + } else if cx.tcx.is_diagnostic_item(sym::mem_zeroed, repl_def_id) && !cx.tables.expr_ty(src).is_primitive() { span_lint_and_help( cx, diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index 1079fbf63ea..495f42700ee 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -1,10 +1,10 @@ use super::INEFFICIENT_TO_STRING; use crate::utils::{match_def_path, paths, snippet_with_applicability, span_lint_and_then, walk_ptrs_ty_depth}; use if_chain::if_chain; -use rustc::ty::{self, Ty}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_middle::ty::{self, Ty}; /// Checks for the `INEFFICIENT_TO_STRING` lint pub fn lint<'tcx>(cx: &LateContext<'_, 'tcx>, expr: &hir::Expr<'_>, arg: &hir::Expr<'_>, arg_ty: Ty<'tcx>) { diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index e6c6cb6f779..5255fec2cec 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -8,17 +8,18 @@ use std::fmt; use std::iter; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; -use rustc::ty::{self, Predicate, Ty}; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::{self, Visitor}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::{self, Predicate, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::symbol::{sym, Symbol, SymbolStr}; +use rustc_span::symbol::{sym, SymbolStr}; use crate::consts::{constant, Constant}; use crate::utils::usage::mutated_variables; @@ -331,6 +332,32 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// **What it does:** Checks for usage of `_.map_or(None, Some)`. + /// + /// **Why is this bad?** Readability, this can be written more concisely as + /// `_.ok()`. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// Bad: + /// ```rust + /// # let r: Result<u32, &str> = Ok(1); + /// assert_eq!(Some(1), r.map_or(None, Some)); + /// ``` + /// + /// Good: + /// ```rust + /// # let r: Result<u32, &str> = Ok(1); + /// assert_eq!(Some(1), r.ok()); + /// ``` + pub RESULT_MAP_OR_INTO_OPTION, + style, + "using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`" +} + +declare_clippy_lint! { /// **What it does:** Checks for usage of `_.and_then(|x| Some(y))`. /// /// **Why is this bad?** Readability, this can be written more concisely as @@ -698,12 +725,12 @@ declare_clippy_lint! { /// ["foo", "bar"].iter().map(|&s| s.to_string()); /// ``` pub INEFFICIENT_TO_STRING, - perf, + pedantic, "using `to_string` on `&&T` where `T: ToString`" } declare_clippy_lint! { - /// **What it does:** Checks for `new` not returning `Self`. + /// **What it does:** Checks for `new` not returning a type that contains `Self`. /// /// **Why is this bad?** As a convention, `new` methods are used to make a new /// instance of a type. @@ -720,9 +747,31 @@ declare_clippy_lint! { /// } /// } /// ``` + /// + /// ```rust + /// # struct Foo; + /// # struct FooError; + /// impl Foo { + /// // Good. Return type contains `Self` + /// fn new() -> Result<Foo, FooError> { + /// # Ok(Foo) + /// } + /// } + /// ``` + /// + /// ```rust + /// # struct Foo; + /// struct Bar(Foo); + /// impl Foo { + /// // Bad. The type name must contain `Self`. + /// fn new() -> Bar { + /// # Bar(Foo) + /// } + /// } + /// ``` pub NEW_RET_NO_SELF, style, - "not returning `Self` in a `new` method" + "not returning type containing `Self` in a `new` method" } declare_clippy_lint! { @@ -1137,8 +1186,8 @@ declare_clippy_lint! { /// ```rust /// # let y: u32 = 0; /// # let x: u32 = 100; - /// let add = x.checked_add(y).unwrap_or(u32::max_value()); - /// let sub = x.checked_sub(y).unwrap_or(u32::min_value()); + /// let add = x.checked_add(y).unwrap_or(u32::MAX); + /// let sub = x.checked_sub(y).unwrap_or(u32::MIN); /// ``` /// /// can be written using dedicated methods for saturating addition/subtraction as: @@ -1248,6 +1297,7 @@ declare_lint_pass!(Methods => [ OPTION_MAP_UNWRAP_OR, OPTION_MAP_UNWRAP_OR_ELSE, RESULT_MAP_UNWRAP_OR_ELSE, + RESULT_MAP_OR_INTO_OPTION, OPTION_MAP_OR_NONE, OPTION_AND_THEN_SOME, OR_FUN_CALL, @@ -1289,7 +1339,7 @@ declare_lint_pass!(Methods => [ ]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { - #[allow(clippy::cognitive_complexity, clippy::too_many_lines)] + #[allow(clippy::too_many_lines)] fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { if in_macro(expr.span) { return; @@ -1407,7 +1457,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id); let item = cx.tcx.hir().expect_item(parent); let def_id = cx.tcx.hir().local_def_id(item.hir_id); - let ty = cx.tcx.type_of(def_id); + let self_ty = cx.tcx.type_of(def_id); if_chain! { if let hir::ImplItemKind::Fn(ref sig, id) = impl_item.kind; if let Some(first_arg) = iter_input_pats(&sig.decl, cx.tcx.hir().body(id)).next(); @@ -1425,11 +1475,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { then { if cx.access_levels.is_exported(impl_item.hir_id) { // check missing trait implementations - for &(method_name, n_args, self_kind, out_type, trait_name) in &TRAIT_METHODS { + for &(method_name, n_args, fn_header, self_kind, out_type, trait_name) in &TRAIT_METHODS { if name == method_name && - sig.decl.inputs.len() == n_args && - out_type.matches(cx, &sig.decl.output) && - self_kind.matches(cx, ty, first_arg_ty) { + sig.decl.inputs.len() == n_args && + out_type.matches(cx, &sig.decl.output) && + self_kind.matches(cx, self_ty, first_arg_ty) && + fn_header_equals(*fn_header, sig.header) { span_lint(cx, SHOULD_IMPLEMENT_TRAIT, impl_item.span, &format!( "defining a method called `{}` on this type; consider implementing \ the `{}` trait or choosing a less ambiguous name", name, trait_name)); @@ -1441,7 +1492,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { .iter() .find(|(ref conv, _)| conv.check(&name)) { - if !self_kinds.iter().any(|k| k.matches(cx, ty, first_arg_ty)) { + if !self_kinds.iter().any(|k| k.matches(cx, self_ty, first_arg_ty)) { let lint = if item.vis.node.is_pub() { WRONG_PUB_SELF_CONVENTION } else { @@ -1471,8 +1522,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { if let hir::ImplItemKind::Fn(_, _) = impl_item.kind { let ret_ty = return_ty(cx, impl_item.hir_id); + let contains_self_ty = |ty: Ty<'tcx>| { + ty.walk().any(|inner| match inner.unpack() { + GenericArgKind::Type(inner_ty) => same_tys(cx, self_ty, inner_ty), + + GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false, + }) + }; + // walk the return type and check for Self (this does not check associated types) - if ret_ty.walk().any(|inner_type| same_tys(cx, ty, inner_type)) { + if contains_self_ty(ret_ty) { return; } @@ -1486,10 +1545,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { let associated_type = binder.skip_binder(); // walk the associated type and check for Self - for inner_type in associated_type.walk() { - if same_tys(cx, ty, inner_type) { - return; - } + if contains_self_ty(associated_type) { + return; } }, (_, _) => {}, @@ -1497,7 +1554,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { } } - if name == "new" && !same_tys(cx, ret_ty, ty) { + if name == "new" && !same_tys(cx, ret_ty, self_ty) { span_lint( cx, NEW_RET_NO_SELF, @@ -1801,9 +1858,9 @@ fn lint_expect_fun_call( } let receiver_type = cx.tables.expr_ty_adjusted(&args[0]); - let closure_args = if match_type(cx, receiver_type, &paths::OPTION) { + let closure_args = if is_type_diagnostic_item(cx, receiver_type, sym!(option_type)) { "||" - } else if match_type(cx, receiver_type, &paths::RESULT) { + } else if is_type_diagnostic_item(cx, receiver_type, sym!(result_type)) { "|_|" } else { return; @@ -1912,9 +1969,10 @@ fn lint_clone_on_copy(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &hir: match &cx.tcx.hir().get(parent) { hir::Node::Expr(parent) => match parent.kind { // &*x is a nop, &x.clone() is not - hir::ExprKind::AddrOf(..) | + hir::ExprKind::AddrOf(..) => return, // (*x).func() is useless, x.clone().func() can work in case func borrows mutably - hir::ExprKind::MethodCall(..) => return, + hir::ExprKind::MethodCall(_, _, parent_args) if expr.hir_id == parent_args[0].hir_id => return, + _ => {}, }, hir::Node::Stmt(stmt) => { @@ -1962,9 +2020,9 @@ fn lint_clone_on_ref_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, arg: &h let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(arg)); if let ty::Adt(_, subst) = obj_ty.kind { - let caller_type = if match_type(cx, obj_ty, &paths::RC) { + let caller_type = if is_type_diagnostic_item(cx, obj_ty, sym::Rc) { "Rc" - } else if match_type(cx, obj_ty, &paths::ARC) { + } else if is_type_diagnostic_item(cx, obj_ty, sym::Arc) { "Arc" } else if match_type(cx, obj_ty, &paths::WEAK_RC) || match_type(cx, obj_ty, &paths::WEAK_ARC) { "Weak" @@ -2031,7 +2089,7 @@ fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, source: & if_chain! { let source_type = cx.tables.expr_ty(source); if let ty::Adt(def, substs) = source_type.kind; - if match_def_path(cx, def.did, &paths::RESULT); + if cx.tcx.is_diagnostic_item(sym!(result_type), def.did); if match_type(cx, substs.type_at(0), &paths::CSTRING); then { span_lint_and_then( @@ -2053,7 +2111,7 @@ fn lint_iter_cloned_collect<'a, 'tcx>( iter_args: &'tcx [hir::Expr<'_>], ) { if_chain! { - if is_type_diagnostic_item(cx, cx.tables.expr_ty(expr), Symbol::intern("vec_type")); + if is_type_diagnostic_item(cx, cx.tables.expr_ty(expr), sym!(vec_type)); if let Some(slice) = derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])); if let Some(to_replace) = expr.span.trim_start(slice.span.source_callsite()); @@ -2182,7 +2240,7 @@ fn lint_iter_nth<'a, 'tcx>( let mut_str = if is_mut { "_mut" } else { "" }; let caller_type = if derefs_to_slice(cx, &iter_args[0], cx.tables.expr_ty(&iter_args[0])).is_some() { "slice" - } else if is_type_diagnostic_item(cx, cx.tables.expr_ty(&iter_args[0]), Symbol::intern("vec_type")) { + } else if is_type_diagnostic_item(cx, cx.tables.expr_ty(&iter_args[0]), sym!(vec_type)) { "Vec" } else if match_type(cx, cx.tables.expr_ty(&iter_args[0]), &paths::VEC_DEQUE) { "VecDeque" @@ -2239,7 +2297,7 @@ fn lint_get_unwrap<'a, 'tcx>( let caller_type = if derefs_to_slice(cx, &get_args[0], expr_ty).is_some() { needs_ref = get_args_str.parse::<usize>().is_ok(); "slice" - } else if is_type_diagnostic_item(cx, expr_ty, Symbol::intern("vec_type")) { + } else if is_type_diagnostic_item(cx, expr_ty, sym!(vec_type)) { needs_ref = get_args_str.parse::<usize>().is_ok(); "Vec" } else if match_type(cx, expr_ty, &paths::VEC_DEQUE) { @@ -2320,7 +2378,7 @@ fn derefs_to_slice<'a, 'tcx>( match ty.kind { ty::Slice(_) => true, ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), - ty::Adt(..) => is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")), + ty::Adt(..) => is_type_diagnostic_item(cx, ty, sym!(vec_type)), ty::Array(_, size) => { if let Some(size) = size.try_eval_usize(cx.tcx, cx.param_env) { size < 32 @@ -2359,9 +2417,9 @@ fn derefs_to_slice<'a, 'tcx>( fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hir::Expr<'_>]) { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&unwrap_args[0])); - let mess = if match_type(cx, obj_ty, &paths::OPTION) { + let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) { Some((OPTION_UNWRAP_USED, "an Option", "None")) - } else if match_type(cx, obj_ty, &paths::RESULT) { + } else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) { Some((RESULT_UNWRAP_USED, "a Result", "Err")) } else { None @@ -2386,9 +2444,9 @@ fn lint_unwrap(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, unwrap_args: &[hi fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hir::Expr<'_>]) { let obj_ty = walk_ptrs_ty(cx.tables.expr_ty(&expect_args[0])); - let mess = if match_type(cx, obj_ty, &paths::OPTION) { + let mess = if is_type_diagnostic_item(cx, obj_ty, sym!(option_type)) { Some((OPTION_EXPECT_USED, "an Option", "None")) - } else if match_type(cx, obj_ty, &paths::RESULT) { + } else if is_type_diagnostic_item(cx, obj_ty, sym!(result_type)) { Some((RESULT_EXPECT_USED, "a Result", "Err")) } else { None @@ -2409,7 +2467,7 @@ fn lint_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, expect_args: &[hi fn lint_ok_expect(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, ok_args: &[hir::Expr<'_>]) { if_chain! { // lint if the caller of `ok()` is a `Result` - if match_type(cx, cx.tables.expr_ty(&ok_args[0]), &paths::RESULT); + if is_type_diagnostic_item(cx, cx.tables.expr_ty(&ok_args[0]), sym!(result_type)); let result_type = cx.tables.expr_ty(&ok_args[0]); if let Some(error_type) = get_error_type(cx, result_type); if has_debug_impl(error_type, cx); @@ -2455,8 +2513,8 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( unwrap_args: &'tcx [hir::Expr<'_>], ) { // lint if the caller of `map()` is an `Option` - let is_option = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION); - let is_result = match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::RESULT); + let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(option_type)); + let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(result_type)); if is_option || is_result { // Don't make a suggestion that may fail to compile due to mutably borrowing @@ -2517,38 +2575,78 @@ fn lint_map_unwrap_or_else<'a, 'tcx>( } } -/// lint use of `_.map_or(None, _)` for `Option`s +/// lint use of `_.map_or(None, _)` for `Option`s and `Result`s fn lint_map_or_none<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>, map_or_args: &'tcx [hir::Expr<'_>], ) { - if match_type(cx, cx.tables.expr_ty(&map_or_args[0]), &paths::OPTION) { - // check if the first non-self argument to map_or() is None - let map_or_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].kind { + let is_option = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_or_args[0]), sym!(option_type)); + let is_result = is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_or_args[0]), sym!(result_type)); + + // There are two variants of this `map_or` lint: + // (1) using `map_or` as an adapter from `Result<T,E>` to `Option<T>` + // (2) using `map_or` as a combinator instead of `and_then` + // + // (For this lint) we don't care if any other type calls `map_or` + if !is_option && !is_result { + return; + } + + let (lint_name, msg, instead, hint) = { + let default_arg_is_none = if let hir::ExprKind::Path(ref qpath) = map_or_args[1].kind { match_qpath(qpath, &paths::OPTION_NONE) } else { + return; + }; + + if !default_arg_is_none { + // nothing to lint! + return; + } + + let f_arg_is_some = if let hir::ExprKind::Path(ref qpath) = map_or_args[2].kind { + match_qpath(qpath, &paths::OPTION_SOME) + } else { false }; - if map_or_arg_is_none { - // lint message + if is_option { + let self_snippet = snippet(cx, map_or_args[0].span, ".."); + let func_snippet = snippet(cx, map_or_args[2].span, ".."); let msg = "called `map_or(None, f)` on an `Option` value. This can be done more directly by calling \ `and_then(f)` instead"; - let map_or_self_snippet = snippet(cx, map_or_args[0].span, ".."); - let map_or_func_snippet = snippet(cx, map_or_args[2].span, ".."); - let hint = format!("{0}.and_then({1})", map_or_self_snippet, map_or_func_snippet); - span_lint_and_sugg( - cx, + ( OPTION_MAP_OR_NONE, - expr.span, msg, "try using `and_then` instead", - hint, - Applicability::MachineApplicable, - ); + format!("{0}.and_then({1})", self_snippet, func_snippet), + ) + } else if f_arg_is_some { + let msg = "called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling \ + `ok()` instead"; + let self_snippet = snippet(cx, map_or_args[0].span, ".."); + ( + RESULT_MAP_OR_INTO_OPTION, + msg, + "try using `ok` instead", + format!("{0}.ok()", self_snippet), + ) + } else { + // nothing to lint! + return; } - } + }; + + span_lint_and_sugg( + cx, + lint_name, + expr.span, + msg, + instead, + hint, + Applicability::MachineApplicable, + ); } /// Lint use of `_.and_then(|x| Some(y))` for `Option`s @@ -3133,10 +3231,7 @@ fn is_maybe_uninit_ty_valid(cx: &LateContext<'_, '_>, ty: Ty<'_>) -> bool { match ty.kind { ty::Array(ref component, _) => is_maybe_uninit_ty_valid(cx, component), ty::Tuple(ref types) => types.types().all(|ty| is_maybe_uninit_ty_valid(cx, ty)), - ty::Adt(ref adt, _) => { - // needs to be a MaybeUninit - match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT) - }, + ty::Adt(ref adt, _) => match_def_path(cx, adt.did, &paths::MEM_MAYBEUNINIT), _ => false, } } @@ -3159,6 +3254,8 @@ fn lint_option_as_ref_deref<'a, 'tcx>( map_args: &[hir::Expr<'_>], is_mut: bool, ) { + let same_mutability = |m| (is_mut && m == &hir::Mutability::Mut) || (!is_mut && m == &hir::Mutability::Not); + let option_ty = cx.tables.expr_ty(&as_ref_args[0]); if !match_type(cx, option_ty, &paths::OPTION) { return; @@ -3181,39 +3278,56 @@ fn lint_option_as_ref_deref<'a, 'tcx>( hir::ExprKind::Closure(_, _, body_id, _, _) => { let closure_body = cx.tcx.hir().body(body_id); let closure_expr = remove_blocks(&closure_body.value); - if_chain! { - if let hir::ExprKind::MethodCall(_, _, args) = &closure_expr.kind; - if args.len() == 1; - if let hir::ExprKind::Path(qpath) = &args[0].kind; - if let hir::def::Res::Local(local_id) = cx.tables.qpath_res(qpath, args[0].hir_id); - if closure_body.params[0].pat.hir_id == local_id; - let adj = cx.tables.expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>(); - if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj; - then { - let method_did = cx.tables.type_dependent_def_id(closure_expr.hir_id).unwrap(); - deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) - } else { - false - } + + match &closure_expr.kind { + hir::ExprKind::MethodCall(_, _, args) => { + if_chain! { + if args.len() == 1; + if let hir::ExprKind::Path(qpath) = &args[0].kind; + if let hir::def::Res::Local(local_id) = cx.tables.qpath_res(qpath, args[0].hir_id); + if closure_body.params[0].pat.hir_id == local_id; + let adj = cx.tables.expr_adjustments(&args[0]).iter().map(|x| &x.kind).collect::<Box<[_]>>(); + if let [ty::adjustment::Adjust::Deref(None), ty::adjustment::Adjust::Borrow(_)] = *adj; + then { + let method_did = cx.tables.type_dependent_def_id(closure_expr.hir_id).unwrap(); + deref_aliases.iter().any(|path| match_def_path(cx, method_did, path)) + } else { + false + } + } + }, + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, m, ref inner) if same_mutability(m) => { + if_chain! { + if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner1) = inner.kind; + if let hir::ExprKind::Unary(hir::UnOp::UnDeref, ref inner2) = inner1.kind; + if let hir::ExprKind::Path(ref qpath) = inner2.kind; + if let hir::def::Res::Local(local_id) = cx.tables.qpath_res(qpath, inner2.hir_id); + then { + closure_body.params[0].pat.hir_id == local_id + } else { + false + } + } + }, + _ => false, } }, - _ => false, }; if is_deref { let current_method = if is_mut { - ".as_mut().map(DerefMut::deref_mut)" + format!(".as_mut().map({})", snippet(cx, map_args[1].span, "..")) } else { - ".as_ref().map(Deref::deref)" + format!(".as_ref().map({})", snippet(cx, map_args[1].span, "..")) }; let method_hint = if is_mut { "as_deref_mut" } else { "as_deref" }; let hint = format!("{}.{}()", snippet(cx, as_ref_args[0].span, ".."), method_hint); let suggestion = format!("try using {} instead", method_hint); let msg = format!( - "called `{0}` (or with one of deref aliases) on an Option value. \ - This can be done more directly by calling `{1}` instead", + "called `{0}` on an Option value. This can be done more directly \ + by calling `{1}` instead", current_method, hint ); span_lint_and_sugg( @@ -3231,7 +3345,7 @@ fn lint_option_as_ref_deref<'a, 'tcx>( /// Given a `Result<T, E>` type, return its error type (`E`). fn get_error_type<'a>(cx: &LateContext<'_, '_>, ty: Ty<'a>) -> Option<Ty<'a>> { match ty.kind { - ty::Adt(_, substs) if match_type(cx, ty, &paths::RESULT) => substs.types().nth(1), + ty::Adt(_, substs) if is_type_diagnostic_item(cx, ty, sym!(result_type)) => substs.types().nth(1), _ => None, } } @@ -3259,38 +3373,45 @@ const CONVENTIONS: [(Convention, &[SelfKind]); 7] = [ (Convention::StartsWith("to_"), &[SelfKind::Ref]), ]; +const FN_HEADER: hir::FnHeader = hir::FnHeader { + unsafety: hir::Unsafety::Normal, + constness: hir::Constness::NotConst, + asyncness: hir::IsAsync::NotAsync, + abi: rustc_target::spec::abi::Abi::Rust, +}; + #[rustfmt::skip] -const TRAIT_METHODS: [(&str, usize, SelfKind, OutType, &str); 30] = [ - ("add", 2, SelfKind::Value, OutType::Any, "std::ops::Add"), - ("as_mut", 1, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), - ("as_ref", 1, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), - ("bitand", 2, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), - ("bitor", 2, SelfKind::Value, OutType::Any, "std::ops::BitOr"), - ("bitxor", 2, SelfKind::Value, OutType::Any, "std::ops::BitXor"), - ("borrow", 1, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), - ("borrow_mut", 1, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), - ("clone", 1, SelfKind::Ref, OutType::Any, "std::clone::Clone"), - ("cmp", 2, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), - ("default", 0, SelfKind::No, OutType::Any, "std::default::Default"), - ("deref", 1, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), - ("deref_mut", 1, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), - ("div", 2, SelfKind::Value, OutType::Any, "std::ops::Div"), - ("drop", 1, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), - ("eq", 2, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), - ("from_iter", 1, SelfKind::No, OutType::Any, "std::iter::FromIterator"), - ("from_str", 1, SelfKind::No, OutType::Any, "std::str::FromStr"), - ("hash", 2, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), - ("index", 2, SelfKind::Ref, OutType::Ref, "std::ops::Index"), - ("index_mut", 2, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), - ("into_iter", 1, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), - ("mul", 2, SelfKind::Value, OutType::Any, "std::ops::Mul"), - ("neg", 1, SelfKind::Value, OutType::Any, "std::ops::Neg"), - ("next", 1, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), - ("not", 1, SelfKind::Value, OutType::Any, "std::ops::Not"), - ("rem", 2, SelfKind::Value, OutType::Any, "std::ops::Rem"), - ("shl", 2, SelfKind::Value, OutType::Any, "std::ops::Shl"), - ("shr", 2, SelfKind::Value, OutType::Any, "std::ops::Shr"), - ("sub", 2, SelfKind::Value, OutType::Any, "std::ops::Sub"), +const TRAIT_METHODS: [(&str, usize, &hir::FnHeader, SelfKind, OutType, &str); 30] = [ + ("add", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Add"), + ("as_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::convert::AsMut"), + ("as_ref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::convert::AsRef"), + ("bitand", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitAnd"), + ("bitor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitOr"), + ("bitxor", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::BitXor"), + ("borrow", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::borrow::Borrow"), + ("borrow_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::borrow::BorrowMut"), + ("clone", 1, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::clone::Clone"), + ("cmp", 2, &FN_HEADER, SelfKind::Ref, OutType::Any, "std::cmp::Ord"), + ("default", 0, &FN_HEADER, SelfKind::No, OutType::Any, "std::default::Default"), + ("deref", 1, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Deref"), + ("deref_mut", 1, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::DerefMut"), + ("div", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Div"), + ("drop", 1, &FN_HEADER, SelfKind::RefMut, OutType::Unit, "std::ops::Drop"), + ("eq", 2, &FN_HEADER, SelfKind::Ref, OutType::Bool, "std::cmp::PartialEq"), + ("from_iter", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::iter::FromIterator"), + ("from_str", 1, &FN_HEADER, SelfKind::No, OutType::Any, "std::str::FromStr"), + ("hash", 2, &FN_HEADER, SelfKind::Ref, OutType::Unit, "std::hash::Hash"), + ("index", 2, &FN_HEADER, SelfKind::Ref, OutType::Ref, "std::ops::Index"), + ("index_mut", 2, &FN_HEADER, SelfKind::RefMut, OutType::Ref, "std::ops::IndexMut"), + ("into_iter", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::iter::IntoIterator"), + ("mul", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Mul"), + ("neg", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Neg"), + ("next", 1, &FN_HEADER, SelfKind::RefMut, OutType::Any, "std::iter::Iterator"), + ("not", 1, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Not"), + ("rem", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Rem"), + ("shl", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shl"), + ("shr", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Shr"), + ("sub", 2, &FN_HEADER, SelfKind::Value, OutType::Any, "std::ops::Sub"), ]; #[rustfmt::skip] @@ -3324,12 +3445,12 @@ enum SelfKind { impl SelfKind { fn matches<'a>(self, cx: &LateContext<'_, 'a>, parent_ty: Ty<'a>, ty: Ty<'a>) -> bool { - fn matches_value(parent_ty: Ty<'_>, ty: Ty<'_>) -> bool { + fn matches_value<'a>(cx: &LateContext<'_, 'a>, parent_ty: Ty<'_>, ty: Ty<'_>) -> bool { if ty == parent_ty { true } else if ty.is_box() { ty.boxed_ty() == parent_ty - } else if ty.is_rc() || ty.is_arc() { + } else if is_type_diagnostic_item(cx, ty, sym::Rc) || is_type_diagnostic_item(cx, ty, sym::Arc) { if let ty::Adt(_, substs) = ty.kind { substs.types().next().map_or(false, |t| t == parent_ty) } else { @@ -3363,7 +3484,7 @@ impl SelfKind { } match self { - Self::Value => matches_value(parent_ty, ty), + Self::Value => matches_value(cx, parent_ty, ty), Self::Ref => matches_ref(cx, hir::Mutability::Not, parent_ty, ty) || ty == parent_ty && is_copy(cx, ty), Self::RefMut => matches_ref(cx, hir::Mutability::Mut, parent_ty, ty), Self::No => ty != parent_ty, @@ -3503,3 +3624,9 @@ fn lint_filetype_is_file(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, args: & let help_msg = format!("use `{}FileType::is_dir()` instead", help_unary); span_lint_and_help(cx, FILETYPE_IS_FILE, span, &lint_msg, &help_msg); } + +fn fn_header_equals(expected: hir::FnHeader, actual: hir::FnHeader) -> bool { + expected.constness == actual.constness + && expected.unsafety == actual.unsafety + && expected.asyncness == actual.asyncness +} diff --git a/clippy_lints/src/methods/option_map_unwrap_or.rs b/clippy_lints/src/methods/option_map_unwrap_or.rs index c40ab7beba4..35d481cf666 100644 --- a/clippy_lints/src/methods/option_map_unwrap_or.rs +++ b/clippy_lints/src/methods/option_map_unwrap_or.rs @@ -1,11 +1,11 @@ -use crate::utils::{differing_macro_contexts, paths, snippet_with_applicability, span_lint_and_then}; -use crate::utils::{is_copy, match_type}; -use rustc::hir::map::Map; +use crate::utils::{differing_macro_contexts, snippet_with_applicability, span_lint_and_then}; +use crate::utils::{is_copy, is_type_diagnostic_item}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; use rustc_hir::{self, HirId, Path}; use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; use rustc_span::source_map::Span; use rustc_span::symbol::Symbol; @@ -20,7 +20,7 @@ pub(super) fn lint<'a, 'tcx>( map_span: Span, ) { // lint if the caller of `map()` is an `Option` - if match_type(cx, cx.tables.expr_ty(&map_args[0]), &paths::OPTION) { + if is_type_diagnostic_item(cx, cx.tables.expr_ty(&map_args[0]), sym!(option_type)) { if !is_copy(cx, cx.tables.expr_ty(&unwrap_args[1])) { // Do not lint if the `map` argument uses identifiers in the `map` // argument that are also used in the `unwrap_or` argument diff --git a/clippy_lints/src/methods/unnecessary_filter_map.rs b/clippy_lints/src/methods/unnecessary_filter_map.rs index ee6c6ef12e5..41c9ce7cda3 100644 --- a/clippy_lints/src/methods/unnecessary_filter_map.rs +++ b/clippy_lints/src/methods/unnecessary_filter_map.rs @@ -1,11 +1,11 @@ use crate::utils::paths; use crate::utils::usage::mutated_variables; use crate::utils::{match_qpath, match_trait_method, span_lint}; -use rustc::hir::map::Map; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; use if_chain::if_chain; diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 6dbc33d8729..58a5a29eb16 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -1,5 +1,4 @@ use if_chain::if_chain; -use rustc::ty; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; @@ -8,6 +7,7 @@ use rustc_hir::{ TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{ExpnKind, Span}; @@ -57,10 +57,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// # use core::f32::NAN; /// # let x = 1.0; /// - /// if x == NAN { } + /// if x == f32::NAN { } /// ``` pub CMP_NAN, correctness, @@ -370,26 +369,28 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { return; } } - let (lint, msg) = if is_named_constant(cx, left) || is_named_constant(cx, right) { - (FLOAT_CMP_CONST, "strict comparison of `f32` or `f64` constant") - } else { - (FLOAT_CMP, "strict comparison of `f32` or `f64`") - }; + let is_comparing_arrays = is_array(cx, left) || is_array(cx, right); + let (lint, msg) = get_lint_and_message( + is_named_constant(cx, left) || is_named_constant(cx, right), + is_comparing_arrays, + ); span_lint_and_then(cx, lint, expr.span, msg, |db| { let lhs = Sugg::hir(cx, left, ".."); let rhs = Sugg::hir(cx, right, ".."); - db.span_suggestion( - expr.span, - "consider comparing them within some error", - format!( - "({}).abs() {} error", - lhs - rhs, - if op == BinOpKind::Eq { '<' } else { '>' } - ), - Applicability::HasPlaceholders, // snippet - ); - db.span_note(expr.span, "`std::f32::EPSILON` and `std::f64::EPSILON` are available."); + if !is_comparing_arrays { + db.span_suggestion( + expr.span, + "consider comparing them within some error", + format!( + "({}).abs() {} error", + lhs - rhs, + if op == BinOpKind::Eq { '<' } else { '>' } + ), + Applicability::HasPlaceholders, // snippet + ); + } + db.note("`f32::EPSILON` and `f64::EPSILON` are available for the `error`"); }); } else if op == BinOpKind::Rem && is_integer_const(cx, right, 1) { span_lint(cx, MODULO_ONE, expr.span, "any number modulo 1 will be 0"); @@ -441,6 +442,31 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { } } +fn get_lint_and_message( + is_comparing_constants: bool, + is_comparing_arrays: bool, +) -> (&'static rustc_lint::Lint, &'static str) { + if is_comparing_constants { + ( + FLOAT_CMP_CONST, + if is_comparing_arrays { + "strict comparison of `f32` or `f64` constant arrays" + } else { + "strict comparison of `f32` or `f64` constant" + }, + ) + } else { + ( + FLOAT_CMP, + if is_comparing_arrays { + "strict comparison of `f32` or `f64` arrays" + } else { + "strict comparison of `f32` or `f64`" + }, + ) + } +} + fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { if_chain! { if !in_constant(cx, cmp_expr.hir_id); @@ -457,7 +483,7 @@ fn check_nan(cx: &LateContext<'_, '_>, expr: &Expr<'_>, cmp_expr: &Expr<'_>) { cx, CMP_NAN, cmp_expr.span, - "doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead", + "doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead", ); } } @@ -476,6 +502,11 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) -> boo match constant(cx, cx.tables, expr) { Some((Constant::F32(f), _)) => f == 0.0 || f.is_infinite(), Some((Constant::F64(f), _)) => f == 0.0 || f.is_infinite(), + Some((Constant::Vec(vec), _)) => vec.iter().all(|f| match f { + Constant::F32(f) => *f == 0.0 || (*f).is_infinite(), + Constant::F64(f) => *f == 0.0 || (*f).is_infinite(), + _ => false, + }), _ => false, } } @@ -500,7 +531,17 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { } fn is_float(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { - matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).kind, ty::Float(_)) + let value = &walk_ptrs_ty(cx.tables.expr_ty(expr)).kind; + + if let ty::Array(arr_ty, _) = value { + return matches!(arr_ty.kind, ty::Float(_)); + }; + + matches!(value, ty::Float(_)) +} + +fn is_array(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + matches!(&walk_ptrs_ty(cx.tables.expr_ty(expr)).kind, ty::Array(_, _)) } fn check_to_owned(cx: &LateContext<'_, '_>, expr: &Expr<'_>, other: &Expr<'_>) { diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index 718ec1c00bb..b3244453d6b 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -3,7 +3,6 @@ use crate::utils::{ span_lint_and_then, }; use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_ast::ast::{ BindingMode, Block, Expr, ExprKind, GenericParamKind, Generics, Lit, LitFloatType, LitIntType, LitKind, Mutability, NodeId, Pat, PatKind, StmtKind, UnOp, @@ -12,6 +11,7 @@ use rustc_ast::visit::{walk_expr, FnKind, Visitor}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index bd67302cbf4..0b235bdfe3c 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -1,9 +1,9 @@ use crate::utils::{fn_has_unsatisfiable_preds, has_drop, is_entrypoint_fn, span_lint, trait_ref_of_method}; -use rustc::lint::in_external_macro; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Constness, FnDecl, GenericParamKind, HirId}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; use rustc_mir::transform::qualify_min_const_fn::is_min_const_fn; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index e03f9e36095..2eefb6bbaf4 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -7,11 +7,11 @@ use crate::utils::span_lint; use if_chain::if_chain; -use rustc::ty; use rustc_ast::ast::{self, MetaItem, MetaItemKind}; use rustc_ast::attr; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::ty; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 22b56c28b6b..9fc26047d88 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -81,7 +81,7 @@ declare_lint_pass!(MissingInline => [MISSING_INLINE_IN_PUBLIC_ITEMS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, it: &'tcx hir::Item<'_>) { - if rustc::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) { + if rustc_middle::lint::in_external_macro(cx.sess(), it.span) || is_executable(cx) { return; } @@ -130,8 +130,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { } fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx hir::ImplItem<'_>) { - use rustc::ty::{ImplContainer, TraitContainer}; - if rustc::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) { + use rustc_middle::ty::{ImplContainer, TraitContainer}; + if rustc_middle::lint::in_external_macro(cx.sess(), impl_item.span) || is_executable(cx) { return; } diff --git a/clippy_lints/src/modulo_arithmetic.rs b/clippy_lints/src/modulo_arithmetic.rs index 7446b732c4b..b24d5c1fc8e 100644 --- a/clippy_lints/src/modulo_arithmetic.rs +++ b/clippy_lints/src/modulo_arithmetic.rs @@ -1,9 +1,9 @@ use crate::consts::{constant, Constant}; use crate::utils::{sext, span_lint_and_then}; use if_chain::if_chain; -use rustc::ty::{self}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::fmt::Display; diff --git a/clippy_lints/src/mut_key.rs b/clippy_lints/src/mut_key.rs index adaf82c7074..0b9b7e1b8cc 100644 --- a/clippy_lints/src/mut_key.rs +++ b/clippy_lints/src/mut_key.rs @@ -1,7 +1,7 @@ use crate::utils::{match_def_path, paths, span_lint, trait_ref_of_method, walk_ptrs_ty}; -use rustc::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut}; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{Adt, Array, RawPtr, Ref, Slice, Tuple, Ty, TypeAndMut}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 70061f2aa83..f7a20a74b85 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -1,10 +1,10 @@ use crate::utils::{higher, span_lint}; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; -use rustc::ty; use rustc_hir as hir; use rustc_hir::intravisit; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/mut_reference.rs b/clippy_lints/src/mut_reference.rs index aeffcd34110..e5680482e5b 100644 --- a/clippy_lints/src/mut_reference.rs +++ b/clippy_lints/src/mut_reference.rs @@ -1,8 +1,8 @@ use crate::utils::span_lint; -use rustc::ty::subst::Subst; -use rustc::ty::{self, Ty}; -use rustc_hir::{print, BorrowKind, Expr, ExprKind, Mutability}; +use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::subst::Subst; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -34,7 +34,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnecessaryMutPassed { cx, arguments, cx.tables.expr_ty(fn_expr), - &print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)), + &rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)), ); } }, diff --git a/clippy_lints/src/mutable_debug_assertion.rs b/clippy_lints/src/mutable_debug_assertion.rs index c576fc2c197..119e0905ff4 100644 --- a/clippy_lints/src/mutable_debug_assertion.rs +++ b/clippy_lints/src/mutable_debug_assertion.rs @@ -1,10 +1,10 @@ use crate::utils::{is_direct_expn_of, span_lint}; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::ty; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{BorrowKind, Expr, ExprKind, MatchSource, Mutability, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::Span; @@ -53,7 +53,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DebugAssertWithMutCall { } //HACK(hellow554): remove this when #4694 is implemented -#[allow(clippy::cognitive_complexity)] fn extract_call<'a, 'tcx>(cx: &'a LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) -> Option<Span> { if_chain! { if let ExprKind::Block(ref block, _) = e.kind; diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index bbd2e4d83fa..de8feee76ba 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -3,10 +3,10 @@ //! This lint is **warn** by default use crate::utils::{match_type, paths, span_lint}; -use rustc::ty::{self, Ty}; use rustc_ast::ast; use rustc_hir::Expr; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 19c22d2b791..efa77db822d 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -3,13 +3,15 @@ //! This lint is **warn** by default use crate::utils::sugg::Sugg; -use crate::utils::{higher, parent_node_is_if_expr, span_lint, span_lint_and_sugg}; +use crate::utils::{higher, parent_node_is_if_expr, snippet_with_applicability, span_lint, span_lint_and_sugg}; +use if_chain::if_chain; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind}; +use rustc_hir::{BinOpKind, Block, Expr, ExprKind, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; +use rustc_span::Span; declare_clippy_lint! { /// **What it does:** Checks for expressions of the form `if c { true } else { @@ -188,6 +190,34 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoolComparison { } } +struct ExpressionInfoWithSpan { + one_side_is_unary_not: bool, + left_span: Span, + right_span: Span, +} + +fn is_unary_not(e: &Expr<'_>) -> (bool, Span) { + if_chain! { + if let ExprKind::Unary(unop, operand) = e.kind; + if let UnOp::UnNot = unop; + then { + return (true, operand.span); + } + }; + (false, e.span) +} + +fn one_side_is_unary_not<'tcx>(left_side: &'tcx Expr<'_>, right_side: &'tcx Expr<'_>) -> ExpressionInfoWithSpan { + let left = is_unary_not(left_side); + let right = is_unary_not(right_side); + + ExpressionInfoWithSpan { + one_side_is_unary_not: left.0 != right.0, + left_span: left.1, + right_span: right.1, + } +} + fn check_comparison<'a, 'tcx>( cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>, @@ -199,10 +229,30 @@ fn check_comparison<'a, 'tcx>( ) { use self::Expression::{Bool, Other}; - if let ExprKind::Binary(_, ref left_side, ref right_side) = e.kind { + if let ExprKind::Binary(op, ref left_side, ref right_side) = e.kind { let (l_ty, r_ty) = (cx.tables.expr_ty(left_side), cx.tables.expr_ty(right_side)); if l_ty.is_bool() && r_ty.is_bool() { let mut applicability = Applicability::MachineApplicable; + + if let BinOpKind::Eq = op.node { + let expression_info = one_side_is_unary_not(&left_side, &right_side); + if expression_info.one_side_is_unary_not { + span_lint_and_sugg( + cx, + BOOL_COMPARISON, + e.span, + "This comparison might be written more concisely", + "try simplifying it as shown", + format!( + "{} != {}", + snippet_with_applicability(cx, expression_info.left_span, "..", &mut applicability), + snippet_with_applicability(cx, expression_info.right_span, "..", &mut applicability) + ), + applicability, + ) + } + } + match (fetch_bool_expr(left_side), fetch_bool_expr(right_side)) { (Bool(true), Other) => left_true.map_or((), |(h, m)| { suggest_bool_comparison(cx, e, right_side, applicability, m, h) diff --git a/clippy_lints/src/needless_borrow.rs b/clippy_lints/src/needless_borrow.rs index dc37c7804fe..422254bb007 100644 --- a/clippy_lints/src/needless_borrow.rs +++ b/clippy_lints/src/needless_borrow.rs @@ -4,11 +4,11 @@ use crate::utils::{snippet_opt, span_lint_and_then}; use if_chain::if_chain; -use rustc::ty; -use rustc::ty::adjustment::{Adjust, Adjustment}; use rustc_errors::Applicability; use rustc_hir::{BindingAnnotation, BorrowKind, Expr, ExprKind, HirId, Item, Mutability, Pat, PatKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_middle::ty::adjustment::{Adjust, Adjustment}; use rustc_session::{declare_tool_lint, impl_lint_pass}; declare_clippy_lint! { diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index dc18a745c26..a76776e45a8 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -4,7 +4,6 @@ use crate::utils::{ snippet, snippet_opt, span_lint_and_then, }; use if_chain::if_chain; -use rustc::ty::{self, TypeFoldable}; use rustc_ast::ast::Attribute; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{Applicability, DiagnosticBuilder}; @@ -12,8 +11,9 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{BindingAnnotation, Body, FnDecl, GenericArg, HirId, ItemKind, Node, PatKind, QPath, TyKind}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, TypeFoldable}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::{Span, Symbol}; +use rustc_span::Span; use rustc_target::spec::abi::Abi; use rustc_trait_selection::traits; use rustc_trait_selection::traits::misc::can_type_implement_copy; @@ -113,8 +113,8 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.to_vec()) .filter(|p| !p.is_global()) - .filter_map(|pred| { - if let ty::Predicate::Trait(poly_trait_ref, _) = pred { + .filter_map(|obligation| { + if let ty::Predicate::Trait(poly_trait_ref, _) = obligation.predicate { if poly_trait_ref.def_id() == sized_trait || poly_trait_ref.skip_binder().has_escaping_bound_vars() { return None; @@ -214,7 +214,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let deref_span = spans_need_deref.get(&canonical_id); if_chain! { - if is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")); + if is_type_diagnostic_item(cx, ty, sym!(vec_type)); if let Some(clone_spans) = get_spans(cx, Some(body.id()), idx, &[("clone", ".to_owned()")]); if let TyKind::Path(QPath::Resolved(_, ref path)) = input.kind; diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index e52b1cbf453..4b2586877e5 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -1,7 +1,7 @@ use crate::utils::span_lint; -use rustc::ty; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs index 2c4c29913cf..54536ed57d3 100644 --- a/clippy_lints/src/neg_cmp_op_on_partial_ord.rs +++ b/clippy_lints/src/neg_cmp_op_on_partial_ord.rs @@ -1,7 +1,7 @@ use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::{self, paths, span_lint}; @@ -25,13 +25,13 @@ declare_clippy_lint! { /// /// // Bad /// let a = 1.0; - /// let b = std::f64::NAN; + /// let b = f64::NAN; /// /// let _not_less_or_equal = !(a <= b); /// /// // Good /// let a = 1.0; - /// let b = std::f64::NAN; + /// let b = f64::NAN; /// /// let _not_less_or_equal = match a.partial_cmp(&b) { /// None | Some(Ordering::Greater) => true, diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index f69b145fa39..9d065005c99 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -2,13 +2,13 @@ use crate::utils::paths; use crate::utils::sugg::DiagnosticBuilderExt; use crate::utils::{get_trait_def_id, implements_trait, return_ty, same_tys, span_lint_hir_and_then}; use if_chain::if_chain; -use rustc::lint::in_external_macro; -use rustc::ty::{self, Ty}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def_id::DefId; use rustc_hir::HirIdSet; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::Span; @@ -100,7 +100,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault { } = item.kind { for assoc_item in items { - if let hir::AssocItemKind::Method { has_self: false } = assoc_item.kind { + if let hir::AssocItemKind::Fn { has_self: false } = assoc_item.kind { let impl_item = cx.tcx.hir().impl_item(assoc_item.id); if in_external_macro(cx.sess(), impl_item.span) { return; diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 43d76d0cbbd..744cade461c 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -4,11 +4,11 @@ use std::ptr; -use rustc::ty::adjustment::Adjust; -use rustc::ty::{Ty, TypeFlags}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Node, TraitItem, TraitItemKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, Lint}; +use rustc_middle::ty::adjustment::Adjust; +use rustc_middle::ty::{Ty, TypeFlags}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::{InnerSpan, Span, DUMMY_SP}; use rustc_typeck::hir_ty_to_ty; diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 3d420cf8cec..949ad0510d3 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -6,16 +6,16 @@ use crate::utils::{ walk_ptrs_hir_ty, }; use if_chain::if_chain; -use rustc::ty; use rustc_errors::Applicability; use rustc_hir::{ BinOpKind, BodyId, Expr, ExprKind, FnDecl, FnRetTy, GenericArg, HirId, ImplItem, ImplItemKind, Item, ItemKind, Lifetime, MutTy, Mutability, Node, PathSegment, QPath, TraitFn, TraitItem, TraitItemKind, Ty, TyKind, }; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; -use rustc_span::{MultiSpan, Symbol}; +use rustc_span::MultiSpan; use std::borrow::Cow; declare_clippy_lint! { @@ -153,7 +153,7 @@ fn check_fn(cx: &LateContext<'_, '_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_ for (idx, (arg, ty)) in decl.inputs.iter().zip(fn_ty.inputs()).enumerate() { if let ty::Ref(_, ty, Mutability::Not) = ty.kind { - if is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) { + if is_type_diagnostic_item(cx, ty, sym!(vec_type)) { let mut ty_snippet = None; if_chain! { if let TyKind::Path(QPath::Resolved(_, ref path)) = walk_ptrs_hir_ty(arg).kind; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index f054c6ef67d..28c1d975309 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -5,10 +5,10 @@ use rustc_hir::{def, BindingAnnotation, Block, Expr, ExprKind, MatchSource, PatK use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use crate::utils::paths::{OPTION, OPTION_NONE}; use crate::utils::sugg::Sugg; use crate::utils::{ - higher, match_def_path, match_qpath, match_type, snippet_with_applicability, span_lint_and_sugg, SpanlessEq, + higher, is_type_diagnostic_item, match_def_path, match_qpath, paths, snippet_with_applicability, + span_lint_and_sugg, SpanlessEq, }; declare_clippy_lint! { @@ -141,7 +141,7 @@ impl QuestionMark { fn is_option(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { let expr_ty = cx.tables.expr_ty(expression); - match_type(cx, expr_ty, &OPTION) + is_type_diagnostic_item(cx, expr_ty, sym!(option_type)) } fn expression_returns_none(cx: &LateContext<'_, '_>, expression: &Expr<'_>) -> bool { @@ -158,7 +158,7 @@ impl QuestionMark { if let Res::Def(DefKind::Ctor(def::CtorOf::Variant, def::CtorKind::Const), def_id) = cx.tables.qpath_res(qp, expression.hir_id) { - return match_def_path(cx, def_id, &OPTION_NONE); + return match_def_path(cx, def_id, &paths::OPTION_NONE); } false diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index a2070e1c38a..aedbafd408b 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -3,19 +3,19 @@ use crate::utils::{ span_lint_hir_and_then, walk_ptrs_ty_depth, }; use if_chain::if_chain; -use rustc::mir::{ - self, traversal, - visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _}, -}; -use rustc::ty::{self, fold::TypeVisitor, Ty}; use rustc_data_structures::{fx::FxHashMap, transitive_relation::TransitiveRelation}; use rustc_errors::Applicability; use rustc_hir::intravisit::FnKind; use rustc_hir::{def_id, Body, FnDecl, HirId}; use rustc_index::bit_set::{BitSet, HybridBitSet}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_mir::dataflow::generic::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; +use rustc_middle::mir::{ + self, traversal, + visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _}, +}; +use rustc_middle::ty::{self, fold::TypeVisitor, Ty}; use rustc_mir::dataflow::BottomValue; +use rustc_mir::dataflow::{Analysis, AnalysisDomain, GenKill, GenKillAnalysis, ResultsCursor}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::{BytePos, Span}; use std::convert::TryFrom; @@ -80,20 +80,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); // Building MIR for `fn`s with unsatisfiable preds results in ICE. - if fn_has_unsatisfiable_preds(cx, def_id) { + if fn_has_unsatisfiable_preds(cx, def_id.to_def_id()) { return; } - let mir = cx.tcx.optimized_mir(def_id); + let mir = cx.tcx.optimized_mir(def_id.to_def_id()); let mir_read_only = mir.unwrap_read_only(); let maybe_storage_live_result = MaybeStorageLive - .into_engine(cx.tcx, mir, def_id) + .into_engine(cx.tcx, mir, def_id.to_def_id()) .iterate_to_fixpoint() .into_results_cursor(mir); let mut possible_borrower = { let mut vis = PossibleBorrowerVisitor::new(cx, mir); - vis.visit_body(mir_read_only); + vis.visit_body(&mir_read_only); vis.into_map(cx, maybe_storage_live_result) }; @@ -335,12 +335,15 @@ fn base_local_and_movability<'tcx>( mir: &mir::Body<'tcx>, place: mir::Place<'tcx>, ) -> Option<(mir::Local, CannotMoveOut)> { - use rustc::mir::PlaceRef; + use rustc_middle::mir::PlaceRef; // Dereference. You cannot move things out from a borrowed value. let mut deref = false; // Accessing a field of an ADT that has `Drop`. Moving the field out will cause E0509. let mut field = false; + // If projection is a slice index then clone can be removed only if the + // underlying type implements Copy + let mut slice = false; let PlaceRef { local, mut projection } = place.as_ref(); while let [base @ .., elem] = projection { @@ -348,9 +351,11 @@ fn base_local_and_movability<'tcx>( deref |= matches!(elem, mir::ProjectionElem::Deref); field |= matches!(elem, mir::ProjectionElem::Field(..)) && has_drop(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); + slice |= matches!(elem, mir::ProjectionElem::Index(..)) + && !is_copy(cx, mir::Place::ty_from(local, projection, &mir.local_decls, cx.tcx).ty); } - Some((local, deref || field)) + Some((local, deref || field || slice)) } struct LocalUseVisitor { @@ -437,7 +442,7 @@ impl<'tcx> GenKillAnalysis<'tcx> for MaybeStorageLive { _block: mir::BasicBlock, _func: &mir::Operand<'tcx>, _args: &[mir::Operand<'tcx>], - _return_place: &mir::Place<'tcx>, + _return_place: mir::Place<'tcx>, ) { // Nothing to do when a call returns successfully } @@ -556,7 +561,7 @@ impl TypeVisitor<'_> for ContainsRegion { } fn rvalue_locals(rvalue: &mir::Rvalue<'_>, mut visit: impl FnMut(mir::Local)) { - use rustc::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use}; + use rustc_middle::mir::Rvalue::{Aggregate, BinaryOp, Cast, CheckedBinaryOp, Repeat, UnaryOp, Use}; let mut visit_op = |op: &mir::Operand<'_>| match op { mir::Operand::Copy(p) | mir::Operand::Move(p) => visit(p.local), diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs deleted file mode 100644 index aca1ebbd508..00000000000 --- a/clippy_lints/src/replace_consts.rs +++ /dev/null @@ -1,103 +0,0 @@ -use crate::utils::{match_def_path, span_lint_and_sugg}; -use if_chain::if_chain; -use rustc_errors::Applicability; -use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Expr, ExprKind, Node}; -use rustc_lint::{LateContext, LateLintPass}; -use rustc_session::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// **What it does:** Checks for usage of standard library - /// `const`s that could be replaced by `const fn`s. - /// - /// **Why is this bad?** `const fn`s exist - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```rust - /// let x = std::u32::MIN; - /// let y = std::u32::MAX; - /// ``` - /// - /// Could be written: - /// - /// ```rust - /// let x = u32::min_value(); - /// let y = u32::max_value(); - /// ``` - pub REPLACE_CONSTS, - pedantic, - "Lint usages of standard library `const`s that could be replaced by `const fn`s" -} - -declare_lint_pass!(ReplaceConsts => [REPLACE_CONSTS]); - -fn in_pattern(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { - let map = &cx.tcx.hir(); - let parent_id = map.get_parent_node(expr.hir_id); - - if let Some(node) = map.find(parent_id) { - if let Node::Pat(_) = node { - return true; - } - } - - false -} - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ReplaceConsts { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) { - if_chain! { - if let ExprKind::Path(ref qp) = expr.kind; - if let Res::Def(DefKind::Const, def_id) = cx.tables.qpath_res(qp, expr.hir_id); - // Do not lint within patterns as function calls are disallowed in them - if !in_pattern(cx, expr); - then { - for &(ref const_path, repl_snip) in &REPLACEMENTS { - if match_def_path(cx, def_id, const_path) { - span_lint_and_sugg( - cx, - REPLACE_CONSTS, - expr.span, - &format!("using `{}`", const_path.last().expect("empty path")), - "try this", - repl_snip.to_string(), - Applicability::MachineApplicable, - ); - return; - } - } - } - } - } -} - -const REPLACEMENTS: [([&str; 3], &str); 24] = [ - // Min - (["core", "isize", "MIN"], "isize::min_value()"), - (["core", "i8", "MIN"], "i8::min_value()"), - (["core", "i16", "MIN"], "i16::min_value()"), - (["core", "i32", "MIN"], "i32::min_value()"), - (["core", "i64", "MIN"], "i64::min_value()"), - (["core", "i128", "MIN"], "i128::min_value()"), - (["core", "usize", "MIN"], "usize::min_value()"), - (["core", "u8", "MIN"], "u8::min_value()"), - (["core", "u16", "MIN"], "u16::min_value()"), - (["core", "u32", "MIN"], "u32::min_value()"), - (["core", "u64", "MIN"], "u64::min_value()"), - (["core", "u128", "MIN"], "u128::min_value()"), - // Max - (["core", "isize", "MAX"], "isize::max_value()"), - (["core", "i8", "MAX"], "i8::max_value()"), - (["core", "i16", "MAX"], "i16::max_value()"), - (["core", "i32", "MAX"], "i32::max_value()"), - (["core", "i64", "MAX"], "i64::max_value()"), - (["core", "i128", "MAX"], "i128::max_value()"), - (["core", "usize", "MAX"], "usize::max_value()"), - (["core", "u8", "MAX"], "u8::max_value()"), - (["core", "u16", "MAX"], "u16::max_value()"), - (["core", "u32", "MAX"], "u32::max_value()"), - (["core", "u64", "MAX"], "u64::max_value()"), - (["core", "u128", "MAX"], "u128::max_value()"), -]; diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index ef1bbfd8fa9..ef1a1d7ac29 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -1,9 +1,9 @@ use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_ast::ast; use rustc_ast::visit::FnKind; use rustc_errors::Applicability; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; use rustc_span::BytePos; diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index 0ada65ec785..9b5c3306f3a 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -1,13 +1,13 @@ use crate::reexport::Name; use crate::utils::{contains_name, higher, iter_input_pats, snippet, span_lint_and_then}; -use rustc::lint::in_external_macro; -use rustc::ty; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, Body, Expr, ExprKind, FnDecl, Guard, HirId, Local, MutTy, Pat, PatKind, Path, QPath, StmtKind, Ty, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index 61dc7d1c9c5..b308692b849 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -1,12 +1,12 @@ use crate::utils::sugg::Sugg; use crate::utils::{get_enclosing_block, match_qpath, span_lint_and_then, SpanlessEq}; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::intravisit::{walk_block, walk_expr, walk_stmt, NestedVisitorMap, Visitor}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, PatKind, QPath, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass, Lint}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::Symbol; diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index e777adb22cf..bb41e964d13 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,7 +1,7 @@ -use rustc::lint::in_external_macro; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Spanned; diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index e39a7b5e2ab..f1e223d9a48 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -1,9 +1,9 @@ use crate::utils::{get_trait_def_id, span_lint, trait_ref_of_method}; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_hir as hir; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { @@ -54,7 +54,7 @@ declare_lint_pass!(SuspiciousImpl => [SUSPICIOUS_ARITHMETIC_IMPL, SUSPICIOUS_OP_ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr<'_>) { - if let hir::ExprKind::Binary(binop, _, _) = expr.kind { + if let hir::ExprKind::Binary(binop, _, _) | hir::ExprKind::AssignOp(binop, ..) = expr.kind { match binop.node { hir::BinOpKind::Eq | hir::BinOpKind::Lt @@ -65,14 +65,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for SuspiciousImpl { _ => {}, } // Check if the binary expression is part of another bi/unary expression - // as a child node + // or operator assignment as a child node let mut parent_expr = cx.tcx.hir().get_parent_node(expr.hir_id); while parent_expr != hir::CRATE_HIR_ID { if let hir::Node::Expr(e) = cx.tcx.hir().get(parent_expr) { match e.kind { hir::ExprKind::Binary(..) | hir::ExprKind::Unary(hir::UnOp::UnNot, _) - | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => return, + | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) + | hir::ExprKind::AssignOp(..) => return, _ => {}, } } @@ -191,7 +192,8 @@ impl<'a, 'tcx> Visitor<'tcx> for BinaryExprVisitor { match expr.kind { hir::ExprKind::Binary(..) | hir::ExprKind::Unary(hir::UnOp::UnNot, _) - | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) => self.in_binary_expr = true, + | hir::ExprKind::Unary(hir::UnOp::UnNeg, _) + | hir::ExprKind::AssignOp(..) => self.in_binary_expr = true, _ => {}, } diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index a909216dccc..94d8296a9be 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -4,12 +4,11 @@ use crate::utils::{ span_lint_and_then, walk_ptrs_ty, SpanlessEq, }; use if_chain::if_chain; -use rustc::ty; use rustc_errors::Applicability; use rustc_hir::{Block, Expr, ExprKind, PatKind, QPath, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; -use rustc_span::Symbol; declare_clippy_lint! { /// **What it does:** Checks for manual swapping. @@ -199,7 +198,7 @@ fn check_for_slice<'a>(cx: &LateContext<'_, '_>, lhs1: &'a Expr<'_>, lhs2: &'a E if matches!(ty.kind, ty::Slice(_)) || matches!(ty.kind, ty::Array(_, _)) - || is_type_diagnostic_item(cx, ty, Symbol::intern("vec_type")) + || is_type_diagnostic_item(cx, ty, sym!(vec_type)) || match_type(cx, ty, &paths::VEC_DEQUE) { return Slice::Swappable(lhs1, idx1, idx2); diff --git a/clippy_lints/src/to_digit_is_some.rs b/clippy_lints/src/to_digit_is_some.rs index 5ec4a82b12e..c6302ca03d9 100644 --- a/clippy_lints/src/to_digit_is_some.rs +++ b/clippy_lints/src/to_digit_is_some.rs @@ -1,9 +1,9 @@ use crate::utils::{match_def_path, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; -use rustc::ty; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index d343ec4a848..075df19a71e 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,5 +1,6 @@ -use crate::utils::{in_macro, snippet, span_lint_and_help, SpanlessHash}; +use crate::utils::{in_macro, snippet, snippet_with_applicability, span_lint_and_help, SpanlessHash}; use rustc_data_structures::fx::FxHashMap; +use rustc_errors::Applicability; use rustc_hir::{GenericBound, Generics, WherePredicate}; use rustc_lint::{LateContext, LateLintPass}; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -41,6 +42,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { hasher.finish() }; let mut map = FxHashMap::default(); + let mut applicability = Applicability::MaybeIncorrect; for bound in gen.where_clause.predicates { if let WherePredicate::BoundPredicate(ref p) = bound { let h = hash(&p.bounded_ty); @@ -52,13 +54,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { for b in v.iter() { if let GenericBound::Trait(ref poly_trait_ref, _) = b { let path = &poly_trait_ref.trait_ref.path; - hint_string.push_str(&format!(" {} +", path)); + hint_string.push_str(&format!( + " {} +", + snippet_with_applicability(cx, path.span, "..", &mut applicability) + )); } } for b in p.bounds.iter() { if let GenericBound::Trait(ref poly_trait_ref, _) = b { let path = &poly_trait_ref.trait_ref.path; - hint_string.push_str(&format!(" {} +", path)); + hint_string.push_str(&format!( + " {} +", + snippet_with_applicability(cx, path.span, "..", &mut applicability) + )); } } hint_string.truncate(hint_string.len() - 2); diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index 6dad9eef522..3220bd9b9e2 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -2,11 +2,11 @@ use crate::utils::{ is_normalizable, last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then, sugg, }; use if_chain::if_chain; -use rustc::ty::{self, Ty}; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind, GenericArg, Mutability, QPath, TyKind, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use std::borrow::Cow; diff --git a/clippy_lints/src/transmuting_null.rs b/clippy_lints/src/transmuting_null.rs index 494dd448689..1d0332c5805 100644 --- a/clippy_lints/src/transmuting_null.rs +++ b/clippy_lints/src/transmuting_null.rs @@ -1,10 +1,10 @@ use crate::consts::{constant_context, Constant}; use crate::utils::{match_qpath, paths, span_lint}; use if_chain::if_chain; -use rustc::lint::in_external_macro; use rustc_ast::ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 0f00ed6c1fa..2c101220c5d 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -2,12 +2,12 @@ use std::cmp; use crate::utils::{is_copy, is_self_ty, snippet, span_lint_and_sugg}; use if_chain::if_chain; -use rustc::ty; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, FnDecl, HirId, ItemKind, MutTy, Mutability, Node}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; use rustc_session::config::Config as SessionConfig; use rustc_session::{declare_tool_lint, impl_lint_pass}; use rustc_span::Span; @@ -49,7 +49,7 @@ declare_clippy_lint! { /// fn foo(v: u32) {} /// ``` pub TRIVIALLY_COPY_PASS_BY_REF, - perf, + pedantic, "functions taking small copyable arguments by reference" } diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs index a6624408ce0..7018fa6804b 100644 --- a/clippy_lints/src/try_err.rs +++ b/clippy_lints/src/try_err.rs @@ -1,10 +1,10 @@ use crate::utils::{match_qpath, paths, snippet, snippet_with_macro_callsite, span_lint_and_sugg}; use if_chain::if_chain; -use rustc::lint::in_external_macro; -use rustc::ty::Ty; use rustc_errors::Applicability; use rustc_hir::{Arm, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::Ty; use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index d466924dc68..14f4ea154eb 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -5,10 +5,6 @@ use std::cmp::Ordering; use std::collections::BTreeMap; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; -use rustc::ty::layout::LayoutOf; -use rustc::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; use rustc_ast::ast::{FloatTy, IntTy, LitFloatType, LitIntType, LitKind, UintTy}; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -19,10 +15,14 @@ use rustc_hir::{ TraitItem, TraitItemKind, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty::{self, InferTy, Ty, TyCtxt, TypeckTables}; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::Span; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; +use rustc_target::abi::LayoutOf; use rustc_target::spec::abi::Abi; use rustc_typeck::hir_ty_to_ty; @@ -99,16 +99,33 @@ declare_clippy_lint! { /// represents an optional optional value which is logically the same thing as an optional /// value but has an unneeded extra level of wrapping. /// + /// If you have a case where `Some(Some(_))`, `Some(None)` and `None` are distinct cases, + /// consider a custom `enum` instead, with clear names for each case. + /// /// **Known problems:** None. /// /// **Example** /// ```rust - /// fn x() -> Option<Option<u32>> { + /// fn get_data() -> Option<Option<u32>> { /// None /// } /// ``` + /// + /// Better: + /// + /// ```rust + /// pub enum Contents { + /// Data(Vec<u8>), // Was Some(Some(Vec<u8>)) + /// NotYetFetched, // Was Some(None) + /// None, // Was None + /// } + /// + /// fn get_data() -> Contents { + /// Contents::None + /// } + /// ``` pub OPTION_OPTION, - complexity, + pedantic, "usage of `Option<Option<T>>`" } @@ -171,11 +188,35 @@ declare_clippy_lint! { "a borrow of a boxed type" } +declare_clippy_lint! { + /// **What it does:** Checks for use of redundant allocations anywhere in the code. + /// + /// **Why is this bad?** Expressions such as `Rc<&T>`, `Rc<Rc<T>>`, `Rc<Box<T>>`, `Box<&T>` + /// add an unnecessary level of indirection. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```rust + /// # use std::rc::Rc; + /// fn foo(bar: Rc<&usize>) {} + /// ``` + /// + /// Better: + /// + /// ```rust + /// fn foo(bar: &usize) {} + /// ``` + pub REDUNDANT_ALLOCATION, + perf, + "redundant allocation" +} + pub struct Types { vec_box_size_threshold: u64, } -impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX]); +impl_lint_pass!(Types => [BOX_VEC, VEC_BOX, OPTION_OPTION, LINKEDLIST, BORROWED_BOX, REDUNDANT_ALLOCATION]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { fn check_fn( @@ -217,7 +258,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Types { } /// Checks if `qpath` has last segment with type parameter matching `path` -fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&str]) -> bool { +fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&str]) -> Option<Span> { let last = last_path_segment(qpath); if_chain! { if let Some(ref params) = last.args; @@ -230,10 +271,27 @@ fn match_type_parameter(cx: &LateContext<'_, '_>, qpath: &QPath<'_>, path: &[&st if let Some(did) = qpath_res(cx, qpath, ty.hir_id).opt_def_id(); if match_def_path(cx, did, path); then { - return true; + return Some(ty.span); } } - false + None +} + +fn match_borrows_parameter(_cx: &LateContext<'_, '_>, qpath: &QPath<'_>) -> Option<Span> { + let last = last_path_segment(qpath); + if_chain! { + if let Some(ref params) = last.args; + if !params.parenthesized; + if let Some(ty) = params.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }); + if let TyKind::Rptr(..) = ty.kind; + then { + return Some(ty.span); + } + } + None } impl Types { @@ -267,7 +325,19 @@ impl Types { let res = qpath_res(cx, qpath, hir_id); if let Some(def_id) = res.opt_def_id() { if Some(def_id) == cx.tcx.lang_items().owned_box() { - if match_type_parameter(cx, qpath, &paths::VEC) { + if let Some(span) = match_borrows_parameter(cx, qpath) { + span_lint_and_sugg( + cx, + REDUNDANT_ALLOCATION, + hir_ty.span, + "usage of `Box<&T>`", + "try", + snippet(cx, span, "..").to_string(), + Applicability::MachineApplicable, + ); + return; // don't recurse into the type + } + if match_type_parameter(cx, qpath, &paths::VEC).is_some() { span_lint_and_help( cx, BOX_VEC, @@ -277,7 +347,44 @@ impl Types { ); return; // don't recurse into the type } - } else if cx.tcx.is_diagnostic_item(Symbol::intern("vec_type"), def_id) { + } else if cx.tcx.is_diagnostic_item(sym::Rc, def_id) { + if let Some(span) = match_type_parameter(cx, qpath, &paths::RC) { + span_lint_and_sugg( + cx, + REDUNDANT_ALLOCATION, + hir_ty.span, + "usage of `Rc<Rc<T>>`", + "try", + snippet(cx, span, "..").to_string(), + Applicability::MachineApplicable, + ); + return; // don't recurse into the type + } + if let Some(span) = match_type_parameter(cx, qpath, &paths::BOX) { + span_lint_and_sugg( + cx, + REDUNDANT_ALLOCATION, + hir_ty.span, + "usage of `Rc<Box<T>>`", + "try", + snippet(cx, span, "..").to_string(), + Applicability::MachineApplicable, + ); + return; // don't recurse into the type + } + if let Some(span) = match_borrows_parameter(cx, qpath) { + span_lint_and_sugg( + cx, + REDUNDANT_ALLOCATION, + hir_ty.span, + "usage of `Rc<&T>`", + "try", + snippet(cx, span, "..").to_string(), + Applicability::MachineApplicable, + ); + return; // don't recurse into the type + } + } else if cx.tcx.is_diagnostic_item(sym!(vec_type), def_id) { if_chain! { // Get the _ part of Vec<_> if let Some(ref last) = last_path_segment(qpath).args; @@ -313,8 +420,8 @@ impl Types { return; // don't recurse into the type } } - } else if match_def_path(cx, def_id, &paths::OPTION) { - if match_type_parameter(cx, qpath, &paths::OPTION) { + } else if cx.tcx.is_diagnostic_item(sym!(option_type), def_id) { + if match_type_parameter(cx, qpath, &paths::OPTION).is_some() { span_lint( cx, OPTION_OPTION, @@ -485,7 +592,7 @@ declare_clippy_lint! { /// }; /// ``` pub LET_UNIT_VALUE, - style, + pedantic, "creating a `let` binding to a value of unit type, which usually can't be used afterwards" } @@ -729,7 +836,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let x = std::u64::MAX; + /// let x = u64::MAX; /// x as f64; /// ``` pub CAST_PRECISION_LOSS, @@ -796,7 +903,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// std::u32::MAX as i32; // will yield a value of `-1` + /// u32::MAX as i32; // will yield a value of `-1` /// ``` pub CAST_POSSIBLE_WRAP, pedantic, @@ -1644,7 +1751,7 @@ declare_clippy_lint! { /// ```rust /// let vec: Vec<isize> = Vec::new(); /// if vec.len() <= 0 {} - /// if 100 > std::i32::MAX {} + /// if 100 > i32::MAX {} /// ``` pub ABSURD_EXTREME_COMPARISONS, correctness, @@ -1865,8 +1972,6 @@ impl Ord for FullInt { } fn numeric_cast_precast_bounds<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'_>) -> Option<(FullInt, FullInt)> { - use std::{i128, i16, i32, i64, i8, isize, u128, u16, u32, u64, u8, usize}; - if let ExprKind::Cast(ref cast_exp, _) = expr.kind { let pre_cast_ty = cx.tables.expr_ty(cast_exp); let cast_ty = cx.tables.expr_ty(expr); @@ -2064,7 +2169,7 @@ declare_clippy_lint! { /// pub fn foo<S: BuildHasher>(map: &mut HashMap<i32, i32, S>) { } /// ``` pub IMPLICIT_HASHER, - style, + pedantic, "missing generalization over different hashers" } diff --git a/clippy_lints/src/unnamed_address.rs b/clippy_lints/src/unnamed_address.rs new file mode 100644 index 00000000000..b6473fc594e --- /dev/null +++ b/clippy_lints/src/unnamed_address.rs @@ -0,0 +1,133 @@ +use crate::utils::{match_def_path, paths, span_lint, span_lint_and_help}; +use if_chain::if_chain; +use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty; +use rustc_session::{declare_lint_pass, declare_tool_lint}; + +declare_clippy_lint! { + /// **What it does:** Checks for comparisons with an address of a function item. + /// + /// **Why is this bad?** Function item address is not guaranteed to be unique and could vary + /// between different code generation units. Furthermore different function items could have + /// the same address after being merged together. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust + /// type F = fn(); + /// fn a() {} + /// let f: F = a; + /// if f == a { + /// // ... + /// } + /// ``` + pub FN_ADDRESS_COMPARISONS, + correctness, + "comparison with an address of a function item" +} + +declare_clippy_lint! { + /// **What it does:** Checks for comparisons with an address of a trait vtable. + /// + /// **Why is this bad?** Comparing trait objects pointers compares an vtable addresses which + /// are not guaranteed to be unique and could vary between different code generation units. + /// Furthermore vtables for different types could have the same address after being merged + /// together. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// + /// ```rust,ignore + /// let a: Rc<dyn Trait> = ... + /// let b: Rc<dyn Trait> = ... + /// if Rc::ptr_eq(&a, &b) { + /// ... + /// } + /// ``` + pub VTABLE_ADDRESS_COMPARISONS, + correctness, + "comparison with an address of a trait vtable" +} + +declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS, VTABLE_ADDRESS_COMPARISONS]); + +impl LateLintPass<'_, '_> for UnnamedAddress { + fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &Expr<'_>) { + fn is_comparison(binop: BinOpKind) -> bool { + match binop { + BinOpKind::Eq | BinOpKind::Lt | BinOpKind::Le | BinOpKind::Ne | BinOpKind::Ge | BinOpKind::Gt => true, + _ => false, + } + } + + fn is_trait_ptr(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + match cx.tables.expr_ty_adjusted(expr).kind { + ty::RawPtr(ty::TypeAndMut { ty, .. }) => ty.is_trait(), + _ => false, + } + } + + fn is_fn_def(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool { + if let ty::FnDef(..) = cx.tables.expr_ty(expr).kind { + true + } else { + false + } + } + + if_chain! { + if let ExprKind::Binary(binop, ref left, ref right) = expr.kind; + if is_comparison(binop.node); + if is_trait_ptr(cx, left) && is_trait_ptr(cx, right); + then { + span_lint_and_help( + cx, + VTABLE_ADDRESS_COMPARISONS, + expr.span, + "comparing trait object pointers compares a non-unique vtable address", + "consider extracting and comparing data pointers only", + ); + } + } + + if_chain! { + if let ExprKind::Call(ref func, [ref _left, ref _right]) = expr.kind; + if let ExprKind::Path(ref func_qpath) = func.kind; + if let Some(def_id) = cx.tables.qpath_res(func_qpath, func.hir_id).opt_def_id(); + if match_def_path(cx, def_id, &paths::PTR_EQ) || + match_def_path(cx, def_id, &paths::RC_PTR_EQ) || + match_def_path(cx, def_id, &paths::ARC_PTR_EQ); + let ty_param = cx.tables.node_substs(func.hir_id).type_at(0); + if ty_param.is_trait(); + then { + span_lint_and_help( + cx, + VTABLE_ADDRESS_COMPARISONS, + expr.span, + "comparing trait object pointers compares a non-unique vtable address", + "consider extracting and comparing data pointers only", + ); + } + } + + if_chain! { + if let ExprKind::Binary(binop, ref left, ref right) = expr.kind; + if is_comparison(binop.node); + if cx.tables.expr_ty_adjusted(left).is_fn_ptr() && + cx.tables.expr_ty_adjusted(right).is_fn_ptr(); + if is_fn_def(cx, left) || is_fn_def(cx, right); + then { + span_lint( + cx, + FN_ADDRESS_COMPARISONS, + expr.span, + "comparing with a non-unique address of a function item", + ); + } + } + } +} diff --git a/clippy_lints/src/unused_self.rs b/clippy_lints/src/unused_self.rs index a45b4a6869c..4483059e9ec 100644 --- a/clippy_lints/src/unused_self.rs +++ b/clippy_lints/src/unused_self.rs @@ -1,9 +1,9 @@ use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_hir::def::Res; use rustc_hir::intravisit::{walk_path, NestedVisitorMap, Visitor}; -use rustc_hir::{AssocItemKind, HirId, ImplItem, ImplItemKind, ImplItemRef, ItemKind, Path}; +use rustc_hir::{HirId, ImplItem, ImplItemKind, ItemKind, Path}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint}; use crate::utils::span_lint_and_help; @@ -45,45 +45,36 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedSelf { return; } let parent = cx.tcx.hir().get_parent_item(impl_item.hir_id); - let item = cx.tcx.hir().expect_item(parent); - if let ItemKind::Impl { - of_trait: None, - items: impl_item_refs, - .. - } = item.kind - { - for impl_item_ref in impl_item_refs { - if_chain! { - if let ImplItemRef { - kind: AssocItemKind::Method { has_self: true }, - .. - } = impl_item_ref; - if let ImplItemKind::Fn(_, body_id) = &impl_item.kind; - let body = cx.tcx.hir().body(*body_id); - if !body.params.is_empty(); - then { - let self_param = &body.params[0]; - let self_hir_id = self_param.pat.hir_id; - let mut visitor = UnusedSelfVisitor { - cx, - uses_self: false, - self_hir_id: &self_hir_id, - }; - visitor.visit_body(body); - if !visitor.uses_self { - span_lint_and_help( - cx, - UNUSED_SELF, - self_param.span, - "unused `self` argument", - "consider refactoring to a associated function", - ); - return; - } - } + let parent_item = cx.tcx.hir().expect_item(parent); + let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); + let assoc_item = cx.tcx.associated_item(def_id); + if_chain! { + if let ItemKind::Impl { of_trait: None, .. } = parent_item.kind; + if assoc_item.fn_has_self_parameter; + if let ImplItemKind::Fn(.., body_id) = &impl_item.kind; + let body = cx.tcx.hir().body(*body_id); + if !body.params.is_empty(); + then { + let self_param = &body.params[0]; + let self_hir_id = self_param.pat.hir_id; + let mut visitor = UnusedSelfVisitor { + cx, + uses_self: false, + self_hir_id: &self_hir_id, + }; + visitor.visit_body(body); + if !visitor.uses_self { + span_lint_and_help( + cx, + UNUSED_SELF, + self_param.span, + "unused `self` argument", + "consider refactoring to a associated function", + ); + return; } } - }; + } } } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 767b48d4a09..98dc29507c2 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -1,10 +1,10 @@ -use crate::utils::{higher::if_block, match_type, paths, span_lint_and_then, usage::is_potentially_mutated}; +use crate::utils::{higher::if_block, is_type_diagnostic_item, span_lint_and_then, usage::is_potentially_mutated}; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; use rustc_hir::intravisit::{walk_expr, walk_fn, FnKind, NestedVisitorMap, Visitor}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, HirId, Path, QPath, UnOp}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; @@ -100,7 +100,7 @@ fn collect_unwrap_info<'a, 'tcx>( if let ExprKind::MethodCall(method_name, _, args) = &expr.kind; if let ExprKind::Path(QPath::Resolved(None, path)) = &args[0].kind; let ty = cx.tables.expr_ty(&args[0]); - if match_type(cx, ty, &paths::OPTION) || match_type(cx, ty, &paths::RESULT); + if is_type_diagnostic_item(cx, ty, sym!(option_type)) || is_type_diagnostic_item(cx, ty, sym!(result_type)); let name = method_name.ident.as_str(); if ["is_some", "is_none", "is_ok", "is_err"].contains(&&*name); then { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 73a986b7901..f8e1aff33e7 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -1,8 +1,4 @@ use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::lint::in_external_macro; -use rustc::ty; -use rustc::ty::{DefIdTree, Ty}; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; @@ -12,8 +8,13 @@ use rustc_hir::{ TyKind, }; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::lint::in_external_macro; +use rustc_middle::ty; +use rustc_middle::ty::{DefIdTree, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::symbol::kw; +use rustc_typeck::hir_ty_to_ty; use crate::utils::{differing_macro_contexts, span_lint_and_sugg}; @@ -80,37 +81,28 @@ fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path<'_>, last_segment: O ); } -struct TraitImplTyVisitor<'a, 'tcx> { - item_type: Ty<'tcx>, +// FIXME: always use this (more correct) visitor, not just in method signatures. +struct SemanticUseSelfVisitor<'a, 'tcx> { cx: &'a LateContext<'a, 'tcx>, - trait_type_walker: ty::walk::TypeWalker<'tcx>, - impl_type_walker: ty::walk::TypeWalker<'tcx>, + self_ty: Ty<'tcx>, } -impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { +impl<'a, 'tcx> Visitor<'tcx> for SemanticUseSelfVisitor<'a, 'tcx> { type Map = Map<'tcx>; - fn visit_ty(&mut self, t: &'tcx hir::Ty<'_>) { - let trait_ty = self.trait_type_walker.next(); - let impl_ty = self.impl_type_walker.next(); - - if_chain! { - if let TyKind::Path(QPath::Resolved(_, path)) = &t.kind; - - // The implementation and trait types don't match which means that - // the concrete type was specified by the implementation - if impl_ty != trait_ty; - if let Some(impl_ty) = impl_ty; - if self.item_type == impl_ty; - then { - match path.res { - def::Res::SelfTy(..) => {}, - _ => span_use_self_lint(self.cx, path, None) - } + fn visit_ty(&mut self, hir_ty: &'tcx hir::Ty<'_>) { + if let TyKind::Path(QPath::Resolved(_, path)) = &hir_ty.kind { + match path.res { + def::Res::SelfTy(..) => {}, + _ => { + if hir_ty_to_ty(self.cx.tcx, hir_ty) == self.self_ty { + span_use_self_lint(self.cx, path, None); + } + }, } } - walk_ty(self, t) + walk_ty(self, hir_ty) } fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> { @@ -120,48 +112,48 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { fn check_trait_method_impl_decl<'a, 'tcx>( cx: &'a LateContext<'a, 'tcx>, - item_type: Ty<'tcx>, impl_item: &ImplItem<'_>, impl_decl: &'tcx FnDecl<'_>, - impl_trait_ref: &ty::TraitRef<'_>, + impl_trait_ref: ty::TraitRef<'tcx>, ) { let trait_method = cx .tcx .associated_items(impl_trait_ref.def_id) - .find_by_name_and_kind(cx.tcx, impl_item.ident, ty::AssocKind::Method, impl_trait_ref.def_id) + .find_by_name_and_kind(cx.tcx, impl_item.ident, ty::AssocKind::Fn, impl_trait_ref.def_id) .expect("impl method matches a trait method"); let trait_method_sig = cx.tcx.fn_sig(trait_method.def_id); let trait_method_sig = cx.tcx.erase_late_bound_regions(&trait_method_sig); - let impl_method_def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); - let impl_method_sig = cx.tcx.fn_sig(impl_method_def_id); - let impl_method_sig = cx.tcx.erase_late_bound_regions(&impl_method_sig); - - let output_ty = if let FnRetTy::Return(ty) = &impl_decl.output { + let output_hir_ty = if let FnRetTy::Return(ty) = &impl_decl.output { Some(&**ty) } else { None }; - // `impl_decl_ty` (of type `hir::Ty`) represents the type declared in the signature. - // `impl_ty` (of type `ty:TyS`) is the concrete type that the compiler has determined for - // that declaration. We use `impl_decl_ty` to see if the type was declared as `Self` - // and use `impl_ty` to check its concrete type. - for (impl_decl_ty, (impl_ty, trait_ty)) in impl_decl.inputs.iter().chain(output_ty).zip( - impl_method_sig - .inputs_and_output - .iter() - .zip(trait_method_sig.inputs_and_output), - ) { - let mut visitor = TraitImplTyVisitor { - cx, - item_type, - trait_type_walker: trait_ty.walk(), - impl_type_walker: impl_ty.walk(), - }; - - visitor.visit_ty(&impl_decl_ty); + // `impl_hir_ty` (of type `hir::Ty`) represents the type written in the signature. + // `trait_ty` (of type `ty::Ty`) is the semantic type for the signature in the trait. + // We use `impl_hir_ty` to see if the type was written as `Self`, + // `hir_ty_to_ty(...)` to check semantic types of paths, and + // `trait_ty` to determine which parts of the signature in the trait, mention + // the type being implemented verbatim (as opposed to `Self`). + for (impl_hir_ty, trait_ty) in impl_decl + .inputs + .iter() + .chain(output_hir_ty) + .zip(trait_method_sig.inputs_and_output) + { + // Check if the input/output type in the trait method specifies the implemented + // type verbatim, and only suggest `Self` if that isn't the case. + // This avoids suggestions to e.g. replace `Vec<u8>` with `Vec<Self>`, + // in an `impl Trait for u8`, when the trait always uses `Vec<u8>`. + // See also https://github.com/rust-lang/rust-clippy/issues/2894. + let self_ty = impl_trait_ref.self_ty(); + if !trait_ty.walk().any(|inner| inner == self_ty.into()) { + let mut visitor = SemanticUseSelfVisitor { cx, self_ty }; + + visitor.visit_ty(&impl_hir_ty); + } } } @@ -197,8 +189,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { let impl_item = cx.tcx.hir().impl_item(impl_item_ref.id); if let ImplItemKind::Fn(FnSig{ decl: impl_decl, .. }, impl_body_id) = &impl_item.kind { - let item_type = cx.tcx.type_of(impl_def_id); - check_trait_method_impl_decl(cx, item_type, impl_item, impl_decl, &impl_trait_ref); + check_trait_method_impl_decl(cx, impl_item, impl_decl, impl_trait_ref); let body = cx.tcx.hir().body(*impl_body_id); visitor.visit_body(body); diff --git a/clippy_lints/src/utils/attrs.rs b/clippy_lints/src/utils/attrs.rs index e27e1b7f2e6..104ea7de5c2 100644 --- a/clippy_lints/src/utils/attrs.rs +++ b/clippy_lints/src/utils/attrs.rs @@ -1,4 +1,5 @@ use rustc_ast::ast; +use rustc_ast::expand::is_proc_macro_attr; use rustc_errors::Applicability; use rustc_session::Session; use std::str::FromStr; @@ -123,12 +124,5 @@ fn parse_attrs<F: FnMut(u64)>(sess: &Session, attrs: &[ast::Attribute], name: &' /// Return true if the attributes contain any of `proc_macro`, /// `proc_macro_derive` or `proc_macro_attribute`, false otherwise pub fn is_proc_macro(attrs: &[ast::Attribute]) -> bool { - use rustc_span::Symbol; - - let syms = [ - Symbol::intern("proc_macro"), - Symbol::intern("proc_macro_derive"), - Symbol::intern("proc_macro_attribute"), - ]; - attrs.iter().any(|attr| syms.iter().any(move |&s| attr.check_name(s))) + attrs.iter().any(is_proc_macro_attr) } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 4fcaf4264d7..0c8f06da9bb 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -2,7 +2,6 @@ //! to generate a clippy lint detecting said code automatically. use crate::utils::{get_attr, higher}; -use rustc::hir::map::Map; use rustc_ast::ast::{Attribute, LitFloatType, LitKind}; use rustc_ast::walk_list; use rustc_data_structures::fx::FxHashMap; @@ -10,6 +9,7 @@ use rustc_hir as hir; use rustc_hir::intravisit::{NestedVisitorMap, Visitor}; use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, Pat, PatKind, QPath, Stmt, StmtKind, TyKind}; use rustc_lint::{LateContext, LateLintPass, LintContext}; +use rustc_middle::hir::map::Map; use rustc_session::Session; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -468,9 +468,9 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Ret(None) = {};", current); } }, - ExprKind::InlineAsm(_) => { - println!("InlineAsm(_) = {};", current); - println!(" // unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); + ExprKind::LlvmInlineAsm(_) => { + println!("LlvmInlineAsm(_) = {};", current); + println!(" // unimplemented: `ExprKind::LlvmInlineAsm` is not further destructured at the moment"); }, ExprKind::Struct(ref path, ref fields, ref opt_base) => { let path_pat = self.next("path"); diff --git a/clippy_lints/src/utils/diagnostics.rs b/clippy_lints/src/utils/diagnostics.rs index cc519d52552..409bb2043d4 100644 --- a/clippy_lints/src/utils/diagnostics.rs +++ b/clippy_lints/src/utils/diagnostics.rs @@ -60,7 +60,7 @@ pub fn span_lint<T: LintContext>(cx: &T, lint: &'static Lint, sp: impl Into<Mult /// 6 | let other_f64_nan = 0.0f64 / 0.0; /// | ^^^^^^^^^^^^ /// | -/// = help: Consider using `std::f64::NAN` if you would like a constant representing NaN +/// = help: Consider using `f64::NAN` if you would like a constant representing NaN /// ``` pub fn span_lint_and_help<'a, T: LintContext>(cx: &'a T, lint: &'static Lint, span: Span, msg: &str, help: &str) { cx.struct_span_lint(lint, span, |ldb| { diff --git a/clippy_lints/src/utils/higher.rs b/clippy_lints/src/utils/higher.rs index f27cc57fb54..33fba7df8d3 100644 --- a/clippy_lints/src/utils/higher.rs +++ b/clippy_lints/src/utils/higher.rs @@ -5,10 +5,10 @@ use crate::utils::{is_expn_of, match_def_path, match_qpath, paths}; use if_chain::if_chain; -use rustc::ty; use rustc_ast::ast; use rustc_hir as hir; use rustc_lint::LateContext; +use rustc_middle::ty; /// Converts a hir binary operator to the corresponding `ast` type. #[must_use] @@ -280,6 +280,9 @@ pub fn vec_macro<'e>(cx: &LateContext<'_, '_>, expr: &'e hir::Expr<'_>) -> Optio None } + else if match_def_path(cx, fun_def_id, &paths::VEC_NEW) && args.is_empty() { + Some(VecArgs::Vec(&[])) + } else { None }; diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index dcdec2e7eb6..02b721fd378 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -1,7 +1,5 @@ use crate::consts::{constant_context, constant_simple}; use crate::utils::differing_macro_contexts; -use rustc::ich::StableHashingContextProvider; -use rustc::ty::TypeckTables; use rustc_ast::ast::Name; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_hir::{ @@ -10,6 +8,8 @@ use rustc_hir::{ TyKind, TypeBinding, }; use rustc_lint::LateContext; +use rustc_middle::ich::StableHashingContextProvider; +use rustc_middle::ty::TypeckTables; use std::hash::Hash; /// Type used to check whether two ast are the same. This is different from the @@ -474,7 +474,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(a); self.hash_expr(i); }, - ExprKind::InlineAsm(..) | ExprKind::Err => {}, + ExprKind::LlvmInlineAsm(..) | ExprKind::Err => {}, ExprKind::Lit(ref l) => { l.node.hash(&mut self.s); }, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index c6a47f05e24..b97fc9547e5 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -3,7 +3,6 @@ use crate::utils::get_attr; use rustc_ast::ast::Attribute; use rustc_hir as hir; -use rustc_hir::print; use rustc_lint::{LateContext, LateLintPass, LintContext}; use rustc_session::Session; use rustc_session::{declare_lint_pass, declare_tool_lint}; @@ -50,7 +49,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { hir::VisibilityKind::Crate(_) => println!("visible crate wide"), hir::VisibilityKind::Restricted { ref path, .. } => println!( "visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false)) ), hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"), } @@ -283,10 +282,10 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr<'_>, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprKind::InlineAsm(ref asm) => { + hir::ExprKind::LlvmInlineAsm(ref asm) => { let inputs = &asm.inputs_exprs; let outputs = &asm.outputs_exprs; - println!("{}InlineAsm", ind); + println!("{}LlvmInlineAsm", ind); println!("{}inputs:", ind); for e in inputs.iter() { print_expr(cx, e, indent + 1); @@ -333,7 +332,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item<'_>) { hir::VisibilityKind::Crate(_) => println!("visible crate wide"), hir::VisibilityKind::Restricted { ref path, .. } => println!( "visible in module `{}`", - print::to_string(print::NO_ANN, |s| s.print_path(path, false)) + rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_path(path, false)) ), hir::VisibilityKind::Inherited => println!("visibility inherited from outer item"), } @@ -427,7 +426,7 @@ fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, indent: usize) { println!( "{}name: {}", ind, - print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) + rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)) ); println!("{}ignore leftover fields: {}", ind, ignore); println!("{}fields:", ind); @@ -444,7 +443,7 @@ fn print_pat(cx: &LateContext<'_, '_>, pat: &hir::Pat<'_>, indent: usize) { println!( "{}path: {}", ind, - print::to_string(print::NO_ANN, |s| s.print_qpath(path, false)) + rustc_hir_pretty::to_string(rustc_hir_pretty::NO_ANN, |s| s.print_qpath(path, false)) ); if let Some(dot_position) = opt_dots_position { println!("{}dot position: {}", ind, dot_position); diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 7dbb0d5a9ab..bc2200800de 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -3,7 +3,6 @@ use crate::utils::{ walk_ptrs_ty, }; use if_chain::if_chain; -use rustc::hir::map::Map; use rustc_ast::ast::{Crate as AstCrate, ItemKind, LitKind, Name, NodeId}; use rustc_ast::visit::FnKind; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -13,6 +12,7 @@ use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Crate, Expr, ExprKind, HirId, Item, MutTy, Mutability, Path, Ty, TyKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass}; +use rustc_middle::hir::map::Map; use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::SymbolStr; diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 871f7e6c31b..f7a91fcdd21 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -25,14 +25,6 @@ use std::borrow::Cow; use std::mem; use if_chain::if_chain; -use rustc::hir::map::Map; -use rustc::traits; -use rustc::ty::{ - self, - layout::{self, IntegerExt}, - subst::GenericArg, - Binder, Ty, TyCtxt, TypeFoldable, -}; use rustc_ast::ast::{self, Attribute, LitKind}; use rustc_attr as attr; use rustc_errors::Applicability; @@ -47,10 +39,14 @@ use rustc_hir::{ }; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::{LateContext, Level, Lint, LintContext}; +use rustc_middle::hir::map::Map; +use rustc_middle::traits; +use rustc_middle::ty::{self, layout::IntegerExt, subst::GenericArg, Binder, Ty, TyCtxt, TypeFoldable}; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::original_sp; use rustc_span::symbol::{self, kw, Symbol}; use rustc_span::{BytePos, Pos, Span, DUMMY_SP}; +use rustc_target::abi::Integer; use rustc_trait_selection::traits::predicate_for_trait_def; use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt; use rustc_trait_selection::traits::query::normalize::AtExt; @@ -230,7 +226,7 @@ pub fn match_qpath(path: &QPath<'_>, segments: &[&str]) -> bool { /// } /// /// if match_path(ty_path, &["rustc", "lint", "Lint"]) { -/// // This is a `rustc::lint::Lint`. +/// // This is a `rustc_middle::lint::Lint`. /// } /// ``` pub fn match_path(path: &Path<'_>, segments: &[&str]) -> bool { @@ -832,7 +828,7 @@ pub fn is_integer_literal(expr: &Expr<'_>, value: u128) -> bool { /// Examples of coercions can be found in the Nomicon at /// <https://doc.rust-lang.org/nomicon/coercions.html>. /// -/// See `rustc::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more +/// See `rustc_middle::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more /// information on adjustments and coercions. pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr<'_>) -> bool { cx.tables.adjustments().get(e.hir_id).is_some() @@ -1080,9 +1076,7 @@ pub fn get_arg_name(pat: &Pat<'_>) -> Option<ast::Name> { } pub fn int_bits(tcx: TyCtxt<'_>, ity: ast::IntTy) -> u64 { - layout::Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)) - .size() - .bits() + Integer::from_attr(&tcx, attr::IntType::SignedInt(ity)).size().bits() } #[allow(clippy::cast_possible_wrap)] @@ -1101,9 +1095,7 @@ pub fn unsext(tcx: TyCtxt<'_>, u: i128, ity: ast::IntTy) -> u128 { /// clip unused bytes pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: ast::UintTy) -> u128 { - let bits = layout::Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)) - .size() - .bits(); + let bits = Integer::from_attr(&tcx, attr::IntType::UnsignedInt(ity)).size().bits(); let amt = 128 - bits; (u << amt) >> amt } @@ -1224,14 +1216,16 @@ pub fn match_function_call<'a, 'tcx>( /// to avoid crashes on `layout_of`. pub fn is_normalizable<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, param_env: ty::ParamEnv<'tcx>, ty: Ty<'tcx>) -> bool { cx.tcx.infer_ctxt().enter(|infcx| { - let cause = rustc::traits::ObligationCause::dummy(); + let cause = rustc_middle::traits::ObligationCause::dummy(); infcx.at(&cause, param_env).normalize(&ty).is_ok() }) } pub fn match_def_path<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, did: DefId, syms: &[&str]) -> bool { - let path = cx.get_def_path(did); - path.len() == syms.len() && path.into_iter().zip(syms.iter()).all(|(a, &b)| a.as_str() == b) + // We have to convert `syms` to `&[Symbol]` here because rustc's `match_def_path` + // accepts only that. We should probably move to Symbols in Clippy as well. + let syms = syms.iter().map(|p| Symbol::intern(p)).collect::<Vec<Symbol>>(); + cx.match_def_path(did, &syms) } /// Returns the list of condition expressions and the list of blocks in a @@ -1397,7 +1391,12 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_, '_>, did: DefId) -> bool .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }) .collect(); - !traits::normalize_and_test_predicates(cx.tcx, traits::elaborate_predicates(cx.tcx, predicates).collect()) + !traits::normalize_and_test_predicates( + cx.tcx, + traits::elaborate_predicates(cx.tcx, predicates) + .map(|o| o.predicate) + .collect::<Vec<_>>(), + ) } #[cfg(test)] diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 6cb1f694fd5..d93f8a1e560 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -1,14 +1,18 @@ //! This module contains paths to types and functions Clippy needs to know //! about. +//! +//! Whenever possible, please consider diagnostic items over hardcoded paths. +//! See <https://github.com/rust-lang/rust-clippy/issues/5393> for more information. pub const ANY_TRAIT: [&str; 3] = ["std", "any", "Any"]; -pub const ARC: [&str; 3] = ["alloc", "sync", "Arc"]; +pub const ARC_PTR_EQ: [&str; 4] = ["alloc", "sync", "Arc", "ptr_eq"]; pub const ASMUT_TRAIT: [&str; 3] = ["core", "convert", "AsMut"]; pub const ASREF_TRAIT: [&str; 3] = ["core", "convert", "AsRef"]; pub const BEGIN_PANIC: [&str; 3] = ["std", "panicking", "begin_panic"]; pub const BEGIN_PANIC_FMT: [&str; 3] = ["std", "panicking", "begin_panic_fmt"]; pub const BINARY_HEAP: [&str; 4] = ["alloc", "collections", "binary_heap", "BinaryHeap"]; pub const BORROW_TRAIT: [&str; 3] = ["core", "borrow", "Borrow"]; +pub const BOX: [&str; 3] = ["alloc", "boxed", "Box"]; pub const BTREEMAP: [&str; 5] = ["alloc", "collections", "btree", "map", "BTreeMap"]; pub const BTREEMAP_ENTRY: [&str; 5] = ["alloc", "collections", "btree", "map", "Entry"]; pub const BTREESET: [&str; 5] = ["alloc", "collections", "btree", "set", "BTreeSet"]; @@ -57,8 +61,6 @@ pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_MAYBEUNINIT: [&str; 4] = ["core", "mem", "maybe_uninit", "MaybeUninit"]; pub const MEM_MAYBEUNINIT_UNINIT: [&str; 5] = ["core", "mem", "maybe_uninit", "MaybeUninit", "uninit"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; -pub const MEM_UNINITIALIZED: [&str; 3] = ["core", "mem", "uninitialized"]; -pub const MEM_ZEROED: [&str; 3] = ["core", "mem", "zeroed"]; pub const MUTEX: [&str; 4] = ["std", "sync", "mutex", "Mutex"]; pub const MUTEX_GUARD: [&str; 4] = ["std", "sync", "mutex", "MutexGuard"]; pub const OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; @@ -74,6 +76,7 @@ pub const PATH: [&str; 3] = ["std", "path", "Path"]; pub const PATH_BUF: [&str; 3] = ["std", "path", "PathBuf"]; pub const PATH_BUF_AS_PATH: [&str; 4] = ["std", "path", "PathBuf", "as_path"]; pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; +pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_NULL: [&str; 2] = ["ptr", "null"]; pub const PTR_NULL_MUT: [&str; 2] = ["ptr", "null_mut"]; pub const RANGE: [&str; 3] = ["core", "ops", "Range"]; @@ -90,6 +93,7 @@ pub const RANGE_TO_INCLUSIVE: [&str; 3] = ["core", "ops", "RangeToInclusive"]; pub const RANGE_TO_INCLUSIVE_STD: [&str; 3] = ["std", "ops", "RangeToInclusive"]; pub const RANGE_TO_STD: [&str; 3] = ["std", "ops", "RangeTo"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; +pub const RC_PTR_EQ: [&str; 4] = ["alloc", "rc", "Rc", "ptr_eq"]; pub const RECEIVER: [&str; 4] = ["std", "sync", "mpsc", "Receiver"]; pub const REGEX: [&str; 3] = ["regex", "re_unicode", "Regex"]; pub const REGEX_BUILDER_NEW: [&str; 5] = ["regex", "re_builder", "unicode", "RegexBuilder", "new"]; @@ -128,5 +132,6 @@ pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"]; pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"]; pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; +pub const VEC_NEW: [&str; 4] = ["alloc", "vec", "Vec", "new"]; pub const WEAK_ARC: [&str; 3] = ["alloc", "sync", "Weak"]; pub const WEAK_RC: [&str; 3] = ["alloc", "rc", "Weak"]; diff --git a/clippy_lints/src/utils/ptr.rs b/clippy_lints/src/utils/ptr.rs index 238c2277a93..240bf2449cb 100644 --- a/clippy_lints/src/utils/ptr.rs +++ b/clippy_lints/src/utils/ptr.rs @@ -1,9 +1,9 @@ use crate::utils::{get_pat_name, match_var, snippet}; -use rustc::hir::map::Map; use rustc_ast::ast::Name; use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Body, BodyId, Expr, ExprKind, Param}; use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; use rustc_span::source_map::Span; use std::borrow::Cow; diff --git a/clippy_lints/src/utils/sugg.rs b/clippy_lints/src/utils/sugg.rs index c0c7959b571..8957121a0a5 100644 --- a/clippy_lints/src/utils/sugg.rs +++ b/clippy_lints/src/utils/sugg.rs @@ -108,7 +108,7 @@ impl<'a> Sugg<'a> { | hir::ExprKind::Call(..) | hir::ExprKind::Field(..) | hir::ExprKind::Index(..) - | hir::ExprKind::InlineAsm(..) + | hir::ExprKind::LlvmInlineAsm(..) | hir::ExprKind::Lit(..) | hir::ExprKind::Loop(..) | hir::ExprKind::MethodCall(..) @@ -150,7 +150,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Field(..) | ast::ExprKind::ForLoop(..) | ast::ExprKind::Index(..) - | ast::ExprKind::InlineAsm(..) + | ast::ExprKind::LlvmInlineAsm(..) | ast::ExprKind::Lit(..) | ast::ExprKind::Loop(..) | ast::ExprKind::MacCall(..) diff --git a/clippy_lints/src/utils/usage.rs b/clippy_lints/src/utils/usage.rs index a08251c1a4e..1838fa5f8ff 100644 --- a/clippy_lints/src/utils/usage.rs +++ b/clippy_lints/src/utils/usage.rs @@ -1,6 +1,4 @@ use crate::utils::match_var; -use rustc::hir::map::Map; -use rustc::ty; use rustc_ast::ast; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::Res; @@ -8,6 +6,8 @@ use rustc_hir::intravisit::{walk_expr, NestedVisitorMap, Visitor}; use rustc_hir::{Expr, HirId, Path}; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint::LateContext; +use rustc_middle::hir::map::Map; +use rustc_middle::ty; use rustc_span::symbol::Ident; use rustc_typeck::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Place, PlaceBase}; diff --git a/clippy_lints/src/vec.rs b/clippy_lints/src/vec.rs index 726a34856ae..1174f421577 100644 --- a/clippy_lints/src/vec.rs +++ b/clippy_lints/src/vec.rs @@ -1,10 +1,10 @@ use crate::consts::constant; use crate::utils::{higher, is_copy, snippet_with_applicability, span_lint_and_sugg}; use if_chain::if_chain; -use rustc::ty::{self, Ty}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass}; +use rustc_middle::ty::{self, Ty}; use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_span::source_map::Span; diff --git a/clippy_lints/src/verbose_file_reads.rs b/clippy_lints/src/verbose_file_reads.rs index 37885317c58..55d7983249a 100644 --- a/clippy_lints/src/verbose_file_reads.rs +++ b/clippy_lints/src/verbose_file_reads.rs @@ -26,7 +26,7 @@ declare_clippy_lint! { /// let mut bytes = fs::read("foo.txt").unwrap(); /// ``` pub VERBOSE_FILE_READS, - complexity, + restriction, "use of `File::read_to_end` or `File::read_to_string`" } diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 42cb9a77db0..afd10d9ed53 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -8,8 +8,7 @@ use rustc_session::{declare_lint_pass, declare_tool_lint}; declare_clippy_lint! { /// **What it does:** Checks for `0.0 / 0.0`. /// - /// **Why is this bad?** It's less readable than `std::f32::NAN` or - /// `std::f64::NAN`. + /// **Why is this bad?** It's less readable than `f32::NAN` or `f64::NAN`. /// /// **Known problems:** None. /// @@ -19,7 +18,7 @@ declare_clippy_lint! { /// ``` pub ZERO_DIVIDED_BY_ZERO, complexity, - "usage of `0.0 / 0.0` to obtain NaN instead of `std::f32::NAN` or `std::f64::NAN`" + "usage of `0.0 / 0.0` to obtain NaN instead of `f32::NAN` or `f64::NAN`" } declare_lint_pass!(ZeroDiv => [ZERO_DIVIDED_BY_ZERO]); @@ -38,7 +37,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ZeroDiv { if Constant::F32(0.0) == lhs_value || Constant::F64(0.0) == lhs_value; if Constant::F32(0.0) == rhs_value || Constant::F64(0.0) == rhs_value; then { - // since we're about to suggest a use of std::f32::NaN or std::f64::NaN, + // since we're about to suggest a use of f32::NAN or f64::NAN, // match the precision of the literals that are given. let float_type = match (lhs_value, rhs_value) { (Constant::F64(_), _) @@ -51,7 +50,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ZeroDiv { expr.span, "constant division of `0.0` with `0.0` will always result in NaN", &format!( - "Consider using `std::{}::NAN` if you would like a constant representing NaN", + "Consider using `{}::NAN` if you would like a constant representing NaN", float_type, ), ); diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 1d78a27820a..a66d4e66add 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -463,11 +463,11 @@ don't hesitate to ask on [Discord] or in the issue/PR. [utils]: https://github.com/rust-lang/rust-clippy/blob/master/clippy_lints/src/utils/mod.rs [if_chain]: https://docs.rs/if_chain/*/if_chain/ [from_expansion]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html#method.from_expansion -[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/lint/fn.in_external_macro.html +[in_external_macro]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/fn.in_external_macro.html [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html [applicability]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/enum.Applicability.html [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/ -[nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ +[nightly_docs]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ [ast]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/ast/index.html -[ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc/ty/sty/index.html +[ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/sty/index.html [Discord]: https://discord.gg/rust-lang diff --git a/doc/backport.md b/doc/backport.md new file mode 100644 index 00000000000..259696658ea --- /dev/null +++ b/doc/backport.md @@ -0,0 +1,50 @@ +# Backport Changes + +Sometimes it is necessary to backport changes to the beta release of Clippy. +Backports in Clippy are rare and should be approved by the Clippy team. For +example, a backport is done, if a crucial ICE was fixed or a lint is broken to a +point, that it has to be disabled, before landing on stable. + +Backports are done to the `beta` release of Clippy. Backports to stable Clippy +releases basically don't exist, since this would require a Rust point release, +which is almost never justifiable for a Clippy fix. + + +## Backport the changes + +Backports are done on the beta branch of the Clippy repository. + +```bash +# Assuming the current directory corresponds to the Clippy repository +$ git checkout beta +$ git checkout -b backport +$ git cherry-pick <SHA> # `<SHA>` is the commit hash of the commit, that should be backported +$ git push origin backport +``` + +After this, you can open a PR to the `beta` branch of the Clippy repository. + + +## Update Clippy in the Rust Repository + +This step must be done, **after** the PR of the previous step was merged. + +After the backport landed in the Clippy repository, also the Clippy version on +the Rust `beta` branch has to be updated. + +```bash +# Assuming the current directory corresponds to the Rust repository +$ git checkout beta +$ git checkout -b clippy_backport +$ pushd src/tools/clippy +$ git fetch +$ git checkout beta +$ popd +$ git add src/tools/clippy +§ git commit -m "Update Clippy" +$ git push origin clippy_backport +``` + +After this you can open a PR to the `beta` branch of the Rust repository. In +this PR you should tag the Clippy team member, that agreed to the backport or +the `@rust-lang/clippy` team. Make sure to add `[beta]` to the title of the PR. diff --git a/doc/release.md b/doc/release.md new file mode 100644 index 00000000000..25ddff4c48c --- /dev/null +++ b/doc/release.md @@ -0,0 +1,101 @@ +# Release a new Clippy Version + +_NOTE: This document is probably only relevant to you, if you're a member of the +Clippy team._ + +Clippy is released together with stable Rust releases. The dates for these +releases can be found at the [Rust Forge]. This document explains the necessary +steps to create a Clippy release. + +1. [Find the Clippy commit](#find-the-clippy-commit) +2. [Tag the stable commit](#tag-the-stable-commit) +3. [Update `CHANGELOG.md`](#update-changelogmd) +4. [Remerge the `beta` branch](#remerge-the-beta-branch) +5. [Update the `beta` branch](#update-the-beta-branch) + +_NOTE: This document is for stable Rust releases, not for point releases. For +point releases, step 1. and 2. should be enough._ + +[Rust Forge]: https://forge.rust-lang.org/ + + +## Find the Clippy commit + +The first step is to tag the Clippy commit, that is included in the stable Rust +release. This commit can be found in the Rust repository. + +```bash +# Assuming the current directory corresponds to the Rust repository +$ git fetch upstream # `upstream` is the `rust-lang/rust` remote +$ git checkout 1.XX.0 # XX should be exchanged with the corresponding version +$ git submodule update +$ SHA=$(git submodule status src/tools/clippy | awk '{print $1}') +``` + + +## Tag the stable commit + +After finding the Clippy commit, it can be tagged with the release number. + +```bash +# Assuming the current directory corresponds to the Clippy repository +$ git checkout $SHA +$ git tag rust-1.XX.0 # XX should be exchanged with the corresponding version +$ git push upstream master --tags # `upstream` is the `rust-lang/rust-clippy` remote +``` + +After this, the release should be available on the Clippy [release page]. + +[release page]: https://github.com/rust-lang/rust-clippy/releases + + +## Update `CHANGELOG.md` + +For this see the document on [how to update the changelog]. + +[how to update the changelog]: https://github.com/rust-lang/rust-clippy/blob/master/doc/changelog_update.md + + +## Remerge the `beta` branch + +This step is only necessary, if since the last release something was backported +to the beta Rust release. The remerge is then necessary, to make sure that the +Clippy commit, that was used by the now stable Rust release, persists in the +tree of the Clippy repository. + +```bash +# Assuming `HEAD` is the current `master` branch of rust-lang/rust-clippy +$ git checkout -b backport_remerge +$ git merge beta +$ git diff # This diff has to be empty, otherwise something with the remerge failed +$ git push origin backport_remerge # This can be pushed to your fork +``` + +After this, open a PR to the master branch. In this PR, the commit hash of the +`HEAD` of the `beta` branch must exists. In addition to that, no files should +be changed by this PR. + + +## Update the `beta` branch + +This step must be done **after** the PR of the previous step was merged. + +First, the Clippy commit of the `beta` branch of the Rust repository has to be +determined. + +```bash +# Assuming the current directory corresponds to the Rust repository +$ git checkout beta +$ git submodule update +$ BETA_SHA=$(git submodule status src/tools/clippy | awk '{print $1}') +``` + +After finding the Clippy commit, the `beta` branch in the Clippy repository can +be updated. + +```bash +# Assuming the current directory corresponds to the Clippy repository +$ git checkout beta +$ git rebase $BETA_SHA +$ git push upstream beta [-f] # This requires a force push, if a remerge was done +``` diff --git a/setup-toolchain.sh b/setup-toolchain.sh index 469cba1874d..6038ed697f9 100755 --- a/setup-toolchain.sh +++ b/setup-toolchain.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/usr/bin/env bash # Set up the appropriate rustc toolchain set -e diff --git a/src/driver.rs b/src/driver.rs index 7865f6bb9dd..2c699998ea9 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -5,16 +5,16 @@ // FIXME: switch to something more ergonomic here, once available. // (Currently there is no way to opt into sysroot crates without `extern crate`.) #[allow(unused_extern_crates)] -extern crate rustc; -#[allow(unused_extern_crates)] extern crate rustc_driver; #[allow(unused_extern_crates)] extern crate rustc_errors; #[allow(unused_extern_crates)] extern crate rustc_interface; +#[allow(unused_extern_crates)] +extern crate rustc_middle; -use rustc::ty::TyCtxt; use rustc_interface::interface; +use rustc_middle::ty::TyCtxt; use rustc_tools_util::VersionInfo; use lazy_static::lazy_static; diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 0cf094b8ed3..935ea180ebe 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1,12 +1,15 @@ //! This file is managed by `cargo dev update_lints`. Do not edit. +use lazy_static::lazy_static; + pub mod lint; pub use lint::Level; pub use lint::Lint; pub use lint::LINT_LEVELS; +lazy_static! { // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 362] = [ +pub static ref ALL_LINTS: Vec<Lint> = vec![ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -247,7 +250,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "cognitive_complexity", - group: "complexity", + group: "nursery", desc: "functions that should be split up into multiple functions", deprecation: None, module: "cognitive_complexity", @@ -624,6 +627,13 @@ pub const ALL_LINTS: [Lint; 362] = [ module: "misc", }, Lint { + name: "fn_address_comparisons", + group: "correctness", + desc: "comparison with an address of a function item", + deprecation: None, + module: "unnamed_address", + }, + Lint { name: "fn_params_excessive_bools", group: "pedantic", desc: "using too many bools in function parameters", @@ -737,7 +747,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "implicit_hasher", - group: "style", + group: "pedantic", desc: "missing generalization over different hashers", deprecation: None, module: "types", @@ -779,7 +789,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "inefficient_to_string", - group: "perf", + group: "pedantic", desc: "using `to_string` on `&&T` where `T: ToString`", deprecation: None, module: "methods", @@ -989,7 +999,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "let_unit_value", - group: "style", + group: "pedantic", desc: "creating a `let` binding to a value of unit type, which usually can\'t be used afterwards", deprecation: None, module: "types", @@ -1438,7 +1448,7 @@ pub const ALL_LINTS: [Lint; 362] = [ Lint { name: "new_ret_no_self", group: "style", - desc: "not returning `Self` in a `new` method", + desc: "not returning type containing `Self` in a `new` method", deprecation: None, module: "methods", }, @@ -1556,7 +1566,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "option_option", - group: "complexity", + group: "pedantic", desc: "usage of `Option<Option<T>>`", deprecation: None, module: "types", @@ -1716,6 +1726,13 @@ pub const ALL_LINTS: [Lint; 362] = [ module: "ranges", }, Lint { + name: "redundant_allocation", + group: "perf", + desc: "redundant allocation", + deprecation: None, + module: "types", + }, + Lint { name: "redundant_clone", group: "perf", desc: "`clone()` of an owned value that is going to be dropped immediately", @@ -1793,13 +1810,6 @@ pub const ALL_LINTS: [Lint; 362] = [ module: "regex", }, Lint { - name: "replace_consts", - group: "pedantic", - desc: "Lint usages of standard library `const`s that could be replaced by `const fn`s", - deprecation: None, - module: "replace_consts", - }, - Lint { name: "rest_pat_in_fully_bound_structs", group: "restriction", desc: "a match on a struct that binds all fields but still uses the wildcard pattern", @@ -1814,6 +1824,13 @@ pub const ALL_LINTS: [Lint; 362] = [ module: "methods", }, Lint { + name: "result_map_or_into_option", + group: "style", + desc: "using `Result.map_or(None, Some)`, which is more succinctly expressed as `ok()`", + deprecation: None, + module: "methods", + }, + Lint { name: "result_map_unit_fn", group: "complexity", desc: "using `result.map(f)`, where `f` is a function or closure that returns `()`", @@ -2151,7 +2168,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "trivially_copy_pass_by_ref", - group: "perf", + group: "pedantic", desc: "functions taking small copyable arguments by reference", deprecation: None, module: "trivially_copy_pass_by_ref", @@ -2284,7 +2301,7 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "unreadable_literal", - group: "style", + group: "pedantic", desc: "long integer literal without underscores", deprecation: None, module: "literal_representation", @@ -2410,12 +2427,19 @@ pub const ALL_LINTS: [Lint; 362] = [ }, Lint { name: "verbose_file_reads", - group: "complexity", + group: "restriction", desc: "use of `File::read_to_end` or `File::read_to_string`", deprecation: None, module: "verbose_file_reads", }, Lint { + name: "vtable_address_comparisons", + group: "correctness", + desc: "comparison with an address of a trait vtable", + deprecation: None, + module: "unnamed_address", + }, + Lint { name: "while_immutable_condition", group: "correctness", desc: "variables used within while expression are not mutated in the body", @@ -2509,7 +2533,7 @@ pub const ALL_LINTS: [Lint; 362] = [ Lint { name: "zero_divided_by_zero", group: "complexity", - desc: "usage of `0.0 / 0.0` to obtain NaN instead of `std::f32::NAN` or `std::f64::NAN`", + desc: "usage of `0.0 / 0.0` to obtain NaN instead of `f32::NAN` or `f64::NAN`", deprecation: None, module: "zero_div_zero", }, @@ -2543,3 +2567,4 @@ pub const ALL_LINTS: [Lint; 362] = [ }, ]; // end lint list, do not remove this comment, it’s used in `update_lints` +} diff --git a/tests/integration.rs b/tests/integration.rs index 4f373e034bc..a78273ce0da 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -64,6 +64,9 @@ fn integration_test() { } else if stderr.contains("query stack during panic") { panic!("query stack during panic in the output"); } else if stderr.contains("E0463") { + // Encountering E0463 (can't find crate for `x`) did _not_ cause the build to fail in the + // past. Even though it should have. That's why we explicitly panic here. + // See PR #3552 and issue #3523 for more background. panic!("error: E0463"); } else if stderr.contains("E0514") { panic!("incompatible crate versions"); diff --git a/tests/matches.rs b/tests/matches.rs deleted file mode 100644 index 6691c074caf..00000000000 --- a/tests/matches.rs +++ /dev/null @@ -1,42 +0,0 @@ -#![feature(rustc_private)] - -extern crate rustc_span; -use std::collections::Bound; - -#[test] -fn test_overlapping() { - use clippy_lints::matches::overlapping; - use rustc_span::source_map::DUMMY_SP; - - let sp = |s, e| clippy_lints::matches::SpannedRange { - span: DUMMY_SP, - node: (s, e), - }; - - assert_eq!(None, overlapping::<u8>(&[])); - assert_eq!(None, overlapping(&[sp(1, Bound::Included(4))])); - assert_eq!( - None, - overlapping(&[sp(1, Bound::Included(4)), sp(5, Bound::Included(6))]) - ); - assert_eq!( - None, - overlapping(&[ - sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(10, Bound::Included(11)) - ],) - ); - assert_eq!( - Some((&sp(1, Bound::Included(4)), &sp(3, Bound::Included(6)))), - overlapping(&[sp(1, Bound::Included(4)), sp(3, Bound::Included(6))]) - ); - assert_eq!( - Some((&sp(5, Bound::Included(6)), &sp(6, Bound::Included(11)))), - overlapping(&[ - sp(1, Bound::Included(4)), - sp(5, Bound::Included(6)), - sp(6, Bound::Included(11)) - ],) - ); -} diff --git a/tests/ui-toml/toml_trivially_copy/test.rs b/tests/ui-toml/toml_trivially_copy/test.rs index 6dcbae04075..19019a25416 100644 --- a/tests/ui-toml/toml_trivially_copy/test.rs +++ b/tests/ui-toml/toml_trivially_copy/test.rs @@ -1,6 +1,7 @@ // normalize-stderr-test "\(\d+ byte\)" -> "(N byte)" // normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)" +#![deny(clippy::trivially_copy_pass_by_ref)] #![allow(clippy::many_single_char_names)] #[derive(Copy, Clone)] diff --git a/tests/ui-toml/toml_trivially_copy/test.stderr b/tests/ui-toml/toml_trivially_copy/test.stderr index d2b55eff16d..912761a8f00 100644 --- a/tests/ui-toml/toml_trivially_copy/test.stderr +++ b/tests/ui-toml/toml_trivially_copy/test.stderr @@ -1,13 +1,17 @@ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/test.rs:14:11 + --> $DIR/test.rs:15:11 | LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `u16` | - = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/test.rs:4:9 + | +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) - --> $DIR/test.rs:14:20 + --> $DIR/test.rs:15:20 | LL | fn bad(x: &u16, y: &Foo) {} | ^^^^ help: consider passing by value instead: `Foo` diff --git a/tests/ui/absurd-extreme-comparisons.rs b/tests/ui/absurd-extreme-comparisons.rs index ae0727fe2ba..d205b383d1f 100644 --- a/tests/ui/absurd-extreme-comparisons.rs +++ b/tests/ui/absurd-extreme-comparisons.rs @@ -16,17 +16,17 @@ fn main() { u < Z; Z >= u; Z > u; - u > std::u32::MAX; - u >= std::u32::MAX; - std::u32::MAX < u; - std::u32::MAX <= u; + u > u32::MAX; + u >= u32::MAX; + u32::MAX < u; + u32::MAX <= u; 1-1 > u; u >= !0; u <= 12 - 2*6; let i: i8 = 0; i < -127 - 1; - std::i8::MAX >= i; - 3-7 < std::i32::MIN; + i8::MAX >= i; + 3-7 < i32::MIN; let b = false; b >= true; false > b; @@ -52,10 +52,10 @@ impl PartialOrd<u32> for U { } pub fn foo(val: U) -> bool { - val > std::u32::MAX + val > u32::MAX } pub fn bar(len: u64) -> bool { // This is OK as we are casting from target sized to fixed size - len >= std::usize::MAX as u64 + len >= usize::MAX as u64 } diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index 4ef364148cd..6de554378aa 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -42,34 +42,34 @@ LL | Z > u; error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:19:5 | -LL | u > std::u32::MAX; - | ^^^^^^^^^^^^^^^^^ +LL | u > u32::MAX; + | ^^^^^^^^^^^^ | - = help: because `std::u32::MAX` is the maximum value for this type, this comparison is always false + = help: because `u32::MAX` is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:20:5 | -LL | u >= std::u32::MAX; - | ^^^^^^^^^^^^^^^^^^ +LL | u >= u32::MAX; + | ^^^^^^^^^^^^^ | - = help: because `std::u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u == std::u32::MAX` instead + = help: because `u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u == u32::MAX` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:21:5 | -LL | std::u32::MAX < u; - | ^^^^^^^^^^^^^^^^^ +LL | u32::MAX < u; + | ^^^^^^^^^^^^ | - = help: because `std::u32::MAX` is the maximum value for this type, this comparison is always false + = help: because `u32::MAX` is the maximum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:22:5 | -LL | std::u32::MAX <= u; - | ^^^^^^^^^^^^^^^^^^ +LL | u32::MAX <= u; + | ^^^^^^^^^^^^^ | - = help: because `std::u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `std::u32::MAX == u` instead + = help: because `u32::MAX` is the maximum value for this type, the case where the two sides are not equal never occurs, consider using `u32::MAX == u` instead error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:23:5 @@ -106,18 +106,18 @@ LL | i < -127 - 1; error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:28:5 | -LL | std::i8::MAX >= i; - | ^^^^^^^^^^^^^^^^^ +LL | i8::MAX >= i; + | ^^^^^^^^^^^^ | - = help: because `std::i8::MAX` is the maximum value for this type, this comparison is always true + = help: because `i8::MAX` is the maximum value for this type, this comparison is always true error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:29:5 | -LL | 3-7 < std::i32::MIN; - | ^^^^^^^^^^^^^^^^^^^ +LL | 3-7 < i32::MIN; + | ^^^^^^^^^^^^^^ | - = help: because `std::i32::MIN` is the minimum value for this type, this comparison is always false + = help: because `i32::MIN` is the minimum value for this type, this comparison is always false error: this comparison involving the minimum or maximum element for this type contains a case that is always true or always false --> $DIR/absurd-extreme-comparisons.rs:31:5 diff --git a/tests/ui/approx_const.rs b/tests/ui/approx_const.rs index e1c150fdefd..fb57a0becbb 100644 --- a/tests/ui/approx_const.rs +++ b/tests/ui/approx_const.rs @@ -1,5 +1,5 @@ #[warn(clippy::approx_constant)] -#[allow(unused, clippy::shadow_unrelated, clippy::similar_names, clippy::unreadable_literal)] +#[allow(unused, clippy::shadow_unrelated, clippy::similar_names)] fn main() { let my_e = 2.7182; let almost_e = 2.718; diff --git a/tests/ui/auxiliary/proc_macro_derive.rs b/tests/ui/auxiliary/proc_macro_derive.rs index f6d101a0911..21bb5b01e02 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; + extern crate rustc_middle; }; output } diff --git a/tests/ui/bool_comparison.fixed b/tests/ui/bool_comparison.fixed index 0bd73ec2c10..91211764759 100644 --- a/tests/ui/bool_comparison.fixed +++ b/tests/ui/bool_comparison.fixed @@ -111,3 +111,19 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +#[allow(dead_code)] +fn issue4983() { + let a = true; + let b = false; + + if a != b {}; + if a != b {}; + if a == b {}; + if !a == !b {}; + + if b != a {}; + if b != a {}; + if b == a {}; + if !b == !a {}; +} diff --git a/tests/ui/bool_comparison.rs b/tests/ui/bool_comparison.rs index 74f504edfd0..01ee35859f0 100644 --- a/tests/ui/bool_comparison.rs +++ b/tests/ui/bool_comparison.rs @@ -111,3 +111,19 @@ fn issue3703() { if Foo < false {} if false < Foo {} } + +#[allow(dead_code)] +fn issue4983() { + let a = true; + let b = false; + + if a == !b {}; + if !a == b {}; + if a == b {}; + if !a == !b {}; + + if b == !a {}; + if !b == a {}; + if b == a {}; + if !b == !a {}; +} diff --git a/tests/ui/bool_comparison.stderr b/tests/ui/bool_comparison.stderr index 2aa070a00f3..eeb1f20ee89 100644 --- a/tests/ui/bool_comparison.stderr +++ b/tests/ui/bool_comparison.stderr @@ -84,5 +84,29 @@ error: order comparisons between booleans can be simplified LL | if x > y { | ^^^^^ help: try simplifying it as shown: `x & !y` -error: aborting due to 14 previous errors +error: This comparison might be written more concisely + --> $DIR/bool_comparison.rs:120:8 + | +LL | if a == !b {}; + | ^^^^^^^ help: try simplifying it as shown: `a != b` + +error: This comparison might be written more concisely + --> $DIR/bool_comparison.rs:121:8 + | +LL | if !a == b {}; + | ^^^^^^^ help: try simplifying it as shown: `a != b` + +error: This comparison might be written more concisely + --> $DIR/bool_comparison.rs:125:8 + | +LL | if b == !a {}; + | ^^^^^^^ help: try simplifying it as shown: `b != a` + +error: This comparison might be written more concisely + --> $DIR/bool_comparison.rs:126:8 + | +LL | if !b == a {}; + | ^^^^^^^ help: try simplifying it as shown: `b != a` + +error: aborting due to 18 previous errors diff --git a/tests/ui/clone_on_copy_mut.rs b/tests/ui/clone_on_copy_mut.rs index 3cbbcb7c083..5bfa256623b 100644 --- a/tests/ui/clone_on_copy_mut.rs +++ b/tests/ui/clone_on_copy_mut.rs @@ -5,7 +5,6 @@ pub fn dec_read_dec(i: &mut i32) -> i32 { ret } -#[allow(clippy::trivially_copy_pass_by_ref)] pub fn minus_1(i: &i32) -> i32 { dec_read_dec(&mut i.clone()) } diff --git a/tests/ui/cmp_nan.rs b/tests/ui/cmp_nan.rs index f89ccddbfa4..64ca52b010a 100644 --- a/tests/ui/cmp_nan.rs +++ b/tests/ui/cmp_nan.rs @@ -1,16 +1,16 @@ -const NAN_F32: f32 = std::f32::NAN; -const NAN_F64: f64 = std::f64::NAN; +const NAN_F32: f32 = f32::NAN; +const NAN_F64: f64 = f64::NAN; #[warn(clippy::cmp_nan)] #[allow(clippy::float_cmp, clippy::no_effect, clippy::unnecessary_operation)] fn main() { let x = 5f32; - x == std::f32::NAN; - x != std::f32::NAN; - x < std::f32::NAN; - x > std::f32::NAN; - x <= std::f32::NAN; - x >= std::f32::NAN; + x == f32::NAN; + x != f32::NAN; + x < f32::NAN; + x > f32::NAN; + x <= f32::NAN; + x >= f32::NAN; x == NAN_F32; x != NAN_F32; x < NAN_F32; @@ -19,12 +19,12 @@ fn main() { x >= NAN_F32; let y = 0f64; - y == std::f64::NAN; - y != std::f64::NAN; - y < std::f64::NAN; - y > std::f64::NAN; - y <= std::f64::NAN; - y >= std::f64::NAN; + y == f64::NAN; + y != f64::NAN; + y < f64::NAN; + y > f64::NAN; + y <= f64::NAN; + y >= f64::NAN; y == NAN_F64; y != NAN_F64; y < NAN_F64; diff --git a/tests/ui/cmp_nan.stderr b/tests/ui/cmp_nan.stderr index 7aceeeaf78f..867516661a5 100644 --- a/tests/ui/cmp_nan.stderr +++ b/tests/ui/cmp_nan.stderr @@ -1,144 +1,144 @@ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:8:5 | -LL | x == std::f32::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | x == f32::NAN; + | ^^^^^^^^^^^^^ | = note: `-D clippy::cmp-nan` implied by `-D warnings` -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:9:5 | -LL | x != std::f32::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | x != f32::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:10:5 | -LL | x < std::f32::NAN; - | ^^^^^^^^^^^^^^^^^ +LL | x < f32::NAN; + | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:11:5 | -LL | x > std::f32::NAN; - | ^^^^^^^^^^^^^^^^^ +LL | x > f32::NAN; + | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:12:5 | -LL | x <= std::f32::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | x <= f32::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:13:5 | -LL | x >= std::f32::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | x >= f32::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:14:5 | LL | x == NAN_F32; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:15:5 | LL | x != NAN_F32; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:16:5 | LL | x < NAN_F32; | ^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:17:5 | LL | x > NAN_F32; | ^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:18:5 | LL | x <= NAN_F32; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:19:5 | LL | x >= NAN_F32; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:22:5 | -LL | y == std::f64::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | y == f64::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:23:5 | -LL | y != std::f64::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | y != f64::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:24:5 | -LL | y < std::f64::NAN; - | ^^^^^^^^^^^^^^^^^ +LL | y < f64::NAN; + | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:25:5 | -LL | y > std::f64::NAN; - | ^^^^^^^^^^^^^^^^^ +LL | y > f64::NAN; + | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:26:5 | -LL | y <= std::f64::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | y <= f64::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:27:5 | -LL | y >= std::f64::NAN; - | ^^^^^^^^^^^^^^^^^^ +LL | y >= f64::NAN; + | ^^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:28:5 | LL | y == NAN_F64; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:29:5 | LL | y != NAN_F64; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:30:5 | LL | y < NAN_F64; | ^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:31:5 | LL | y > NAN_F64; | ^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:32:5 | LL | y <= NAN_F64; | ^^^^^^^^^^^^ -error: doomed comparison with `NAN`, use `std::{f32,f64}::is_nan()` instead +error: doomed comparison with `NAN`, use `{f32,f64}::is_nan()` instead --> $DIR/cmp_nan.rs:33:5 | LL | y >= NAN_F64; diff --git a/tests/ui/collapsible_else_if.fixed b/tests/ui/collapsible_else_if.fixed index c4149ad19c1..ce2a1c28c8a 100644 --- a/tests/ui/collapsible_else_if.fixed +++ b/tests/ui/collapsible_else_if.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cognitive_complexity, clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_else_if.rs b/tests/ui/collapsible_else_if.rs index 79a27aafc4d..99c40b8d38e 100644 --- a/tests/ui/collapsible_else_if.rs +++ b/tests/ui/collapsible_else_if.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cognitive_complexity, clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_if.fixed b/tests/ui/collapsible_if.fixed index 076771f5c57..561283fc8e7 100644 --- a/tests/ui/collapsible_if.fixed +++ b/tests/ui/collapsible_if.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cognitive_complexity, clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/collapsible_if.rs b/tests/ui/collapsible_if.rs index 503cb35f858..dc9d9b451c0 100644 --- a/tests/ui/collapsible_if.rs +++ b/tests/ui/collapsible_if.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(clippy::cognitive_complexity, clippy::assertions_on_constants)] +#![allow(clippy::assertions_on_constants)] #[rustfmt::skip] #[warn(clippy::collapsible_if)] diff --git a/tests/ui/crashes/ice-3717.rs b/tests/ui/crashes/ice-3717.rs index 21c48f4749c..f50714643fd 100644 --- a/tests/ui/crashes/ice-3717.rs +++ b/tests/ui/crashes/ice-3717.rs @@ -1,3 +1,5 @@ +#![deny(clippy::implicit_hasher)] + use std::collections::HashSet; fn main() {} diff --git a/tests/ui/crashes/ice-3717.stderr b/tests/ui/crashes/ice-3717.stderr index 08c53c399c2..296c95abb96 100644 --- a/tests/ui/crashes/ice-3717.stderr +++ b/tests/ui/crashes/ice-3717.stderr @@ -1,10 +1,14 @@ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/ice-3717.rs:5:21 + --> $DIR/ice-3717.rs:7:21 | LL | pub fn ice_3717(_: &HashSet<usize>) { | ^^^^^^^^^^^^^^ | - = note: `-D clippy::implicit-hasher` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/ice-3717.rs:1:9 + | +LL | #![deny(clippy::implicit_hasher)] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | LL | pub fn ice_3717<S: ::std::hash::BuildHasher + Default>(_: &HashSet<usize, S>) { diff --git a/tests/ui/crashes/mut_mut_macro.rs b/tests/ui/crashes/mut_mut_macro.rs index 14219f574c5..d8fbaa54146 100644 --- a/tests/ui/crashes/mut_mut_macro.rs +++ b/tests/ui/crashes/mut_mut_macro.rs @@ -16,7 +16,7 @@ const BAA: *const i32 = 0 as *const i32; static mut BAR: *const i32 = BAA; static mut FOO: *const i32 = 0 as *const i32; -static mut BUH: bool = 42.0 < std::f32::NAN; +static mut BUH: bool = 42.0 < f32::NAN; #[allow(unused_variables, unused_mut)] fn main() { @@ -32,5 +32,5 @@ fn main() { assert_eq!(*MUT_COUNT, 1); */ // FIXME: don't lint in array length, requires `check_body` - //let _ = [""; (42.0 < std::f32::NAN) as usize]; + //let _ = [""; (42.0 < f32::NAN) as usize]; } diff --git a/tests/ui/debug_assert_with_mut_call.rs b/tests/ui/debug_assert_with_mut_call.rs index 3db7e0164fa..477a47118d4 100644 --- a/tests/ui/debug_assert_with_mut_call.rs +++ b/tests/ui/debug_assert_with_mut_call.rs @@ -2,7 +2,7 @@ #![feature(custom_inner_attributes)] #![rustfmt::skip] #![warn(clippy::debug_assert_with_mut_call)] -#![allow(clippy::trivially_copy_pass_by_ref, clippy::cognitive_complexity, clippy::redundant_closure_call)] +#![allow(clippy::redundant_closure_call)] struct S; diff --git a/tests/ui/default_lint.rs b/tests/ui/default_lint.rs index 0c6f29a43c6..053faae02ce 100644 --- a/tests/ui/default_lint.rs +++ b/tests/ui/default_lint.rs @@ -2,7 +2,7 @@ #![feature(rustc_private)] #[macro_use] -extern crate rustc; +extern crate rustc_middle; #[macro_use] extern crate rustc_session; extern crate rustc_lint; diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index c44f3c62a98..484aa72d59a 100644 --- a/tests/ui/doc_unsafe.rs +++ b/tests/ui/doc_unsafe.rs @@ -88,7 +88,6 @@ very_unsafe!(); // we don't lint code from external macros undocd_unsafe!(); -#[allow(clippy::let_unit_value)] fn main() { unsafe { you_dont_see_me(); diff --git a/tests/ui/enum_clike_unportable_variant.rs b/tests/ui/enum_clike_unportable_variant.rs index 7379ad99f4a..7d6842f5b54 100644 --- a/tests/ui/enum_clike_unportable_variant.rs +++ b/tests/ui/enum_clike_unportable_variant.rs @@ -24,8 +24,8 @@ enum NonPortableSigned { Y = 0x7FFF_FFFF, Z = 0xFFFF_FFFF, A = 0x1_0000_0000, - B = std::i32::MIN as isize, - C = (std::i32::MIN as isize) - 1, + B = i32::MIN as isize, + C = (i32::MIN as isize) - 1, } enum NonPortableSignedNoHint { diff --git a/tests/ui/enum_clike_unportable_variant.stderr b/tests/ui/enum_clike_unportable_variant.stderr index bd729683e4c..71f3f5e083e 100644 --- a/tests/ui/enum_clike_unportable_variant.stderr +++ b/tests/ui/enum_clike_unportable_variant.stderr @@ -33,8 +33,8 @@ LL | A = 0x1_0000_0000, error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:28:5 | -LL | C = (std::i32::MIN as isize) - 1, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | C = (i32::MIN as isize) - 1, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: Clike enum variant discriminant is not portable to 32-bit targets --> $DIR/enum_clike_unportable_variant.rs:34:5 diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index 5d62a6d9b01..1b34c2f74eb 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -6,8 +6,7 @@ clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, - clippy::option_map_unit_fn, - clippy::trivially_copy_pass_by_ref + clippy::option_map_unit_fn )] #![warn( clippy::redundant_closure, diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index a9c4b209960..4f050bd8479 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -6,8 +6,7 @@ clippy::redundant_closure_call, clippy::many_single_char_names, clippy::needless_pass_by_value, - clippy::option_map_unit_fn, - clippy::trivially_copy_pass_by_ref + clippy::option_map_unit_fn )] #![warn( clippy::redundant_closure, diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index d19d21eec0d..c4713ca8083 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure found - --> $DIR/eta.rs:21:27 + --> $DIR/eta.rs:20:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` @@ -7,13 +7,13 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:22:10 + --> $DIR/eta.rs:21:10 | LL | meta(|a| foo(a)); | ^^^^^^^^^^ help: remove closure as shown: `foo` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/eta.rs:25:21 + --> $DIR/eta.rs:24:21 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^ help: change this to: `&2` @@ -21,13 +21,13 @@ LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted = note: `-D clippy::needless-borrow` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:32:27 + --> $DIR/eta.rs:31:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `generic` error: redundant closure found - --> $DIR/eta.rs:75:51 + --> $DIR/eta.rs:74:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: remove closure as shown: `TestStruct::foo` @@ -35,43 +35,43 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure found - --> $DIR/eta.rs:77:51 + --> $DIR/eta.rs:76:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `TestTrait::trait_foo` error: redundant closure found - --> $DIR/eta.rs:80:42 + --> $DIR/eta.rs:79:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: remove closure as shown: `std::vec::Vec::clear` error: redundant closure found - --> $DIR/eta.rs:85:29 + --> $DIR/eta.rs:84:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: remove closure as shown: `std::string::ToString::to_string` error: redundant closure found - --> $DIR/eta.rs:87:27 + --> $DIR/eta.rs:86:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_uppercase` error: redundant closure found - --> $DIR/eta.rs:90:65 + --> $DIR/eta.rs:89:65 | LL | let e: std::vec::Vec<char> = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove closure as shown: `char::to_ascii_uppercase` error: redundant closure found - --> $DIR/eta.rs:173:27 + --> $DIR/eta.rs:172:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `foo_ptr` error: redundant closure found - --> $DIR/eta.rs:178:27 + --> $DIR/eta.rs:177:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: remove closure as shown: `closure` diff --git a/tests/ui/extra_unused_lifetimes.rs b/tests/ui/extra_unused_lifetimes.rs index ba95fd63bf9..ddbf4e98c51 100644 --- a/tests/ui/extra_unused_lifetimes.rs +++ b/tests/ui/extra_unused_lifetimes.rs @@ -1,10 +1,4 @@ -#![allow( - unused, - dead_code, - clippy::needless_lifetimes, - clippy::needless_pass_by_value, - clippy::trivially_copy_pass_by_ref -)] +#![allow(unused, dead_code, clippy::needless_lifetimes, clippy::needless_pass_by_value)] #![warn(clippy::extra_unused_lifetimes)] fn empty() {} diff --git a/tests/ui/extra_unused_lifetimes.stderr b/tests/ui/extra_unused_lifetimes.stderr index ebdb8e74952..16bbb1c037d 100644 --- a/tests/ui/extra_unused_lifetimes.stderr +++ b/tests/ui/extra_unused_lifetimes.stderr @@ -1,5 +1,5 @@ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:14:14 + --> $DIR/extra_unused_lifetimes.rs:8:14 | LL | fn unused_lt<'a>(x: u8) {} | ^^ @@ -7,19 +7,19 @@ LL | fn unused_lt<'a>(x: u8) {} = note: `-D clippy::extra-unused-lifetimes` implied by `-D warnings` error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:16:25 + --> $DIR/extra_unused_lifetimes.rs:10:25 | LL | fn unused_lt_transitive<'a, 'b: 'a>(x: &'b u8) { | ^^ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:41:10 + --> $DIR/extra_unused_lifetimes.rs:35:10 | LL | fn x<'a>(&self) {} | ^^ error: this lifetime isn't used in the function definition - --> $DIR/extra_unused_lifetimes.rs:67:22 + --> $DIR/extra_unused_lifetimes.rs:61:22 | LL | fn unused_lt<'a>(x: u8) {} | ^^ diff --git a/tests/ui/float_arithmetic.rs b/tests/ui/float_arithmetic.rs index 5ad320c6209..60fa7569eb9 100644 --- a/tests/ui/float_arithmetic.rs +++ b/tests/ui/float_arithmetic.rs @@ -5,8 +5,7 @@ clippy::shadow_unrelated, clippy::no_effect, clippy::unnecessary_operation, - clippy::op_ref, - clippy::trivially_copy_pass_by_ref + clippy::op_ref )] #[rustfmt::skip] diff --git a/tests/ui/float_arithmetic.stderr b/tests/ui/float_arithmetic.stderr index 809392529fd..1ceffb35bee 100644 --- a/tests/ui/float_arithmetic.stderr +++ b/tests/ui/float_arithmetic.stderr @@ -1,5 +1,5 @@ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:16:5 + --> $DIR/float_arithmetic.rs:15:5 | LL | f * 2.0; | ^^^^^^^ @@ -7,97 +7,97 @@ LL | f * 2.0; = note: `-D clippy::float-arithmetic` implied by `-D warnings` error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:18:5 + --> $DIR/float_arithmetic.rs:17:5 | LL | 1.0 + f; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:19:5 + --> $DIR/float_arithmetic.rs:18:5 | LL | f * 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:20:5 + --> $DIR/float_arithmetic.rs:19:5 | LL | f / 2.0; | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:21:5 + --> $DIR/float_arithmetic.rs:20:5 | LL | f - 2.0 * 4.2; | ^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:22:5 + --> $DIR/float_arithmetic.rs:21:5 | LL | -f; | ^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:24:5 + --> $DIR/float_arithmetic.rs:23:5 | LL | f += 1.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:25:5 + --> $DIR/float_arithmetic.rs:24:5 | LL | f -= 1.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:26:5 + --> $DIR/float_arithmetic.rs:25:5 | LL | f *= 2.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:27:5 + --> $DIR/float_arithmetic.rs:26:5 | LL | f /= 2.0; | ^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:33:5 + --> $DIR/float_arithmetic.rs:32:5 | LL | 3.1_f32 + &1.2_f32; | ^^^^^^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:34:5 + --> $DIR/float_arithmetic.rs:33:5 | LL | &3.4_f32 + 1.5_f32; | ^^^^^^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:35:5 + --> $DIR/float_arithmetic.rs:34:5 | LL | &3.5_f32 + &1.3_f32; | ^^^^^^^^^^^^^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:40:5 + --> $DIR/float_arithmetic.rs:39:5 | LL | a + f | ^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:44:5 + --> $DIR/float_arithmetic.rs:43:5 | LL | f1 + f2 | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:48:5 + --> $DIR/float_arithmetic.rs:47:5 | LL | f1 + f2 | ^^^^^^^ error: floating-point arithmetic detected - --> $DIR/float_arithmetic.rs:52:5 + --> $DIR/float_arithmetic.rs:51:5 | LL | (&f1 + &f2) | ^^^^^^^^^^^ diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 207c1bcbbc6..9fa0e5f5c07 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -1,5 +1,11 @@ #![warn(clippy::float_cmp)] -#![allow(unused, clippy::no_effect, clippy::unnecessary_operation, clippy::cast_lossless)] +#![allow( + unused, + clippy::no_effect, + clippy::unnecessary_operation, + clippy::cast_lossless, + clippy::many_single_char_names +)] use std::ops::Add; @@ -45,8 +51,8 @@ impl PartialEq for X { fn main() { ZERO == 0f32; //no error, comparison with zero is ok - 1.0f32 != ::std::f32::INFINITY; // also comparison with infinity - 1.0f32 != ::std::f32::NEG_INFINITY; // and negative infinity + 1.0f32 != f32::INFINITY; // also comparison with infinity + 1.0f32 != f32::NEG_INFINITY; // and negative infinity ZERO == 0.0; //no error, comparison with zero is ok ZERO + ZERO != 1.0; //no error, comparison with zero is ok @@ -77,6 +83,21 @@ fn main() { assert_eq!(a, b); // no errors + const ZERO_ARRAY: [f32; 2] = [0.0, 0.0]; + const NON_ZERO_ARRAY: [f32; 2] = [0.0, 0.1]; + + let i = 0; + let j = 1; + + ZERO_ARRAY[i] == NON_ZERO_ARRAY[j]; // ok, because lhs is zero regardless of i + NON_ZERO_ARRAY[i] == NON_ZERO_ARRAY[j]; + + let a1: [f32; 1] = [0.0]; + let a2: [f32; 1] = [1.1]; + + a1 == a2; + a1[0] == a2[0]; + // no errors - comparing signums is ok let x32 = 3.21f32; 1.23f32.signum() == x32.signum(); diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index 68f5b23bdc7..2d454e8e70d 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,39 +1,51 @@ error: strict comparison of `f32` or `f64` - --> $DIR/float_cmp.rs:59:5 + --> $DIR/float_cmp.rs:65:5 | LL | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE as f64 - 2.0).abs() > error` | = note: `-D clippy::float-cmp` implied by `-D warnings` -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp.rs:59:5 - | -LL | ONE as f64 != 2.0; - | ^^^^^^^^^^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` - --> $DIR/float_cmp.rs:64:5 + --> $DIR/float_cmp.rs:70:5 | LL | x == 1.0; | ^^^^^^^^ help: consider comparing them within some error: `(x - 1.0).abs() < error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp.rs:64:5 - | -LL | x == 1.0; - | ^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` - --> $DIR/float_cmp.rs:67:5 + --> $DIR/float_cmp.rs:73:5 | LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(twice(x) - twice(ONE as f64)).abs() > error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp.rs:67:5 + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` + +error: strict comparison of `f32` or `f64` + --> $DIR/float_cmp.rs:93:5 | -LL | twice(x) != twice(ONE as f64); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | NON_ZERO_ARRAY[i] == NON_ZERO_ARRAY[j]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(NON_ZERO_ARRAY[i] - NON_ZERO_ARRAY[j]).abs() < error` + | + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` + +error: strict comparison of `f32` or `f64` arrays + --> $DIR/float_cmp.rs:98:5 + | +LL | a1 == a2; + | ^^^^^^^^ + | + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` + +error: strict comparison of `f32` or `f64` + --> $DIR/float_cmp.rs:99:5 + | +LL | a1[0] == a2[0]; + | ^^^^^^^^^^^^^^ help: consider comparing them within some error: `(a1[0] - a2[0]).abs() < error` + | + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` -error: aborting due to 3 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/float_cmp_const.rs b/tests/ui/float_cmp_const.rs index 8f4ad15720b..dfc025558a2 100644 --- a/tests/ui/float_cmp_const.rs +++ b/tests/ui/float_cmp_const.rs @@ -37,8 +37,8 @@ fn main() { // no errors, zero and infinity values ONE != 0f32; TWO == 0f32; - ONE != ::std::f32::INFINITY; - ONE == ::std::f32::NEG_INFINITY; + ONE != f32::INFINITY; + ONE == f32::NEG_INFINITY; // no errors, but will warn clippy::float_cmp if '#![allow(float_cmp)]' above is removed let w = 1.1; @@ -46,4 +46,17 @@ fn main() { v != w; v == 1.0; v != 1.0; + + const ZERO_ARRAY: [f32; 3] = [0.0, 0.0, 0.0]; + const ZERO_INF_ARRAY: [f32; 3] = [0.0, ::std::f32::INFINITY, ::std::f32::NEG_INFINITY]; + const NON_ZERO_ARRAY: [f32; 3] = [0.0, 0.1, 0.2]; + const NON_ZERO_ARRAY2: [f32; 3] = [0.2, 0.1, 0.0]; + + // no errors, zero and infinity values + NON_ZERO_ARRAY[0] == NON_ZERO_ARRAY2[1]; // lhs is 0.0 + ZERO_ARRAY == NON_ZERO_ARRAY; // lhs is all zeros + ZERO_INF_ARRAY == NON_ZERO_ARRAY; // lhs is all zeros or infinities + + // has errors + NON_ZERO_ARRAY == NON_ZERO_ARRAY2; } diff --git a/tests/ui/float_cmp_const.stderr b/tests/ui/float_cmp_const.stderr index c13c555cd11..19dc4a284b7 100644 --- a/tests/ui/float_cmp_const.stderr +++ b/tests/ui/float_cmp_const.stderr @@ -5,11 +5,7 @@ LL | 1f32 == ONE; | ^^^^^^^^^^^ help: consider comparing them within some error: `(1f32 - ONE).abs() < error` | = note: `-D clippy::float-cmp-const` implied by `-D warnings` -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:20:5 - | -LL | 1f32 == ONE; - | ^^^^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` constant --> $DIR/float_cmp_const.rs:21:5 @@ -17,11 +13,7 @@ error: strict comparison of `f32` or `f64` constant LL | TWO == ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() < error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:21:5 - | -LL | TWO == ONE; - | ^^^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` constant --> $DIR/float_cmp_const.rs:22:5 @@ -29,11 +21,7 @@ error: strict comparison of `f32` or `f64` constant LL | TWO != ONE; | ^^^^^^^^^^ help: consider comparing them within some error: `(TWO - ONE).abs() > error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:22:5 - | -LL | TWO != ONE; - | ^^^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` constant --> $DIR/float_cmp_const.rs:23:5 @@ -41,11 +29,7 @@ error: strict comparison of `f32` or `f64` constant LL | ONE + ONE == TWO; | ^^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(ONE + ONE - TWO).abs() < error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:23:5 - | -LL | ONE + ONE == TWO; - | ^^^^^^^^^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` constant --> $DIR/float_cmp_const.rs:25:5 @@ -53,11 +37,7 @@ error: strict comparison of `f32` or `f64` constant LL | x as f32 == ONE; | ^^^^^^^^^^^^^^^ help: consider comparing them within some error: `(x as f32 - ONE).abs() < error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:25:5 - | -LL | x as f32 == ONE; - | ^^^^^^^^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` constant --> $DIR/float_cmp_const.rs:28:5 @@ -65,11 +45,7 @@ error: strict comparison of `f32` or `f64` constant LL | v == ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() < error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:28:5 - | -LL | v == ONE; - | ^^^^^^^^ + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` error: strict comparison of `f32` or `f64` constant --> $DIR/float_cmp_const.rs:29:5 @@ -77,11 +53,15 @@ error: strict comparison of `f32` or `f64` constant LL | v != ONE; | ^^^^^^^^ help: consider comparing them within some error: `(v - ONE).abs() > error` | -note: `std::f32::EPSILON` and `std::f64::EPSILON` are available. - --> $DIR/float_cmp_const.rs:29:5 + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` + +error: strict comparison of `f32` or `f64` constant arrays + --> $DIR/float_cmp_const.rs:61:5 | -LL | v != ONE; - | ^^^^^^^^ +LL | NON_ZERO_ARRAY == NON_ZERO_ARRAY2; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `f32::EPSILON` and `f64::EPSILON` are available for the `error` -error: aborting due to 7 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/fn_address_comparisons.rs b/tests/ui/fn_address_comparisons.rs new file mode 100644 index 00000000000..362dcb4fd80 --- /dev/null +++ b/tests/ui/fn_address_comparisons.rs @@ -0,0 +1,20 @@ +use std::fmt::Debug; +use std::ptr; +use std::rc::Rc; +use std::sync::Arc; + +fn a() {} + +#[warn(clippy::fn_address_comparisons)] +fn main() { + type F = fn(); + let f: F = a; + let g: F = f; + + // These should fail: + let _ = f == a; + let _ = f != a; + + // These should be fine: + let _ = f == g; +} diff --git a/tests/ui/fn_address_comparisons.stderr b/tests/ui/fn_address_comparisons.stderr new file mode 100644 index 00000000000..9c1b5419a43 --- /dev/null +++ b/tests/ui/fn_address_comparisons.stderr @@ -0,0 +1,16 @@ +error: comparing with a non-unique address of a function item + --> $DIR/fn_address_comparisons.rs:15:13 + | +LL | let _ = f == a; + | ^^^^^^ + | + = note: `-D clippy::fn-address-comparisons` implied by `-D warnings` + +error: comparing with a non-unique address of a function item + --> $DIR/fn_address_comparisons.rs:16:13 + | +LL | let _ = f != a; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index 6717899ed09..5fc84ada9ef 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -28,7 +28,6 @@ impl Unrelated { clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, - clippy::cognitive_complexity, clippy::similar_names )] #[allow(clippy::many_single_char_names, unused_variables)] diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 7c08d383420..4165b0dc004 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -28,7 +28,6 @@ impl Unrelated { clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, - clippy::cognitive_complexity, clippy::similar_names )] #[allow(clippy::many_single_char_names, unused_variables)] diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr index f84b7a660ff..cffb4b9f0a9 100644 --- a/tests/ui/for_loop_fixable.stderr +++ b/tests/ui/for_loop_fixable.stderr @@ -1,5 +1,5 @@ error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:39:14 + --> $DIR/for_loop_fixable.rs:38:14 | LL | for i in 10..0 { | ^^^^^ @@ -11,7 +11,7 @@ LL | for i in (0..10).rev() { | ^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:43:14 + --> $DIR/for_loop_fixable.rs:42:14 | LL | for i in 10..=0 { | ^^^^^^ @@ -22,7 +22,7 @@ LL | for i in (0..=10).rev() { | ^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:47:14 + --> $DIR/for_loop_fixable.rs:46:14 | LL | for i in MAX_LEN..0 { | ^^^^^^^^^^ @@ -33,7 +33,7 @@ LL | for i in (0..MAX_LEN).rev() { | ^^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:72:14 + --> $DIR/for_loop_fixable.rs:71:14 | LL | for i in 10..5 + 4 { | ^^^^^^^^^ @@ -44,7 +44,7 @@ LL | for i in (5 + 4..10).rev() { | ^^^^^^^^^^^^^^^^^ error: this range is empty so this for loop will never run - --> $DIR/for_loop_fixable.rs:76:14 + --> $DIR/for_loop_fixable.rs:75:14 | LL | for i in (5 + 2)..(3 - 1) { | ^^^^^^^^^^^^^^^^ @@ -55,7 +55,7 @@ LL | for i in ((3 - 1)..(5 + 2)).rev() { | ^^^^^^^^^^^^^^^^^^^^^^^^ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:98:15 + --> $DIR/for_loop_fixable.rs:97:15 | LL | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -63,13 +63,13 @@ LL | for _v in vec.iter() {} = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:100:15 + --> $DIR/for_loop_fixable.rs:99:15 | LL | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:103:15 + --> $DIR/for_loop_fixable.rs:102:15 | LL | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` @@ -77,73 +77,73 @@ LL | for _v in out_vec.into_iter() {} = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:108:15 + --> $DIR/for_loop_fixable.rs:107:15 | LL | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:112:15 + --> $DIR/for_loop_fixable.rs:111:15 | LL | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:117:15 + --> $DIR/for_loop_fixable.rs:116:15 | LL | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:120:15 + --> $DIR/for_loop_fixable.rs:119:15 | LL | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:123:15 + --> $DIR/for_loop_fixable.rs:122:15 | LL | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:126:15 + --> $DIR/for_loop_fixable.rs:125:15 | LL | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:129:15 + --> $DIR/for_loop_fixable.rs:128:15 | LL | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:132:15 + --> $DIR/for_loop_fixable.rs:131:15 | LL | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:135:15 + --> $DIR/for_loop_fixable.rs:134:15 | LL | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:310:18 + --> $DIR/for_loop_fixable.rs:309:18 | LL | for i in iterator.into_iter() { | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:330:18 + --> $DIR/for_loop_fixable.rs:329:18 | LL | for _ in t.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:332:18 + --> $DIR/for_loop_fixable.rs:331:18 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` diff --git a/tests/ui/for_loop_unfixable.rs b/tests/ui/for_loop_unfixable.rs index 20a93a22282..179b255e08c 100644 --- a/tests/ui/for_loop_unfixable.rs +++ b/tests/ui/for_loop_unfixable.rs @@ -12,7 +12,6 @@ clippy::linkedlist, clippy::shadow_unrelated, clippy::unnecessary_mut_passed, - clippy::cognitive_complexity, clippy::similar_names, unused, dead_code diff --git a/tests/ui/for_loop_unfixable.stderr b/tests/ui/for_loop_unfixable.stderr index e88bfffaae6..1da8e0f3588 100644 --- a/tests/ui/for_loop_unfixable.stderr +++ b/tests/ui/for_loop_unfixable.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function `f` in this scope - --> $DIR/for_loop_unfixable.rs:37:12 + --> $DIR/for_loop_unfixable.rs:36:12 | LL | if f(&vec[i], &vec[i]) { | ^ help: a local variable with a similar name exists: `i` diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index 67b4c311085..6bbf79edfcf 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -78,7 +78,7 @@ fn if_same_then_else() { let _ = if true { 0.0 } else { -0.0 }; // Different NaNs - let _ = if true { 0.0 / 0.0 } else { std::f32::NAN }; + let _ = if true { 0.0 / 0.0 } else { f32::NAN }; if true { foo(); diff --git a/tests/ui/if_same_then_else2.rs b/tests/ui/if_same_then_else2.rs index 8e61bf3830b..3cc21809264 100644 --- a/tests/ui/if_same_then_else2.rs +++ b/tests/ui/if_same_then_else2.rs @@ -1,7 +1,6 @@ #![warn(clippy::if_same_then_else)] #![allow( clippy::blacklisted_name, - clippy::cognitive_complexity, clippy::collapsible_if, clippy::ifs_same_cond, clippy::needless_return @@ -87,10 +86,10 @@ fn if_same_then_else2() -> Result<&'static str, ()> { // Same NaNs let _ = if true { - std::f32::NAN + f32::NAN } else { //~ ERROR same body as `if` block - std::f32::NAN + f32::NAN }; if true { diff --git a/tests/ui/if_same_then_else2.stderr b/tests/ui/if_same_then_else2.stderr index c6da3c6be64..f5d087fe128 100644 --- a/tests/ui/if_same_then_else2.stderr +++ b/tests/ui/if_same_then_else2.stderr @@ -1,5 +1,5 @@ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:20:12 + --> $DIR/if_same_then_else2.rs:19:12 | LL | } else { | ____________^ @@ -13,7 +13,7 @@ LL | | } | = note: `-D clippy::if-same-then-else` implied by `-D warnings` note: same as this - --> $DIR/if_same_then_else2.rs:11:13 + --> $DIR/if_same_then_else2.rs:10:13 | LL | if true { | _____________^ @@ -26,7 +26,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:34:12 + --> $DIR/if_same_then_else2.rs:33:12 | LL | } else { | ____________^ @@ -36,7 +36,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:32:13 + --> $DIR/if_same_then_else2.rs:31:13 | LL | if true { | _____________^ @@ -45,7 +45,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:41:12 + --> $DIR/if_same_then_else2.rs:40:12 | LL | } else { | ____________^ @@ -55,7 +55,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:39:13 + --> $DIR/if_same_then_else2.rs:38:13 | LL | if true { | _____________^ @@ -64,26 +64,26 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:91:12 + --> $DIR/if_same_then_else2.rs:90:12 | LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | std::f32::NAN +LL | | f32::NAN LL | | }; | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:89:21 + --> $DIR/if_same_then_else2.rs:88:21 | LL | let _ = if true { | _____________________^ -LL | | std::f32::NAN +LL | | f32::NAN LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:98:12 + --> $DIR/if_same_then_else2.rs:97:12 | LL | } else { | ____________^ @@ -93,7 +93,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:96:13 + --> $DIR/if_same_then_else2.rs:95:13 | LL | if true { | _____________^ @@ -102,7 +102,7 @@ LL | | } else { | |_____^ error: this `if` has identical blocks - --> $DIR/if_same_then_else2.rs:123:12 + --> $DIR/if_same_then_else2.rs:122:12 | LL | } else { | ____________^ @@ -112,7 +112,7 @@ LL | | } | |_____^ | note: same as this - --> $DIR/if_same_then_else2.rs:120:20 + --> $DIR/if_same_then_else2.rs:119:20 | LL | } else if true { | ____________________^ diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index c0ffa6879ce..fdcc9a33f55 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,4 +1,5 @@ // aux-build:implicit_hasher_macros.rs +#![deny(clippy::implicit_hasher)] #![allow(unused)] #[macro_use] diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 252e9eb5dd8..2b06d661772 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,10 +1,14 @@ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:15:35 + --> $DIR/implicit_hasher.rs:16:35 | LL | impl<K: Hash + Eq, V> Foo<i8> for HashMap<K, V> { | ^^^^^^^^^^^^^ | - = note: `-D clippy::implicit-hasher` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/implicit_hasher.rs:2:9 + | +LL | #![deny(clippy::implicit_hasher)] + | ^^^^^^^^^^^^^^^^^^^^^^^ help: consider adding a type parameter | LL | impl<K: Hash + Eq, V, S: ::std::hash::BuildHasher + Default> Foo<i8> for HashMap<K, V, S> { @@ -15,7 +19,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:24:36 + --> $DIR/implicit_hasher.rs:25:36 | LL | impl<K: Hash + Eq, V> Foo<i8> for (HashMap<K, V>,) { | ^^^^^^^^^^^^^ @@ -30,7 +34,7 @@ LL | ((HashMap::default(),), (HashMap::with_capacity_and_hasher(10, Defa | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:29:19 + --> $DIR/implicit_hasher.rs:30:19 | LL | impl Foo<i16> for HashMap<String, String> { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -45,7 +49,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:46:32 + --> $DIR/implicit_hasher.rs:47:32 | LL | impl<T: Hash + Eq> Foo<i8> for HashSet<T> { | ^^^^^^^^^^ @@ -60,7 +64,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: impl for `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:51:19 + --> $DIR/implicit_hasher.rs:52:19 | LL | impl Foo<i16> for HashSet<String> { | ^^^^^^^^^^^^^^^ @@ -75,7 +79,7 @@ LL | (HashSet::default(), HashSet::with_capacity_and_hasher(10, Default: | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:68:23 + --> $DIR/implicit_hasher.rs:69:23 | LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^^^^^^ @@ -86,7 +90,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32, S>, _s | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:68:53 + --> $DIR/implicit_hasher.rs:69:53 | LL | pub fn foo(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^ @@ -97,7 +101,7 @@ LL | pub fn foo<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i32>, _set: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:72:43 + --> $DIR/implicit_hasher.rs:73:43 | LL | impl<K: Hash + Eq, V> Foo<u8> for HashMap<K, V> { | ^^^^^^^^^^^^^ @@ -116,7 +120,7 @@ LL | (HashMap::default(), HashMap::with_capacity_and_hasher(10, | ^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:80:33 + --> $DIR/implicit_hasher.rs:81:33 | LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^^^^^^ @@ -131,7 +135,7 @@ LL | pub fn $name<S: ::std::hash::BuildHasher>(_map: &mut HashMap<i32, i | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:80:63 + --> $DIR/implicit_hasher.rs:81:63 | LL | pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {} | ^^^^^^^^^^^^ diff --git a/tests/ui/inconsistent_digit_grouping.fixed b/tests/ui/inconsistent_digit_grouping.fixed index f10673adfb2..b75f10917df 100644 --- a/tests/ui/inconsistent_digit_grouping.fixed +++ b/tests/ui/inconsistent_digit_grouping.fixed @@ -1,5 +1,6 @@ // run-rustfix #[warn(clippy::inconsistent_digit_grouping)] +#[deny(clippy::unreadable_literal)] #[allow(unused_variables, clippy::excessive_precision)] fn main() { macro_rules! mac1 { @@ -33,6 +34,9 @@ fn main() { // Test suggestion when fraction has no digits let _: f32 = 123_456.; + // Test UUID formatted literal + let _: u128 = 0x12345678_1234_1234_1234_123456789012; + // Ignore literals in macros let _ = mac1!(); let _ = mac2!(); diff --git a/tests/ui/inconsistent_digit_grouping.rs b/tests/ui/inconsistent_digit_grouping.rs index b97df0865ee..79ce38be19b 100644 --- a/tests/ui/inconsistent_digit_grouping.rs +++ b/tests/ui/inconsistent_digit_grouping.rs @@ -1,5 +1,6 @@ // run-rustfix #[warn(clippy::inconsistent_digit_grouping)] +#[deny(clippy::unreadable_literal)] #[allow(unused_variables, clippy::excessive_precision)] fn main() { macro_rules! mac1 { @@ -33,6 +34,9 @@ fn main() { // Test suggestion when fraction has no digits let _: f32 = 1_23_456.; + // Test UUID formatted literal + let _: u128 = 0x12345678_1234_1234_1234_123456789012; + // Ignore literals in macros let _ = mac1!(); let _ = mac2!(); diff --git a/tests/ui/inconsistent_digit_grouping.stderr b/tests/ui/inconsistent_digit_grouping.stderr index 37211efcab5..b8ac9155462 100644 --- a/tests/ui/inconsistent_digit_grouping.stderr +++ b/tests/ui/inconsistent_digit_grouping.stderr @@ -1,5 +1,5 @@ error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:25:16 + --> $DIR/inconsistent_digit_grouping.rs:26:16 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `123_456` @@ -7,57 +7,61 @@ LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f = note: `-D clippy::inconsistent-digit-grouping` implied by `-D warnings` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:25:26 + --> $DIR/inconsistent_digit_grouping.rs:26:26 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^ help: consider: `12_345_678` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:25:38 + --> $DIR/inconsistent_digit_grouping.rs:26:38 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^ help: consider: `1_234_567` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:25:48 + --> $DIR/inconsistent_digit_grouping.rs:26:48 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1_234.567_8_f32` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:25:64 + --> $DIR/inconsistent_digit_grouping.rs:26:64 | LL | let bad = (1_23_456, 1_234_5678, 1234_567, 1_234.5678_f32, 1.234_5678_f32); | ^^^^^^^^^^^^^^ help: consider: `1.234_567_8_f32` error: long literal lacking separators - --> $DIR/inconsistent_digit_grouping.rs:28:13 + --> $DIR/inconsistent_digit_grouping.rs:29:13 | LL | let _ = 0x100000; | ^^^^^^^^ help: consider: `0x0010_0000` | - = note: `-D clippy::unreadable-literal` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/inconsistent_digit_grouping.rs:3:8 + | +LL | #[deny(clippy::unreadable_literal)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: long literal lacking separators - --> $DIR/inconsistent_digit_grouping.rs:29:13 + --> $DIR/inconsistent_digit_grouping.rs:30:13 | LL | let _ = 0x1000000; | ^^^^^^^^^ help: consider: `0x0100_0000` error: long literal lacking separators - --> $DIR/inconsistent_digit_grouping.rs:30:13 + --> $DIR/inconsistent_digit_grouping.rs:31:13 | LL | let _ = 0x10000000; | ^^^^^^^^^^ help: consider: `0x1000_0000` error: long literal lacking separators - --> $DIR/inconsistent_digit_grouping.rs:31:13 + --> $DIR/inconsistent_digit_grouping.rs:32:13 | LL | let _ = 0x100000000_u64; | ^^^^^^^^^^^^^^^ help: consider: `0x0001_0000_0000_u64` error: digits grouped inconsistently by underscores - --> $DIR/inconsistent_digit_grouping.rs:34:18 + --> $DIR/inconsistent_digit_grouping.rs:35:18 | LL | let _: f32 = 1_23_456.; | ^^^^^^^^^ help: consider: `123_456.` diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index c324eb95777..1fe68897765 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -1,5 +1,4 @@ use std::iter::repeat; -#[allow(clippy::trivially_copy_pass_by_ref)] fn square_is_lower_64(x: &u32) -> bool { x * x < 64 } diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 4750316d3f4..5f5e7ac9f25 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -1,29 +1,29 @@ error: infinite iteration detected - --> $DIR/infinite_iter.rs:10:5 + --> $DIR/infinite_iter.rs:9:5 | LL | repeat(0_u8).collect::<Vec<_>>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/infinite_iter.rs:8:8 + --> $DIR/infinite_iter.rs:7:8 | LL | #[deny(clippy::infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:11:5 + --> $DIR/infinite_iter.rs:10:5 | LL | (0..8_u32).take_while(square_is_lower_64).cycle().count(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:12:5 + --> $DIR/infinite_iter.rs:11:5 | LL | (0..8_u64).chain(0..).max(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:17:5 + --> $DIR/infinite_iter.rs:16:5 | LL | / (0..8_u32) LL | | .rev() @@ -33,37 +33,37 @@ LL | | .for_each(|x| println!("{}", x)); // infinite iter | |________________________________________^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:23:5 + --> $DIR/infinite_iter.rs:22:5 | LL | (0_usize..).flat_map(|x| 0..x).product::<usize>(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:24:5 + --> $DIR/infinite_iter.rs:23:5 | LL | (0_u64..).filter(|x| x % 2 == 0).last(); // infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:31:5 + --> $DIR/infinite_iter.rs:30:5 | LL | (0..).zip((0..).take_while(square_is_lower_64)).count(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/infinite_iter.rs:29:8 + --> $DIR/infinite_iter.rs:28:8 | LL | #[deny(clippy::maybe_infinite_iter)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:32:5 + --> $DIR/infinite_iter.rs:31:5 | LL | repeat(42).take_while(|x| *x == 42).chain(0..42).max(); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:33:5 + --> $DIR/infinite_iter.rs:32:5 | LL | / (1..) LL | | .scan(0, |state, x| { @@ -74,31 +74,31 @@ LL | | .min(); // maybe infinite iter | |______________^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:39:5 + --> $DIR/infinite_iter.rs:38:5 | LL | (0..).find(|x| *x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:40:5 + --> $DIR/infinite_iter.rs:39:5 | LL | (0..).position(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:41:5 + --> $DIR/infinite_iter.rs:40:5 | LL | (0..).any(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: possible infinite iteration detected - --> $DIR/infinite_iter.rs:42:5 + --> $DIR/infinite_iter.rs:41:5 | LL | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ error: infinite iteration detected - --> $DIR/infinite_iter.rs:65:31 + --> $DIR/infinite_iter.rs:64:31 | LL | let _: HashSet<i32> = (0..).collect(); // Infinite iter | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 09f47adc46e..72591f12baf 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,5 +1,3 @@ -#![allow(clippy::trivially_copy_pass_by_ref)] - fn fn_val(i: i32) -> i32 { unimplemented!() } diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 2736753c14b..1fcb29eff18 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,5 +1,5 @@ error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:23:11 + --> $DIR/infinite_loop.rs:21:11 | LL | while y < 10 { | ^^^^^^ @@ -8,7 +8,7 @@ LL | while y < 10 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:28:11 + --> $DIR/infinite_loop.rs:26:11 | LL | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | while y < 10 && x < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:35:11 + --> $DIR/infinite_loop.rs:33:11 | LL | while !cond { | ^^^^^ @@ -24,7 +24,7 @@ LL | while !cond { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:79:11 + --> $DIR/infinite_loop.rs:77:11 | LL | while i < 3 { | ^^^^^ @@ -32,7 +32,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:84:11 + --> $DIR/infinite_loop.rs:82:11 | LL | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | while i < 3 && j > 0 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:88:11 + --> $DIR/infinite_loop.rs:86:11 | LL | while i < 3 { | ^^^^^ @@ -48,7 +48,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:103:11 + --> $DIR/infinite_loop.rs:101:11 | LL | while i < 3 { | ^^^^^ @@ -56,7 +56,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:108:11 + --> $DIR/infinite_loop.rs:106:11 | LL | while i < 3 { | ^^^^^ @@ -64,7 +64,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:174:15 + --> $DIR/infinite_loop.rs:172:15 | LL | while self.count < n { | ^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | while self.count < n { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:182:11 + --> $DIR/infinite_loop.rs:180:11 | LL | while y < 10 { | ^^^^^^ @@ -82,7 +82,7 @@ LL | while y < 10 { = help: rewrite it as `if cond { loop { } }` error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:189:11 + --> $DIR/infinite_loop.rs:187:11 | LL | while y < 10 { | ^^^^^^ diff --git a/tests/ui/integer_arithmetic.rs b/tests/ui/integer_arithmetic.rs index 31a07e7c35b..2fe32c6ace8 100644 --- a/tests/ui/integer_arithmetic.rs +++ b/tests/ui/integer_arithmetic.rs @@ -5,8 +5,7 @@ clippy::shadow_unrelated, clippy::no_effect, clippy::unnecessary_operation, - clippy::op_ref, - clippy::trivially_copy_pass_by_ref + clippy::op_ref )] #[rustfmt::skip] diff --git a/tests/ui/integer_arithmetic.stderr b/tests/ui/integer_arithmetic.stderr index 0b8d0b767bf..64c44d7ecc7 100644 --- a/tests/ui/integer_arithmetic.stderr +++ b/tests/ui/integer_arithmetic.stderr @@ -1,5 +1,5 @@ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:15:5 + --> $DIR/integer_arithmetic.rs:14:5 | LL | 1 + i; | ^^^^^ @@ -7,98 +7,98 @@ LL | 1 + i; = note: `-D clippy::integer-arithmetic` implied by `-D warnings` error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:16:5 + --> $DIR/integer_arithmetic.rs:15:5 | LL | i * 2; | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:17:5 + --> $DIR/integer_arithmetic.rs:16:5 | LL | / 1 % LL | | i / 2; // no error, this is part of the expression in the preceding line | |_________^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:19:5 + --> $DIR/integer_arithmetic.rs:18:5 | LL | i - 2 + 2 - i; | ^^^^^^^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:20:5 + --> $DIR/integer_arithmetic.rs:19:5 | LL | -i; | ^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:32:5 + --> $DIR/integer_arithmetic.rs:31:5 | LL | i += 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:33:5 + --> $DIR/integer_arithmetic.rs:32:5 | LL | i -= 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:34:5 + --> $DIR/integer_arithmetic.rs:33:5 | LL | i *= 2; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:35:5 + --> $DIR/integer_arithmetic.rs:34:5 | LL | i /= 2; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:36:5 + --> $DIR/integer_arithmetic.rs:35:5 | LL | i %= 2; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:82:5 + --> $DIR/integer_arithmetic.rs:81:5 | LL | 3 + &1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:83:5 + --> $DIR/integer_arithmetic.rs:82:5 | LL | &3 + 1; | ^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:84:5 + --> $DIR/integer_arithmetic.rs:83:5 | LL | &3 + &1; | ^^^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:89:5 + --> $DIR/integer_arithmetic.rs:88:5 | LL | a + x | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:93:5 + --> $DIR/integer_arithmetic.rs:92:5 | LL | x + y | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:97:5 + --> $DIR/integer_arithmetic.rs:96:5 | LL | x + y | ^^^^^ error: integer arithmetic detected - --> $DIR/integer_arithmetic.rs:101:5 + --> $DIR/integer_arithmetic.rs:100:5 | LL | (&x + &y) | ^^^^^^^^^ diff --git a/tests/ui/large_enum_variant.stderr b/tests/ui/large_enum_variant.stderr index d3c41ef3c6f..5d659611533 100644 --- a/tests/ui/large_enum_variant.stderr +++ b/tests/ui/large_enum_variant.stderr @@ -11,18 +11,6 @@ LL | B(Box<[i32; 8000]>), | ^^^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:18:5 - | -LL | C(T, [i32; 8000]), - | ^^^^^^^^^^^^^^^^^ - | -help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:18:5 - | -LL | C(T, [i32; 8000]), - | ^^^^^^^^^^^^^^^^^ - -error: large size difference between variants --> $DIR/large_enum_variant.rs:31:5 | LL | ContainingLargeEnum(LargeEnum), @@ -34,18 +22,6 @@ LL | ContainingLargeEnum(Box<LargeEnum>), | ^^^^^^^^^^^^^^ error: large size difference between variants - --> $DIR/large_enum_variant.rs:34:5 - | -LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -help: consider boxing the large fields to reduce the total size of the enum - --> $DIR/large_enum_variant.rs:34:5 - | -LL | ContainingMoreThanOneField(i32, [i32; 8000], [i32; 9500]), - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: large size difference between variants --> $DIR/large_enum_variant.rs:41:5 | LL | StructLikeLarge { x: [i32; 8000], y: i32 }, @@ -68,5 +44,5 @@ help: consider boxing the large fields to reduce the total size of the enum LL | StructLikeLarge2 { x: Box<[i32; 8000]> }, | ^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/let_underscore_must_use.rs b/tests/ui/let_underscore_must_use.rs index 7f481542fa7..27dda606067 100644 --- a/tests/ui/let_underscore_must_use.rs +++ b/tests/ui/let_underscore_must_use.rs @@ -88,4 +88,7 @@ fn main() { let _ = a.map(|_| ()); let _ = a; + + #[allow(clippy::let_underscore_must_use)] + let _ = a; } diff --git a/tests/ui/lint_without_lint_pass.rs b/tests/ui/lint_without_lint_pass.rs index 8eb1f7b6461..beaef79a340 100644 --- a/tests/ui/lint_without_lint_pass.rs +++ b/tests/ui/lint_without_lint_pass.rs @@ -2,7 +2,7 @@ #![feature(rustc_private)] #[macro_use] -extern crate rustc; +extern crate rustc_middle; #[macro_use] extern crate rustc_session; extern crate rustc_lint; diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 2af33b26340..7880cf36415 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -6,6 +6,7 @@ clippy::blacklisted_name, clippy::default_trait_access, clippy::missing_docs_in_private_items, + clippy::missing_safety_doc, clippy::non_ascii_literal, clippy::new_without_default, clippy::needless_pass_by_value, @@ -83,6 +84,20 @@ impl T { } } +pub struct T1; + +impl T1 { + // Shouldn't trigger lint as it is unsafe. + pub unsafe fn add(self, rhs: T1) -> T1 { + self + } + + // Should not trigger lint since this is an async function. + pub async fn next(&mut self) -> Option<T1> { + None + } +} + struct Lt<'a> { foo: &'a u32, } diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 878e78fdcc5..01cf487ac14 100644 --- a/tests/ui/methods.stderr +++ b/tests/ui/methods.stderr @@ -1,5 +1,5 @@ error: defining a method called `add` on this type; consider implementing the `std::ops::Add` trait or choosing a less ambiguous name - --> $DIR/methods.rs:38:5 + --> $DIR/methods.rs:39:5 | LL | / pub fn add(self, other: T) -> T { LL | | self @@ -9,7 +9,7 @@ LL | | } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: methods called `new` usually return `Self` - --> $DIR/methods.rs:154:5 + --> $DIR/methods.rs:169:5 | LL | / fn new() -> i32 { LL | | 0 @@ -19,7 +19,7 @@ LL | | } = note: `-D clippy::new-ret-no-self` implied by `-D warnings` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:173:13 + --> $DIR/methods.rs:188:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL | let _ = v.iter().filter(|&x| *x < 0).next(); = note: replace `filter(|&x| *x < 0).next()` with `find(|&x| *x < 0)` error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:176:13 + --> $DIR/methods.rs:191:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -38,7 +38,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:193:22 + --> $DIR/methods.rs:208:22 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x < 0)` @@ -46,25 +46,25 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: `-D clippy::search-is-some` implied by `-D warnings` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:194:20 + --> $DIR/methods.rs:209:20 | LL | let _ = (0..1).find(|x| **y == *x).is_some(); // one dereference less | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| **y == x)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:195:20 + --> $DIR/methods.rs:210:20 | LL | let _ = (0..1).find(|x| *x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:196:22 + --> $DIR/methods.rs:211:22 | LL | let _ = v.iter().find(|x| **x == 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|x| *x == 0)` error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:199:13 + --> $DIR/methods.rs:214:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -74,13 +74,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:205:22 + --> $DIR/methods.rs:220:22 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:208:13 + --> $DIR/methods.rs:223:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -90,13 +90,13 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:214:22 + --> $DIR/methods.rs:229:22 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `any(|&x| x < 0)` error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:217:13 + --> $DIR/methods.rs:232:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index e2ceb8baded..9556f6f82cc 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -1,6 +1,6 @@ // run-rustfix #![feature(never_type)] -#![allow(unused_mut)] +#![allow(unused_mut, clippy::redundant_allocation)] #![warn(clippy::must_use_candidate)] use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 29ef8d1ed9c..37324220171 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -1,6 +1,6 @@ // run-rustfix #![feature(never_type)] -#![allow(unused_mut)] +#![allow(unused_mut, clippy::redundant_allocation)] #![warn(clippy::must_use_candidate)] use std::rc::Rc; use std::sync::atomic::{AtomicBool, Ordering}; diff --git a/tests/ui/mut_from_ref.rs b/tests/ui/mut_from_ref.rs index 8f9ed7ed637..a9a04c8f56b 100644 --- a/tests/ui/mut_from_ref.rs +++ b/tests/ui/mut_from_ref.rs @@ -1,4 +1,4 @@ -#![allow(unused, clippy::trivially_copy_pass_by_ref)] +#![allow(unused)] #![warn(clippy::mut_from_ref)] struct Foo; diff --git a/tests/ui/mut_key.rs b/tests/ui/mut_key.rs index d45cf8278a8..2d227e6654c 100644 --- a/tests/ui/mut_key.rs +++ b/tests/ui/mut_key.rs @@ -1,5 +1,3 @@ -#![allow(clippy::implicit_hasher)] - use std::collections::{HashMap, HashSet}; use std::hash::{Hash, Hasher}; use std::sync::atomic::{AtomicUsize, Ordering::Relaxed}; diff --git a/tests/ui/mut_key.stderr b/tests/ui/mut_key.stderr index 5af28f18d3d..8d6a259c7e3 100644 --- a/tests/ui/mut_key.stderr +++ b/tests/ui/mut_key.stderr @@ -1,5 +1,5 @@ error: mutable key type - --> $DIR/mut_key.rs:29:32 + --> $DIR/mut_key.rs:27:32 | LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> HashSet<Key> { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> Hash = note: `#[deny(clippy::mutable_key_type)]` on by default error: mutable key type - --> $DIR/mut_key.rs:29:72 + --> $DIR/mut_key.rs:27:72 | LL | fn should_not_take_this_arg(m: &mut HashMap<Key, usize>, _n: usize) -> HashSet<Key> { | ^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:30:5 + --> $DIR/mut_key.rs:28:5 | LL | let _other: HashMap<Key, bool> = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:49:22 + --> $DIR/mut_key.rs:47:22 | LL | fn tuples_bad<U>(_m: &mut HashMap<(Key, U), bool>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index c4379e0ea1c..73906121c40 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,4 +1,4 @@ -#![allow(unused_variables, clippy::trivially_copy_pass_by_ref)] +#![allow(unused_variables)] fn takes_an_immutable_reference(a: &i32) {} fn takes_a_mutable_reference(a: &mut i32) {} diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 50f9b7c7ba6..5ae4a0e79b9 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -2,7 +2,6 @@ #![allow(clippy::needless_borrowed_reference)] -#[allow(clippy::trivially_copy_pass_by_ref)] fn x(y: &i32) -> i32 { *y } diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 8677b957e4c..1e281316c8a 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -2,7 +2,6 @@ #![allow(clippy::needless_borrowed_reference)] -#[allow(clippy::trivially_copy_pass_by_ref)] fn x(y: &i32) -> i32 { *y } diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 49df9cd072b..0bfeda7914d 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:15:15 + --> $DIR/needless_borrow.rs:14:15 | LL | let c = x(&&a); | ^^^ help: change this to: `&a` @@ -7,19 +7,19 @@ LL | let c = x(&&a); = note: `-D clippy::needless-borrow` implied by `-D warnings` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:22:17 + --> $DIR/needless_borrow.rs:21:17 | LL | if let Some(ref cake) = Some(&5) {} | ^^^^^^^^ help: change this to: `cake` error: this expression borrows a reference that is immediately dereferenced by the compiler - --> $DIR/needless_borrow.rs:29:15 + --> $DIR/needless_borrow.rs:28:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this pattern creates a reference to a reference - --> $DIR/needless_borrow.rs:52:31 + --> $DIR/needless_borrow.rs:51:31 | LL | let _ = v.iter().filter(|&ref a| a.is_empty()); | ^^^^^ help: change this to: `a` diff --git a/tests/ui/needless_lifetimes.rs b/tests/ui/needless_lifetimes.rs index f3fdd48633f..913cd004f19 100644 --- a/tests/ui/needless_lifetimes.rs +++ b/tests/ui/needless_lifetimes.rs @@ -1,5 +1,5 @@ #![warn(clippy::needless_lifetimes)] -#![allow(dead_code, clippy::needless_pass_by_value, clippy::trivially_copy_pass_by_ref)] +#![allow(dead_code, clippy::needless_pass_by_value)] fn distinct_lifetimes<'a, 'b>(_x: &'a u8, _y: &'b u8, _z: u8) {} diff --git a/tests/ui/new_ret_no_self.rs b/tests/ui/new_ret_no_self.rs index a31f046c084..35aaecc9ac4 100644 --- a/tests/ui/new_ret_no_self.rs +++ b/tests/ui/new_ret_no_self.rs @@ -1,5 +1,5 @@ #![warn(clippy::new_ret_no_self)] -#![allow(dead_code, clippy::trivially_copy_pass_by_ref)] +#![allow(dead_code)] fn main() {} diff --git a/tests/ui/option_as_ref_deref.fixed b/tests/ui/option_as_ref_deref.fixed index 973e5b308a2..076692e6445 100644 --- a/tests/ui/option_as_ref_deref.fixed +++ b/tests/ui/option_as_ref_deref.fixed @@ -35,4 +35,7 @@ fn main() { let _ = Some(1_usize).as_ref().map(|x| vc[*x].as_str()); // should not be linted let _: Option<&str> = Some(&String::new()).as_ref().map(|x| x.as_str()); // should not be linted + + let _ = opt.as_deref(); + let _ = opt.as_deref_mut(); } diff --git a/tests/ui/option_as_ref_deref.rs b/tests/ui/option_as_ref_deref.rs index baad85ab908..3bf5f715f83 100644 --- a/tests/ui/option_as_ref_deref.rs +++ b/tests/ui/option_as_ref_deref.rs @@ -38,4 +38,7 @@ fn main() { let _ = Some(1_usize).as_ref().map(|x| vc[*x].as_str()); // should not be linted let _: Option<&str> = Some(&String::new()).as_ref().map(|x| x.as_str()); // should not be linted + + let _ = opt.as_ref().map(|x| &**x); + let _ = opt.as_mut().map(|x| &mut **x); } diff --git a/tests/ui/option_as_ref_deref.stderr b/tests/ui/option_as_ref_deref.stderr index 09a0fa058e6..a106582a633 100644 --- a/tests/ui/option_as_ref_deref.stderr +++ b/tests/ui/option_as_ref_deref.stderr @@ -1,4 +1,4 @@ -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead +error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead --> $DIR/option_as_ref_deref.rs:13:13 | LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); @@ -6,7 +6,7 @@ LL | let _ = opt.clone().as_ref().map(Deref::deref).map(str::len); | = note: `-D clippy::option-as-ref-deref` implied by `-D warnings` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead +error: called `.as_ref().map(Deref::deref)` on an Option value. This can be done more directly by calling `opt.clone().as_deref()` instead --> $DIR/option_as_ref_deref.rs:16:13 | LL | let _ = opt.clone() @@ -16,77 +16,89 @@ LL | | Deref::deref LL | | ) | |_________^ help: try using as_deref instead: `opt.clone().as_deref()` -error: called `.as_mut().map(DerefMut::deref_mut)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(DerefMut::deref_mut)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead --> $DIR/option_as_ref_deref.rs:22:13 | LL | let _ = opt.as_mut().map(DerefMut::deref_mut); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(String::as_str)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead --> $DIR/option_as_ref_deref.rs:24:13 | LL | let _ = opt.as_ref().map(String::as_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(|x| x.as_str())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead --> $DIR/option_as_ref_deref.rs:25:13 | LL | let _ = opt.as_ref().map(|x| x.as_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_mut().map(DerefMut::deref_mut)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(String::as_mut_str)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead --> $DIR/option_as_ref_deref.rs:26:13 | LL | let _ = opt.as_mut().map(String::as_mut_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_mut().map(DerefMut::deref_mut)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead +error: called `.as_mut().map(|x| x.as_mut_str())` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead --> $DIR/option_as_ref_deref.rs:27:13 | LL | let _ = opt.as_mut().map(|x| x.as_mut_str()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `Some(CString::new(vec![]).unwrap()).as_deref()` instead +error: called `.as_ref().map(CString::as_c_str)` on an Option value. This can be done more directly by calling `Some(CString::new(vec![]).unwrap()).as_deref()` instead --> $DIR/option_as_ref_deref.rs:28:13 | LL | let _ = Some(CString::new(vec![]).unwrap()).as_ref().map(CString::as_c_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(CString::new(vec![]).unwrap()).as_deref()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `Some(OsString::new()).as_deref()` instead +error: called `.as_ref().map(OsString::as_os_str)` on an Option value. This can be done more directly by calling `Some(OsString::new()).as_deref()` instead --> $DIR/option_as_ref_deref.rs:29:13 | LL | let _ = Some(OsString::new()).as_ref().map(OsString::as_os_str); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(OsString::new()).as_deref()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `Some(PathBuf::new()).as_deref()` instead +error: called `.as_ref().map(PathBuf::as_path)` on an Option value. This can be done more directly by calling `Some(PathBuf::new()).as_deref()` instead --> $DIR/option_as_ref_deref.rs:30:13 | LL | let _ = Some(PathBuf::new()).as_ref().map(PathBuf::as_path); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(PathBuf::new()).as_deref()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref()` instead +error: called `.as_ref().map(Vec::as_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref()` instead --> $DIR/option_as_ref_deref.rs:31:13 | LL | let _ = Some(Vec::<()>::new()).as_ref().map(Vec::as_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `Some(Vec::<()>::new()).as_deref()` -error: called `.as_mut().map(DerefMut::deref_mut)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref_mut()` instead +error: called `.as_mut().map(Vec::as_mut_slice)` on an Option value. This can be done more directly by calling `Some(Vec::<()>::new()).as_deref_mut()` instead --> $DIR/option_as_ref_deref.rs:32:13 | LL | let _ = Some(Vec::<()>::new()).as_mut().map(Vec::as_mut_slice); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `Some(Vec::<()>::new()).as_deref_mut()` -error: called `.as_ref().map(Deref::deref)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.as_deref()` instead +error: called `.as_ref().map(|x| x.deref())` on an Option value. This can be done more directly by calling `opt.as_deref()` instead --> $DIR/option_as_ref_deref.rs:34:13 | LL | let _ = opt.as_ref().map(|x| x.deref()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` -error: called `.as_mut().map(DerefMut::deref_mut)` (or with one of deref aliases) on an Option value. This can be done more directly by calling `opt.clone().as_deref_mut()` instead +error: called `.as_mut().map(|x| x.deref_mut())` on an Option value. This can be done more directly by calling `opt.clone().as_deref_mut()` instead --> $DIR/option_as_ref_deref.rs:35:13 | LL | let _ = opt.clone().as_mut().map(|x| x.deref_mut()).map(|x| x.len()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.clone().as_deref_mut()` -error: aborting due to 14 previous errors +error: called `.as_ref().map(|x| &**x)` on an Option value. This can be done more directly by calling `opt.as_deref()` instead + --> $DIR/option_as_ref_deref.rs:42:13 + | +LL | let _ = opt.as_ref().map(|x| &**x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref instead: `opt.as_deref()` + +error: called `.as_mut().map(|x| &mut **x)` on an Option value. This can be done more directly by calling `opt.as_deref_mut()` instead + --> $DIR/option_as_ref_deref.rs:43:13 + | +LL | let _ = opt.as_mut().map(|x| &mut **x); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try using as_deref_mut instead: `opt.as_deref_mut()` + +error: aborting due to 16 previous errors diff --git a/tests/ui/option_option.rs b/tests/ui/option_option.rs index e2e649a8108..904c50e1403 100644 --- a/tests/ui/option_option.rs +++ b/tests/ui/option_option.rs @@ -1,3 +1,5 @@ +#![deny(clippy::option_option)] + fn input(_: Option<Option<u8>>) {} fn output() -> Option<Option<u8>> { diff --git a/tests/ui/option_option.stderr b/tests/ui/option_option.stderr index 9e9425cf954..79db186d7ea 100644 --- a/tests/ui/option_option.stderr +++ b/tests/ui/option_option.stderr @@ -1,55 +1,59 @@ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:1:13 + --> $DIR/option_option.rs:3:13 | LL | fn input(_: Option<Option<u8>>) {} | ^^^^^^^^^^^^^^^^^^ | - = note: `-D clippy::option-option` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/option_option.rs:1:9 + | +LL | #![deny(clippy::option_option)] + | ^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:3:16 + --> $DIR/option_option.rs:5:16 | LL | fn output() -> Option<Option<u8>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:7:27 + --> $DIR/option_option.rs:9:27 | LL | fn output_nested() -> Vec<Option<Option<u8>>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:12:30 + --> $DIR/option_option.rs:14:30 | LL | fn output_nested_nested() -> Option<Option<Option<u8>>> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:17:8 + --> $DIR/option_option.rs:19:8 | LL | x: Option<Option<u8>>, | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:21:23 + --> $DIR/option_option.rs:23:23 | LL | fn struct_fn() -> Option<Option<u8>> { | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:27:22 + --> $DIR/option_option.rs:29:22 | LL | fn trait_fn() -> Option<Option<u8>>; | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:31:11 + --> $DIR/option_option.rs:33:11 | LL | Tuple(Option<Option<u8>>), | ^^^^^^^^^^^^^^^^^^ error: consider using `Option<T>` instead of `Option<Option<T>>` or a custom enum if you need to distinguish all 3 cases - --> $DIR/option_option.rs:32:17 + --> $DIR/option_option.rs:34:17 | LL | Struct { x: Option<Option<u8>> }, | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/or_fun_call.fixed b/tests/ui/or_fun_call.fixed index cf2a42fa485..8ea03fe4261 100644 --- a/tests/ui/or_fun_call.fixed +++ b/tests/ui/or_fun_call.fixed @@ -53,9 +53,7 @@ fn or_fun_call() { with_default_type.unwrap_or_default(); let with_vec = Some(vec![1]); - with_vec.unwrap_or_else(|| vec![]); - - // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); + with_vec.unwrap_or_default(); let without_default = Some(Foo); without_default.unwrap_or_else(Foo::new); diff --git a/tests/ui/or_fun_call.rs b/tests/ui/or_fun_call.rs index 35fd0a30f6c..7599b945a91 100644 --- a/tests/ui/or_fun_call.rs +++ b/tests/ui/or_fun_call.rs @@ -55,8 +55,6 @@ fn or_fun_call() { let with_vec = Some(vec![1]); with_vec.unwrap_or(vec![]); - // FIXME #944: ~|SUGGESTION with_vec.unwrap_or_else(|| vec![]); - let without_default = Some(Foo); without_default.unwrap_or(Foo::new()); diff --git a/tests/ui/or_fun_call.stderr b/tests/ui/or_fun_call.stderr index cb92892b8e1..96d55771e6c 100644 --- a/tests/ui/or_fun_call.stderr +++ b/tests/ui/or_fun_call.stderr @@ -42,38 +42,38 @@ error: use of `unwrap_or` followed by a call to `default` LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` -error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:56:14 +error: use of `unwrap_or` followed by a call to `new` + --> $DIR/or_fun_call.rs:56:5 | LL | with_vec.unwrap_or(vec![]); - | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_vec.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:61:21 + --> $DIR/or_fun_call.rs:59:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:64:19 + --> $DIR/or_fun_call.rs:62:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/or_fun_call.rs:67:21 + --> $DIR/or_fun_call.rs:65:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/or_fun_call.rs:70:21 + --> $DIR/or_fun_call.rs:68:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: use of `or` followed by a function call - --> $DIR/or_fun_call.rs:95:35 + --> $DIR/or_fun_call.rs:93:35 | LL | let _ = Some("a".to_string()).or(Some("b".to_string())); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_else(|| Some("b".to_string()))` diff --git a/tests/ui/outer_expn_data.fixed b/tests/ui/outer_expn_data.fixed index d1bb01ae87c..999a19b289e 100644 --- a/tests/ui/outer_expn_data.fixed +++ b/tests/ui/outer_expn_data.fixed @@ -3,9 +3,9 @@ #![deny(clippy::internal)] #![feature(rustc_private)] -extern crate rustc; extern crate rustc_hir; extern crate rustc_lint; +extern crate rustc_middle; #[macro_use] extern crate rustc_session; use rustc_hir::Expr; diff --git a/tests/ui/outer_expn_data.rs b/tests/ui/outer_expn_data.rs index 56a69982f26..5405d475d1a 100644 --- a/tests/ui/outer_expn_data.rs +++ b/tests/ui/outer_expn_data.rs @@ -3,9 +3,9 @@ #![deny(clippy::internal)] #![feature(rustc_private)] -extern crate rustc; extern crate rustc_hir; extern crate rustc_lint; +extern crate rustc_middle; #[macro_use] extern crate rustc_session; use rustc_hir::Expr; diff --git a/tests/ui/redundant_allocation.fixed b/tests/ui/redundant_allocation.fixed new file mode 100644 index 00000000000..26635833458 --- /dev/null +++ b/tests/ui/redundant_allocation.fixed @@ -0,0 +1,48 @@ +// run-rustfix +#![warn(clippy::all)] +#![allow(clippy::boxed_local, clippy::needless_pass_by_value)] +#![allow(clippy::blacklisted_name, unused_variables, dead_code)] + +use std::boxed::Box; +use std::rc::Rc; + +pub struct MyStruct {} + +pub struct SubT<T> { + foo: T, +} + +pub enum MyEnum { + One, + Two, +} + +// Rc<&T> + +pub fn test1<T>(foo: &T) {} + +pub fn test2(foo: &MyStruct) {} + +pub fn test3(foo: &MyEnum) {} + +pub fn test4_neg(foo: Rc<SubT<&usize>>) {} + +// Rc<Rc<T>> + +pub fn test5(a: Rc<bool>) {} + +// Rc<Box<T>> + +pub fn test6(a: Box<bool>) {} + +// Box<&T> + +pub fn test7<T>(foo: &T) {} + +pub fn test8(foo: &MyStruct) {} + +pub fn test9(foo: &MyEnum) {} + +pub fn test10_neg(foo: Box<SubT<&usize>>) {} + +fn main() {} diff --git a/tests/ui/redundant_allocation.rs b/tests/ui/redundant_allocation.rs new file mode 100644 index 00000000000..677b3e56d4d --- /dev/null +++ b/tests/ui/redundant_allocation.rs @@ -0,0 +1,48 @@ +// run-rustfix +#![warn(clippy::all)] +#![allow(clippy::boxed_local, clippy::needless_pass_by_value)] +#![allow(clippy::blacklisted_name, unused_variables, dead_code)] + +use std::boxed::Box; +use std::rc::Rc; + +pub struct MyStruct {} + +pub struct SubT<T> { + foo: T, +} + +pub enum MyEnum { + One, + Two, +} + +// Rc<&T> + +pub fn test1<T>(foo: Rc<&T>) {} + +pub fn test2(foo: Rc<&MyStruct>) {} + +pub fn test3(foo: Rc<&MyEnum>) {} + +pub fn test4_neg(foo: Rc<SubT<&usize>>) {} + +// Rc<Rc<T>> + +pub fn test5(a: Rc<Rc<bool>>) {} + +// Rc<Box<T>> + +pub fn test6(a: Rc<Box<bool>>) {} + +// Box<&T> + +pub fn test7<T>(foo: Box<&T>) {} + +pub fn test8(foo: Box<&MyStruct>) {} + +pub fn test9(foo: Box<&MyEnum>) {} + +pub fn test10_neg(foo: Box<SubT<&usize>>) {} + +fn main() {} diff --git a/tests/ui/redundant_allocation.stderr b/tests/ui/redundant_allocation.stderr new file mode 100644 index 00000000000..eaa57ce3024 --- /dev/null +++ b/tests/ui/redundant_allocation.stderr @@ -0,0 +1,52 @@ +error: usage of `Rc<&T>` + --> $DIR/redundant_allocation.rs:22:22 + | +LL | pub fn test1<T>(foo: Rc<&T>) {} + | ^^^^^^ help: try: `&T` + | + = note: `-D clippy::redundant-allocation` implied by `-D warnings` + +error: usage of `Rc<&T>` + --> $DIR/redundant_allocation.rs:24:19 + | +LL | pub fn test2(foo: Rc<&MyStruct>) {} + | ^^^^^^^^^^^^^ help: try: `&MyStruct` + +error: usage of `Rc<&T>` + --> $DIR/redundant_allocation.rs:26:19 + | +LL | pub fn test3(foo: Rc<&MyEnum>) {} + | ^^^^^^^^^^^ help: try: `&MyEnum` + +error: usage of `Rc<Rc<T>>` + --> $DIR/redundant_allocation.rs:32:17 + | +LL | pub fn test5(a: Rc<Rc<bool>>) {} + | ^^^^^^^^^^^^ help: try: `Rc<bool>` + +error: usage of `Rc<Box<T>>` + --> $DIR/redundant_allocation.rs:36:17 + | +LL | pub fn test6(a: Rc<Box<bool>>) {} + | ^^^^^^^^^^^^^ help: try: `Box<bool>` + +error: usage of `Box<&T>` + --> $DIR/redundant_allocation.rs:40:22 + | +LL | pub fn test7<T>(foo: Box<&T>) {} + | ^^^^^^^ help: try: `&T` + +error: usage of `Box<&T>` + --> $DIR/redundant_allocation.rs:42:19 + | +LL | pub fn test8(foo: Box<&MyStruct>) {} + | ^^^^^^^^^^^^^^ help: try: `&MyStruct` + +error: usage of `Box<&T>` + --> $DIR/redundant_allocation.rs:44:19 + | +LL | pub fn test9(foo: Box<&MyEnum>) {} + | ^^^^^^^^^^^^ help: try: `&MyEnum` + +error: aborting due to 8 previous errors + diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 54815603c6d..764c10a6d39 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -51,6 +51,7 @@ fn main() { cannot_move_from_type_with_drop(); borrower_propagation(); not_consumed(); + issue_5405(); } #[derive(Clone)] @@ -160,3 +161,12 @@ fn not_consumed() { println!("{}", x); } } + +#[allow(clippy::clone_on_copy)] +fn issue_5405() { + let a: [String; 1] = [String::from("foo")]; + let _b: String = a[0].clone(); + + let c: [usize; 2] = [2, 3]; + let _d: usize = c[1].clone(); +} diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index a9b31183adc..839747b131d 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -51,6 +51,7 @@ fn main() { cannot_move_from_type_with_drop(); borrower_propagation(); not_consumed(); + issue_5405(); } #[derive(Clone)] @@ -160,3 +161,12 @@ fn not_consumed() { println!("{}", x); } } + +#[allow(clippy::clone_on_copy)] +fn issue_5405() { + let a: [String; 1] = [String::from("foo")]; + let _b: String = a[0].clone(); + + let c: [usize; 2] = [2, 3]; + let _d: usize = c[1].clone(); +} diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index 9c27812b9cd..eced198283c 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -108,61 +108,61 @@ LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:60:22 + --> $DIR/redundant_clone.rs:61:22 | LL | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:60:21 + --> $DIR/redundant_clone.rs:61:21 | LL | (a.clone(), a.clone()) | ^ error: redundant clone - --> $DIR/redundant_clone.rs:120:15 + --> $DIR/redundant_clone.rs:121:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:120:14 + --> $DIR/redundant_clone.rs:121:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:121:15 + --> $DIR/redundant_clone.rs:122:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:121:14 + --> $DIR/redundant_clone.rs:122:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:131:19 + --> $DIR/redundant_clone.rs:132:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:131:18 + --> $DIR/redundant_clone.rs:132:18 | LL | let _f = f.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:143:14 + --> $DIR/redundant_clone.rs:144:14 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^ help: remove this | note: cloned value is neither consumed nor mutated - --> $DIR/redundant_clone.rs:143:13 + --> $DIR/redundant_clone.rs:144:13 | LL | let y = x.clone().join("matthias"); | ^^^^^^^^^ diff --git a/tests/ui/redundant_pattern_matching.fixed b/tests/ui/redundant_pattern_matching.fixed index 776c9444566..538fa1ed9cb 100644 --- a/tests/ui/redundant_pattern_matching.fixed +++ b/tests/ui/redundant_pattern_matching.fixed @@ -2,7 +2,7 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::unit_arg, clippy::let_unit_value, unused_must_use)] +#![allow(clippy::unit_arg, unused_must_use)] fn main() { Ok::<i32, i32>(42).is_ok(); diff --git a/tests/ui/redundant_pattern_matching.rs b/tests/ui/redundant_pattern_matching.rs index 2b2d5b1c1ec..34d2cd62e54 100644 --- a/tests/ui/redundant_pattern_matching.rs +++ b/tests/ui/redundant_pattern_matching.rs @@ -2,7 +2,7 @@ #![warn(clippy::all)] #![warn(clippy::redundant_pattern_matching)] -#![allow(clippy::unit_arg, clippy::let_unit_value, unused_must_use)] +#![allow(clippy::unit_arg, unused_must_use)] fn main() { if let Ok(_) = Ok::<i32, i32>(42) {} diff --git a/tests/ui/rename.fixed b/tests/ui/rename.fixed index 947914aa123..13fbb6e2a6e 100644 --- a/tests/ui/rename.fixed +++ b/tests/ui/rename.fixed @@ -5,7 +5,6 @@ // allow the new lint name here, to test if the new name works #![allow(clippy::module_name_repetitions)] #![allow(clippy::new_without_default)] -#![allow(clippy::cognitive_complexity)] #![allow(clippy::redundant_static_lifetimes)] // warn for the old lint name here, to test if the renaming worked #![warn(clippy::cognitive_complexity)] diff --git a/tests/ui/rename.rs b/tests/ui/rename.rs index e2c8c223fc7..cbd3b1e9166 100644 --- a/tests/ui/rename.rs +++ b/tests/ui/rename.rs @@ -5,7 +5,6 @@ // allow the new lint name here, to test if the new name works #![allow(clippy::module_name_repetitions)] #![allow(clippy::new_without_default)] -#![allow(clippy::cognitive_complexity)] #![allow(clippy::redundant_static_lifetimes)] // warn for the old lint name here, to test if the renaming worked #![warn(clippy::cyclomatic_complexity)] diff --git a/tests/ui/rename.stderr b/tests/ui/rename.stderr index 83c7f26ba5f..a9e80394604 100644 --- a/tests/ui/rename.stderr +++ b/tests/ui/rename.stderr @@ -1,5 +1,5 @@ error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:11:9 + --> $DIR/rename.rs:10:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` @@ -7,25 +7,25 @@ LL | #![warn(clippy::cyclomatic_complexity)] = note: `-D renamed-and-removed-lints` implied by `-D warnings` error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions` - --> $DIR/rename.rs:13:8 + --> $DIR/rename.rs:12:8 | LL | #[warn(clippy::stutter)] | ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions` error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default` - --> $DIR/rename.rs:16:8 + --> $DIR/rename.rs:15:8 | LL | #[warn(clippy::new_without_default_derive)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default` error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes` - --> $DIR/rename.rs:19:8 + --> $DIR/rename.rs:18:8 | LL | #[warn(clippy::const_static_lifetime)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes` error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity` - --> $DIR/rename.rs:11:9 + --> $DIR/rename.rs:10:9 | LL | #![warn(clippy::cyclomatic_complexity)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity` diff --git a/tests/ui/replace_consts.fixed b/tests/ui/replace_consts.fixed deleted file mode 100644 index 108474408e0..00000000000 --- a/tests/ui/replace_consts.fixed +++ /dev/null @@ -1,99 +0,0 @@ -// run-rustfix -#![feature(integer_atomics)] -#![allow(unused_variables, clippy::blacklisted_name)] -#![deny(clippy::replace_consts)] - -use std::sync::atomic::*; - -#[rustfmt::skip] -fn bad() { - // Min - { let foo = isize::min_value(); }; - { let foo = i8::min_value(); }; - { let foo = i16::min_value(); }; - { let foo = i32::min_value(); }; - { let foo = i64::min_value(); }; - { let foo = i128::min_value(); }; - { let foo = usize::min_value(); }; - { let foo = u8::min_value(); }; - { let foo = u16::min_value(); }; - { let foo = u32::min_value(); }; - { let foo = u64::min_value(); }; - { let foo = u128::min_value(); }; - // Max - { let foo = isize::max_value(); }; - { let foo = i8::max_value(); }; - { let foo = i16::max_value(); }; - { let foo = i32::max_value(); }; - { let foo = i64::max_value(); }; - { let foo = i128::max_value(); }; - { let foo = usize::max_value(); }; - { let foo = u8::max_value(); }; - { let foo = u16::max_value(); }; - { let foo = u32::max_value(); }; - { let foo = u64::max_value(); }; - { let foo = u128::max_value(); }; -} - -#[rustfmt::skip] -fn good() { - // Atomic - { let foo = AtomicBool::new(false); }; - { let foo = AtomicIsize::new(0); }; - { let foo = AtomicI8::new(0); }; - { let foo = AtomicI16::new(0); }; - { let foo = AtomicI32::new(0); }; - { let foo = AtomicI64::new(0); }; - { let foo = AtomicUsize::new(0); }; - { let foo = AtomicU8::new(0); }; - { let foo = AtomicU16::new(0); }; - { let foo = AtomicU32::new(0); }; - { let foo = AtomicU64::new(0); }; - // Min - { let foo = isize::min_value(); }; - { let foo = i8::min_value(); }; - { let foo = i16::min_value(); }; - { let foo = i32::min_value(); }; - { let foo = i64::min_value(); }; - { let foo = i128::min_value(); }; - { let foo = usize::min_value(); }; - { let foo = u8::min_value(); }; - { let foo = u16::min_value(); }; - { let foo = u32::min_value(); }; - { let foo = u64::min_value(); }; - { let foo = u128::min_value(); }; - // Max - { let foo = isize::max_value(); }; - { let foo = i8::max_value(); }; - { let foo = i16::max_value(); }; - { let foo = i32::max_value(); }; - { let foo = i64::max_value(); }; - { let foo = i128::max_value(); }; - { let foo = usize::max_value(); }; - { let foo = u8::max_value(); }; - { let foo = u16::max_value(); }; - { let foo = u32::max_value(); }; - { let foo = u64::max_value(); }; - { let foo = u128::max_value(); }; - - let x = 42; - - let _ = match x { - std::i8::MIN => -1, - 1..=std::i8::MAX => 1, - _ => 0 - }; - - let _ = if let std::i8::MIN = x { - -1 - } else if let 1..=std::i8::MAX = x { - 1 - } else { - 0 - }; -} - -fn main() { - bad(); - good(); -} diff --git a/tests/ui/replace_consts.rs b/tests/ui/replace_consts.rs deleted file mode 100644 index dae3422a35f..00000000000 --- a/tests/ui/replace_consts.rs +++ /dev/null @@ -1,99 +0,0 @@ -// run-rustfix -#![feature(integer_atomics)] -#![allow(unused_variables, clippy::blacklisted_name)] -#![deny(clippy::replace_consts)] - -use std::sync::atomic::*; - -#[rustfmt::skip] -fn bad() { - // Min - { let foo = std::isize::MIN; }; - { let foo = std::i8::MIN; }; - { let foo = std::i16::MIN; }; - { let foo = std::i32::MIN; }; - { let foo = std::i64::MIN; }; - { let foo = std::i128::MIN; }; - { let foo = std::usize::MIN; }; - { let foo = std::u8::MIN; }; - { let foo = std::u16::MIN; }; - { let foo = std::u32::MIN; }; - { let foo = std::u64::MIN; }; - { let foo = std::u128::MIN; }; - // Max - { let foo = std::isize::MAX; }; - { let foo = std::i8::MAX; }; - { let foo = std::i16::MAX; }; - { let foo = std::i32::MAX; }; - { let foo = std::i64::MAX; }; - { let foo = std::i128::MAX; }; - { let foo = std::usize::MAX; }; - { let foo = std::u8::MAX; }; - { let foo = std::u16::MAX; }; - { let foo = std::u32::MAX; }; - { let foo = std::u64::MAX; }; - { let foo = std::u128::MAX; }; -} - -#[rustfmt::skip] -fn good() { - // Atomic - { let foo = AtomicBool::new(false); }; - { let foo = AtomicIsize::new(0); }; - { let foo = AtomicI8::new(0); }; - { let foo = AtomicI16::new(0); }; - { let foo = AtomicI32::new(0); }; - { let foo = AtomicI64::new(0); }; - { let foo = AtomicUsize::new(0); }; - { let foo = AtomicU8::new(0); }; - { let foo = AtomicU16::new(0); }; - { let foo = AtomicU32::new(0); }; - { let foo = AtomicU64::new(0); }; - // Min - { let foo = isize::min_value(); }; - { let foo = i8::min_value(); }; - { let foo = i16::min_value(); }; - { let foo = i32::min_value(); }; - { let foo = i64::min_value(); }; - { let foo = i128::min_value(); }; - { let foo = usize::min_value(); }; - { let foo = u8::min_value(); }; - { let foo = u16::min_value(); }; - { let foo = u32::min_value(); }; - { let foo = u64::min_value(); }; - { let foo = u128::min_value(); }; - // Max - { let foo = isize::max_value(); }; - { let foo = i8::max_value(); }; - { let foo = i16::max_value(); }; - { let foo = i32::max_value(); }; - { let foo = i64::max_value(); }; - { let foo = i128::max_value(); }; - { let foo = usize::max_value(); }; - { let foo = u8::max_value(); }; - { let foo = u16::max_value(); }; - { let foo = u32::max_value(); }; - { let foo = u64::max_value(); }; - { let foo = u128::max_value(); }; - - let x = 42; - - let _ = match x { - std::i8::MIN => -1, - 1..=std::i8::MAX => 1, - _ => 0 - }; - - let _ = if let std::i8::MIN = x { - -1 - } else if let 1..=std::i8::MAX = x { - 1 - } else { - 0 - }; -} - -fn main() { - bad(); - good(); -} diff --git a/tests/ui/replace_consts.stderr b/tests/ui/replace_consts.stderr deleted file mode 100644 index 458f63953ef..00000000000 --- a/tests/ui/replace_consts.stderr +++ /dev/null @@ -1,152 +0,0 @@ -error: using `MIN` - --> $DIR/replace_consts.rs:11:17 - | -LL | { let foo = std::isize::MIN; }; - | ^^^^^^^^^^^^^^^ help: try this: `isize::min_value()` - | -note: the lint level is defined here - --> $DIR/replace_consts.rs:4:9 - | -LL | #![deny(clippy::replace_consts)] - | ^^^^^^^^^^^^^^^^^^^^^^ - -error: using `MIN` - --> $DIR/replace_consts.rs:12:17 - | -LL | { let foo = std::i8::MIN; }; - | ^^^^^^^^^^^^ help: try this: `i8::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:13:17 - | -LL | { let foo = std::i16::MIN; }; - | ^^^^^^^^^^^^^ help: try this: `i16::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:14:17 - | -LL | { let foo = std::i32::MIN; }; - | ^^^^^^^^^^^^^ help: try this: `i32::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:15:17 - | -LL | { let foo = std::i64::MIN; }; - | ^^^^^^^^^^^^^ help: try this: `i64::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:16:17 - | -LL | { let foo = std::i128::MIN; }; - | ^^^^^^^^^^^^^^ help: try this: `i128::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:17:17 - | -LL | { let foo = std::usize::MIN; }; - | ^^^^^^^^^^^^^^^ help: try this: `usize::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:18:17 - | -LL | { let foo = std::u8::MIN; }; - | ^^^^^^^^^^^^ help: try this: `u8::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:19:17 - | -LL | { let foo = std::u16::MIN; }; - | ^^^^^^^^^^^^^ help: try this: `u16::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:20:17 - | -LL | { let foo = std::u32::MIN; }; - | ^^^^^^^^^^^^^ help: try this: `u32::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:21:17 - | -LL | { let foo = std::u64::MIN; }; - | ^^^^^^^^^^^^^ help: try this: `u64::min_value()` - -error: using `MIN` - --> $DIR/replace_consts.rs:22:17 - | -LL | { let foo = std::u128::MIN; }; - | ^^^^^^^^^^^^^^ help: try this: `u128::min_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:24:17 - | -LL | { let foo = std::isize::MAX; }; - | ^^^^^^^^^^^^^^^ help: try this: `isize::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:25:17 - | -LL | { let foo = std::i8::MAX; }; - | ^^^^^^^^^^^^ help: try this: `i8::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:26:17 - | -LL | { let foo = std::i16::MAX; }; - | ^^^^^^^^^^^^^ help: try this: `i16::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:27:17 - | -LL | { let foo = std::i32::MAX; }; - | ^^^^^^^^^^^^^ help: try this: `i32::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:28:17 - | -LL | { let foo = std::i64::MAX; }; - | ^^^^^^^^^^^^^ help: try this: `i64::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:29:17 - | -LL | { let foo = std::i128::MAX; }; - | ^^^^^^^^^^^^^^ help: try this: `i128::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:30:17 - | -LL | { let foo = std::usize::MAX; }; - | ^^^^^^^^^^^^^^^ help: try this: `usize::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:31:17 - | -LL | { let foo = std::u8::MAX; }; - | ^^^^^^^^^^^^ help: try this: `u8::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:32:17 - | -LL | { let foo = std::u16::MAX; }; - | ^^^^^^^^^^^^^ help: try this: `u16::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:33:17 - | -LL | { let foo = std::u32::MAX; }; - | ^^^^^^^^^^^^^ help: try this: `u32::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:34:17 - | -LL | { let foo = std::u64::MAX; }; - | ^^^^^^^^^^^^^ help: try this: `u64::max_value()` - -error: using `MAX` - --> $DIR/replace_consts.rs:35:17 - | -LL | { let foo = std::u128::MAX; }; - | ^^^^^^^^^^^^^^ help: try this: `u128::max_value()` - -error: aborting due to 24 previous errors - diff --git a/tests/ui/result_map_or_into_option.fixed b/tests/ui/result_map_or_into_option.fixed new file mode 100644 index 00000000000..331531b5165 --- /dev/null +++ b/tests/ui/result_map_or_into_option.fixed @@ -0,0 +1,19 @@ +// run-rustfix + +#![warn(clippy::result_map_or_into_option)] + +fn main() { + let opt: Result<u32, &str> = Ok(1); + let _ = opt.ok(); + + let rewrap = |s: u32| -> Option<u32> { Some(s) }; + + // A non-Some `f` arg should not emit the lint + let opt: Result<u32, &str> = Ok(1); + let _ = opt.map_or(None, rewrap); + + // A non-Some `f` closure where the argument is not used as the + // return should not emit the lint + let opt: Result<u32, &str> = Ok(1); + opt.map_or(None, |_x| Some(1)); +} diff --git a/tests/ui/result_map_or_into_option.rs b/tests/ui/result_map_or_into_option.rs new file mode 100644 index 00000000000..3058480e2ad --- /dev/null +++ b/tests/ui/result_map_or_into_option.rs @@ -0,0 +1,19 @@ +// run-rustfix + +#![warn(clippy::result_map_or_into_option)] + +fn main() { + let opt: Result<u32, &str> = Ok(1); + let _ = opt.map_or(None, Some); + + let rewrap = |s: u32| -> Option<u32> { Some(s) }; + + // A non-Some `f` arg should not emit the lint + let opt: Result<u32, &str> = Ok(1); + let _ = opt.map_or(None, rewrap); + + // A non-Some `f` closure where the argument is not used as the + // return should not emit the lint + let opt: Result<u32, &str> = Ok(1); + opt.map_or(None, |_x| Some(1)); +} diff --git a/tests/ui/result_map_or_into_option.stderr b/tests/ui/result_map_or_into_option.stderr new file mode 100644 index 00000000000..febf32147d1 --- /dev/null +++ b/tests/ui/result_map_or_into_option.stderr @@ -0,0 +1,10 @@ +error: called `map_or(None, Some)` on a `Result` value. This can be done more directly by calling `ok()` instead + --> $DIR/result_map_or_into_option.rs:7:13 + | +LL | let _ = opt.map_or(None, Some); + | ^^^^^^^^^^^^^^^^^^^^^^ help: try using `ok` instead: `opt.ok()` + | + = note: `-D clippy::result-map-or-into-option` implied by `-D warnings` + +error: aborting due to previous error + diff --git a/tests/ui/result_map_unit_fn_unfixable.rs b/tests/ui/result_map_unit_fn_unfixable.rs index 78a99de92d9..b197c609d7b 100644 --- a/tests/ui/result_map_unit_fn_unfixable.rs +++ b/tests/ui/result_map_unit_fn_unfixable.rs @@ -2,6 +2,10 @@ #![feature(never_type)] #![allow(unused)] +struct HasResult { + field: Result<usize, usize>, +} + fn do_nothing<T>(_: T) {} fn diverge<T>(_: T) -> ! { @@ -14,6 +18,8 @@ fn plus_one(value: usize) -> usize { #[rustfmt::skip] fn result_map_unit_fn() { + let x = HasResult { field: Ok(10) }; + x.field.map(|value| { do_nothing(value); do_nothing(value) }); x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); diff --git a/tests/ui/result_map_unit_fn_unfixable.stderr b/tests/ui/result_map_unit_fn_unfixable.stderr index 949c2294679..b23cc608621 100644 --- a/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/tests/ui/result_map_unit_fn_unfixable.stderr @@ -1,27 +1,58 @@ -error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:17:5 +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type + --> $DIR/result_map_unit_fn_unfixable.rs:23:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); - | ^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` + | + = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` -error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:19:5 +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type + --> $DIR/result_map_unit_fn_unfixable.rs:25:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); - | ^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` -error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:23:5 +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type + --> $DIR/result_map_unit_fn_unfixable.rs:29:5 | -LL | x.field.map(|value| { - | ^ not found in this scope +LL | x.field.map(|value| { + | _____^ + | |_____| + | || +LL | || do_nothing(value); +LL | || do_nothing(value) +LL | || }); + | ||______^- help: try this: `if let Ok(value) = x.field { ... }` + | |_______| + | -error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:27:5 +error: called `map(f)` on an `Result` value where `f` is a closure that returns the unit type + --> $DIR/result_map_unit_fn_unfixable.rs:33:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); - | ^ not found in this scope + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(value) = x.field { ... }` + +error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type + --> $DIR/result_map_unit_fn_unfixable.rs:37:5 + | +LL | "12".parse::<i32>().map(diverge); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(a) = "12".parse::<i32>() { diverge(a) }` + +error: called `map(f)` on an `Result` value where `f` is a function that returns the unit type + --> $DIR/result_map_unit_fn_unfixable.rs:43:5 + | +LL | y.map(do_nothing); + | ^^^^^^^^^^^^^^^^^- + | | + | help: try this: `if let Ok(_y) = y { do_nothing(_y) }` -error: aborting due to 4 previous errors +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/single_match.rs b/tests/ui/single_match.rs index 980ce9a0fab..1c55af5dfb6 100644 --- a/tests/ui/single_match.rs +++ b/tests/ui/single_match.rs @@ -81,4 +81,15 @@ fn single_match_know_enum() { } } -fn main() {} +macro_rules! single_match { + ($num:literal) => { + match $num { + 15 => println!("15"), + _ => (), + } + }; +} + +fn main() { + single_match!(5); +} diff --git a/tests/ui/single_match_else.rs b/tests/ui/single_match_else.rs index 37a99de8832..34193be0b75 100644 --- a/tests/ui/single_match_else.rs +++ b/tests/ui/single_match_else.rs @@ -18,4 +18,18 @@ fn unwrap_addr() -> Option<&'static ExprNode> { } } -fn main() {} +macro_rules! unwrap_addr { + ($expression:expr) => { + match $expression { + ExprNode::ExprAddrOf => Some(&NODE), + _ => { + let x = 5; + None + }, + } + }; +} + +fn main() { + unwrap_addr!(ExprNode::Unicorns); +} diff --git a/tests/ui/suspicious_arithmetic_impl.rs b/tests/ui/suspicious_arithmetic_impl.rs index 6ee924d3b2e..1f5b9811887 100644 --- a/tests/ui/suspicious_arithmetic_impl.rs +++ b/tests/ui/suspicious_arithmetic_impl.rs @@ -1,5 +1,5 @@ #![warn(clippy::suspicious_arithmetic_impl)] -use std::ops::{Add, AddAssign, Div, Mul, Sub}; +use std::ops::{Add, AddAssign, BitOrAssign, Div, DivAssign, Mul, MulAssign, Sub}; #[derive(Copy, Clone)] struct Foo(u32); @@ -18,6 +18,25 @@ impl AddAssign for Foo { } } +impl BitOrAssign for Foo { + fn bitor_assign(&mut self, other: Foo) { + let idx = other.0; + self.0 |= 1 << idx; // OK: BinOpKind::Shl part of AssignOp as child node + } +} + +impl MulAssign for Foo { + fn mul_assign(&mut self, other: Foo) { + self.0 /= other.0; + } +} + +impl DivAssign for Foo { + fn div_assign(&mut self, other: Foo) { + self.0 /= other.0; // OK: BinOpKind::Div == DivAssign + } +} + impl Mul for Foo { type Output = Foo; diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index e8a6efc4c4d..7e42d72c30b 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -14,5 +14,11 @@ LL | *self = *self - other; | = note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default -error: aborting due to 2 previous errors +error: Suspicious use of binary operator in `MulAssign` impl + --> $DIR/suspicious_arithmetic_impl.rs:30:16 + | +LL | self.0 /= other.0; + | ^^ + +error: aborting due to 3 previous errors diff --git a/tests/ui/trivially_copy_pass_by_ref.rs b/tests/ui/trivially_copy_pass_by_ref.rs index bd23aa99ceb..316426f1cf1 100644 --- a/tests/ui/trivially_copy_pass_by_ref.rs +++ b/tests/ui/trivially_copy_pass_by_ref.rs @@ -1,6 +1,7 @@ // normalize-stderr-test "\(\d+ byte\)" -> "(N byte)" // normalize-stderr-test "\(limit: \d+ byte\)" -> "(limit: N byte)" +#![deny(clippy::trivially_copy_pass_by_ref)] #![allow( clippy::many_single_char_names, clippy::blacklisted_name, diff --git a/tests/ui/trivially_copy_pass_by_ref.stderr b/tests/ui/trivially_copy_pass_by_ref.stderr index 1addc3d7195..be0914e4a79 100644 --- a/tests/ui/trivially_copy_pass_by_ref.stderr +++ b/tests/ui/trivially_copy_pass_by_ref.stderr @@ -1,91 +1,95 @@ error: this argument (N byte) is passed by reference, but would be more efficient if passed by value (limit: N byte) - --> $DIR/trivially_copy_pass_by_ref.rs:50:11 + --> $DIR/trivially_copy_pass_by_ref.rs:51:11 | LL | fn bad(x: &u32, y: &Foo, z: &Baz) {} | ^^^^ help: consider passing by value instead: `u32` | - = note: `-D clippy::trivially-copy-pass-by-ref` implied by `-D warnings` +note: the lint level is defined here + --> $DIR/trivially_copy_pass_by_ref.rs:4:9 + | +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) - --> $DIR/trivially_copy_pass_by_ref.rs:50:20 + --> $DIR/trivially_copy_pass_by_ref.rs:51: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) - --> $DIR/trivially_copy_pass_by_ref.rs:50:29 + --> $DIR/trivially_copy_pass_by_ref.rs:51: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) - --> $DIR/trivially_copy_pass_by_ref.rs:57:12 + --> $DIR/trivially_copy_pass_by_ref.rs:58: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) - --> $DIR/trivially_copy_pass_by_ref.rs:57:22 + --> $DIR/trivially_copy_pass_by_ref.rs:58: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) - --> $DIR/trivially_copy_pass_by_ref.rs:57:31 + --> $DIR/trivially_copy_pass_by_ref.rs:58: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) - --> $DIR/trivially_copy_pass_by_ref.rs:57:40 + --> $DIR/trivially_copy_pass_by_ref.rs:58: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) - --> $DIR/trivially_copy_pass_by_ref.rs:59:16 + --> $DIR/trivially_copy_pass_by_ref.rs:60: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) - --> $DIR/trivially_copy_pass_by_ref.rs:59:25 + --> $DIR/trivially_copy_pass_by_ref.rs:60: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) - --> $DIR/trivially_copy_pass_by_ref.rs:59:34 + --> $DIR/trivially_copy_pass_by_ref.rs:60: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) - --> $DIR/trivially_copy_pass_by_ref.rs:71:16 + --> $DIR/trivially_copy_pass_by_ref.rs:72: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) - --> $DIR/trivially_copy_pass_by_ref.rs:71:25 + --> $DIR/trivially_copy_pass_by_ref.rs:72: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) - --> $DIR/trivially_copy_pass_by_ref.rs:71:34 + --> $DIR/trivially_copy_pass_by_ref.rs:72: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) - --> $DIR/trivially_copy_pass_by_ref.rs:75:34 + --> $DIR/trivially_copy_pass_by_ref.rs:76:34 | 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) - --> $DIR/trivially_copy_pass_by_ref.rs:79:37 + --> $DIR/trivially_copy_pass_by_ref.rs:80:37 | LL | fn trait_method2(&self, _color: &Color); | ^^^^^^ help: consider passing by value instead: `Color` diff --git a/tests/ui/uninit.rs b/tests/ui/uninit.rs index a4424c490e7..f42b884e0f0 100644 --- a/tests/ui/uninit.rs +++ b/tests/ui/uninit.rs @@ -2,7 +2,6 @@ use std::mem::MaybeUninit; -#[allow(clippy::let_unit_value)] fn main() { let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; diff --git a/tests/ui/uninit.stderr b/tests/ui/uninit.stderr index f4c45354aef..a37233ecdda 100644 --- a/tests/ui/uninit.stderr +++ b/tests/ui/uninit.stderr @@ -1,5 +1,5 @@ error: this call for this type may be undefined behavior - --> $DIR/uninit.rs:7:29 + --> $DIR/uninit.rs:6:29 | LL | let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | let _: usize = unsafe { MaybeUninit::uninit().assume_init() }; = note: `#[deny(clippy::uninit_assumed_init)]` on by default error: this call for this type may be undefined behavior - --> $DIR/uninit.rs:10:31 + --> $DIR/uninit.rs:9:31 | LL | let _: [u8; 0] = unsafe { MaybeUninit::uninit().assume_init() }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unit_arg.fixed b/tests/ui/unit_arg.fixed index cf146c91f6d..a739cf7ad81 100644 --- a/tests/ui/unit_arg.fixed +++ b/tests/ui/unit_arg.fixed @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::unit_arg)] -#![allow(clippy::no_effect, unused_must_use)] +#![allow(unused_braces, clippy::no_effect, unused_must_use)] use std::fmt::Debug; diff --git a/tests/ui/unit_arg.rs b/tests/ui/unit_arg.rs index c15b0a50045..d90c49f79de 100644 --- a/tests/ui/unit_arg.rs +++ b/tests/ui/unit_arg.rs @@ -1,6 +1,6 @@ // run-rustfix #![warn(clippy::unit_arg)] -#![allow(clippy::no_effect, unused_must_use)] +#![allow(unused_braces, clippy::no_effect, unused_must_use)] use std::fmt::Debug; diff --git a/tests/ui/unnecessary_clone.rs b/tests/ui/unnecessary_clone.rs index 6dff8d87bae..7a1d031fac4 100644 --- a/tests/ui/unnecessary_clone.rs +++ b/tests/ui/unnecessary_clone.rs @@ -13,6 +13,10 @@ impl SomeTrait for SomeImpl {} fn main() {} +fn is_ascii(ch: char) -> bool { + ch.is_ascii() +} + fn clone_on_copy() { 42.clone(); @@ -27,6 +31,11 @@ fn clone_on_copy() { let mut x = 43; let _ = &x.clone(); // ok, getting a ref 'a'.clone().make_ascii_uppercase(); // ok, clone and then mutate + is_ascii('z'.clone()); + + // Issue #5436 + let mut vec = Vec::new(); + vec.push(42.clone()); } fn clone_on_ref_ptr() { diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 69447e6826c..7b34ff9e315 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -1,5 +1,5 @@ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:17:5 + --> $DIR/unnecessary_clone.rs:21:5 | LL | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` @@ -7,19 +7,31 @@ LL | 42.clone(); = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:21:5 + --> $DIR/unnecessary_clone.rs:25:5 | LL | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:24:5 + --> $DIR/unnecessary_clone.rs:28:5 | LL | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:34:14 + | +LL | is_ascii('z'.clone()); + | ^^^^^^^^^^^ help: try removing the `clone` call: `'z'` + +error: using `clone` on a `Copy` type + --> $DIR/unnecessary_clone.rs:38:14 + | +LL | vec.push(42.clone()); + | ^^^^^^^^^^ help: try removing the `clone` call: `42` + error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:39:5 + --> $DIR/unnecessary_clone.rs:48:5 | LL | rc.clone(); | ^^^^^^^^^^ help: try this: `Rc::<bool>::clone(&rc)` @@ -27,43 +39,43 @@ LL | rc.clone(); = note: `-D clippy::clone-on-ref-ptr` implied by `-D warnings` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:42:5 + --> $DIR/unnecessary_clone.rs:51:5 | LL | arc.clone(); | ^^^^^^^^^^^ help: try this: `Arc::<bool>::clone(&arc)` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:45:5 + --> $DIR/unnecessary_clone.rs:54:5 | LL | rcweak.clone(); | ^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&rcweak)` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:48:5 + --> $DIR/unnecessary_clone.rs:57:5 | LL | arc_weak.clone(); | ^^^^^^^^^^^^^^^^ help: try this: `Weak::<bool>::clone(&arc_weak)` error: using `.clone()` on a ref-counted pointer - --> $DIR/unnecessary_clone.rs:52:33 + --> $DIR/unnecessary_clone.rs:61:33 | LL | let _: Arc<dyn SomeTrait> = x.clone(); | ^^^^^^^^^ help: try this: `Arc::<SomeImpl>::clone(&x)` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:56:5 + --> $DIR/unnecessary_clone.rs:65:5 | LL | t.clone(); | ^^^^^^^^^ help: try removing the `clone` call: `t` error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:58:5 + --> $DIR/unnecessary_clone.rs:67:5 | LL | Some(t).clone(); | ^^^^^^^^^^^^^^^ help: try removing the `clone` call: `Some(t)` error: using `clone` on a double-reference; this will copy the reference instead of cloning the inner type - --> $DIR/unnecessary_clone.rs:64:22 + --> $DIR/unnecessary_clone.rs:73:22 | LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ @@ -79,10 +91,10 @@ LL | let z: &Vec<_> = &std::vec::Vec<i32>::clone(y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: using `clone` on a `Copy` type - --> $DIR/unnecessary_clone.rs:100:20 + --> $DIR/unnecessary_clone.rs:109:20 | LL | let _: E = a.clone(); | ^^^^^^^^^ help: try dereferencing it: `*****a` -error: aborting due to 12 previous errors +error: aborting due to 14 previous errors diff --git a/tests/ui/unused_self.rs b/tests/ui/unused_self.rs index 42d432a2c9e..7a4bbdda1ab 100644 --- a/tests/ui/unused_self.rs +++ b/tests/ui/unused_self.rs @@ -42,6 +42,17 @@ mod unused_self_allow { impl B { fn unused_self_move(self) {} } + + struct C {} + + #[allow(clippy::unused_self)] + impl C { + #[warn(clippy::unused_self)] + fn some_fn((): ()) {} + + // shouldn't trigger + fn unused_self_move(self) {} + } } mod used_self { diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index c6fce5df210..e356f13d087 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -1,7 +1,6 @@ // run-rustfix #![deny(clippy::useless_asref)] -#![allow(clippy::trivially_copy_pass_by_ref)] use std::fmt::Debug; diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 1d23760bd14..2a80291f5d8 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -1,7 +1,6 @@ // run-rustfix #![deny(clippy::useless_asref)] -#![allow(clippy::trivially_copy_pass_by_ref)] use std::fmt::Debug; diff --git a/tests/ui/useless_asref.stderr b/tests/ui/useless_asref.stderr index b21c67bb364..5876b54aca8 100644 --- a/tests/ui/useless_asref.stderr +++ b/tests/ui/useless_asref.stderr @@ -1,5 +1,5 @@ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:44:18 + --> $DIR/useless_asref.rs:43:18 | LL | foo_rstr(rstr.as_ref()); | ^^^^^^^^^^^^^ help: try this: `rstr` @@ -11,61 +11,61 @@ LL | #![deny(clippy::useless_asref)] | ^^^^^^^^^^^^^^^^^^^^^ error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:46:20 + --> $DIR/useless_asref.rs:45:20 | LL | foo_rslice(rslice.as_ref()); | ^^^^^^^^^^^^^^^ help: try this: `rslice` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:50:21 + --> $DIR/useless_asref.rs:49:21 | LL | foo_mrslice(mrslice.as_mut()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:52:20 + --> $DIR/useless_asref.rs:51:20 | LL | foo_rslice(mrslice.as_ref()); | ^^^^^^^^^^^^^^^^ help: try this: `mrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:59:20 + --> $DIR/useless_asref.rs:58:20 | LL | foo_rslice(rrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^ help: try this: `rrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:61:18 + --> $DIR/useless_asref.rs:60:18 | LL | foo_rstr(rrrrrstr.as_ref()); | ^^^^^^^^^^^^^^^^^ help: try this: `rrrrrstr` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:66:21 + --> $DIR/useless_asref.rs:65:21 | LL | foo_mrslice(mrrrrrslice.as_mut()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:68:20 + --> $DIR/useless_asref.rs:67:20 | LL | foo_rslice(mrrrrrslice.as_ref()); | ^^^^^^^^^^^^^^^^^^^^ help: try this: `mrrrrrslice` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:72:16 + --> $DIR/useless_asref.rs:71:16 | LL | foo_rrrrmr((&&&&MoreRef).as_ref()); | ^^^^^^^^^^^^^^^^^^^^^^ help: try this: `(&&&&MoreRef)` error: this call to `as_mut` does nothing - --> $DIR/useless_asref.rs:122:13 + --> $DIR/useless_asref.rs:121:13 | LL | foo_mrt(mrt.as_mut()); | ^^^^^^^^^^^^ help: try this: `mrt` error: this call to `as_ref` does nothing - --> $DIR/useless_asref.rs:124:12 + --> $DIR/useless_asref.rs:123:12 | LL | foo_rt(mrt.as_ref()); | ^^^^^^^^^^^^ help: try this: `mrt` diff --git a/tests/ui/useless_attribute.fixed b/tests/ui/useless_attribute.fixed index ff626ab3ddf..b222e2f7976 100644 --- a/tests/ui/useless_attribute.fixed +++ b/tests/ui/useless_attribute.fixed @@ -11,7 +11,7 @@ #[allow(unused_imports)] #[allow(unused_extern_crates)] #[macro_use] -extern crate rustc; +extern crate rustc_middle; #[macro_use] extern crate proc_macro_derive; diff --git a/tests/ui/useless_attribute.rs b/tests/ui/useless_attribute.rs index 822c6b6ea06..3422eace4ab 100644 --- a/tests/ui/useless_attribute.rs +++ b/tests/ui/useless_attribute.rs @@ -11,7 +11,7 @@ #[allow(unused_imports)] #[allow(unused_extern_crates)] #[macro_use] -extern crate rustc; +extern crate rustc_middle; #[macro_use] extern crate proc_macro_derive; diff --git a/tests/ui/vtable_address_comparisons.rs b/tests/ui/vtable_address_comparisons.rs new file mode 100644 index 00000000000..c91d96ee18a --- /dev/null +++ b/tests/ui/vtable_address_comparisons.rs @@ -0,0 +1,42 @@ +use std::fmt::Debug; +use std::ptr; +use std::rc::Rc; +use std::sync::Arc; + +#[warn(clippy::vtable_address_comparisons)] +fn main() { + let a: *const dyn Debug = &1 as &dyn Debug; + let b: *const dyn Debug = &1 as &dyn Debug; + + // These should fail: + let _ = a == b; + let _ = a != b; + let _ = a < b; + let _ = a <= b; + let _ = a > b; + let _ = a >= b; + ptr::eq(a, b); + + let a = &1 as &dyn Debug; + let b = &1 as &dyn Debug; + ptr::eq(a, b); + + let a: Rc<dyn Debug> = Rc::new(1); + Rc::ptr_eq(&a, &a); + + let a: Arc<dyn Debug> = Arc::new(1); + Arc::ptr_eq(&a, &a); + + // These should be fine: + let a = &1; + ptr::eq(a, a); + + let a = Rc::new(1); + Rc::ptr_eq(&a, &a); + + let a = Arc::new(1); + Arc::ptr_eq(&a, &a); + + let a: &[u8] = b""; + ptr::eq(a, a); +} diff --git a/tests/ui/vtable_address_comparisons.stderr b/tests/ui/vtable_address_comparisons.stderr new file mode 100644 index 00000000000..76bd57217d7 --- /dev/null +++ b/tests/ui/vtable_address_comparisons.stderr @@ -0,0 +1,83 @@ +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:12:13 + | +LL | let _ = a == b; + | ^^^^^^ + | + = note: `-D clippy::vtable-address-comparisons` implied by `-D warnings` + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:13:13 + | +LL | let _ = a != b; + | ^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:14:13 + | +LL | let _ = a < b; + | ^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:15:13 + | +LL | let _ = a <= b; + | ^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:16:13 + | +LL | let _ = a > b; + | ^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:17:13 + | +LL | let _ = a >= b; + | ^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:18:5 + | +LL | ptr::eq(a, b); + | ^^^^^^^^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:22:5 + | +LL | ptr::eq(a, b); + | ^^^^^^^^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:25:5 + | +LL | Rc::ptr_eq(&a, &a); + | ^^^^^^^^^^^^^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: comparing trait object pointers compares a non-unique vtable address + --> $DIR/vtable_address_comparisons.rs:28:5 + | +LL | Arc::ptr_eq(&a, &a); + | ^^^^^^^^^^^^^^^^^^^ + | + = help: consider extracting and comparing data pointers only + +error: aborting due to 10 previous errors + diff --git a/tests/ui/while_let_on_iterator.rs b/tests/ui/while_let_on_iterator.rs index 01838ee202e..84dfc34db15 100644 --- a/tests/ui/while_let_on_iterator.rs +++ b/tests/ui/while_let_on_iterator.rs @@ -1,5 +1,5 @@ #![warn(clippy::while_let_on_iterator)] -#![allow(clippy::never_loop, clippy::cognitive_complexity)] +#![allow(clippy::never_loop)] fn main() { let mut iter = 1..20; diff --git a/tests/ui/wrong_self_convention.rs b/tests/ui/wrong_self_convention.rs index 7567fa7158c..99652ca4470 100644 --- a/tests/ui/wrong_self_convention.rs +++ b/tests/ui/wrong_self_convention.rs @@ -1,6 +1,6 @@ #![warn(clippy::wrong_self_convention)] #![warn(clippy::wrong_pub_self_convention)] -#![allow(dead_code, clippy::trivially_copy_pass_by_ref)] +#![allow(dead_code)] fn main() {} diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index e4d6f168038..d0e88f3c5a5 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -13,7 +13,7 @@ LL | let nan = 0.0 / 0.0; | ^^^^^^^^^ | = note: `-D clippy::zero-divided-by-zero` implied by `-D warnings` - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + = help: Consider using `f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:5:19 @@ -27,7 +27,7 @@ error: constant division of `0.0` with `0.0` will always result in NaN LL | let f64_nan = 0.0 / 0.0f64; | ^^^^^^^^^^^^ | - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + = help: Consider using `f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:6:25 @@ -41,7 +41,7 @@ error: constant division of `0.0` with `0.0` will always result in NaN LL | let other_f64_nan = 0.0f64 / 0.0; | ^^^^^^^^^^^^ | - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + = help: Consider using `f64::NAN` if you would like a constant representing NaN error: equal expressions as operands to `/` --> $DIR/zero_div_zero.rs:7:28 @@ -55,7 +55,7 @@ error: constant division of `0.0` with `0.0` will always result in NaN LL | let one_more_f64_nan = 0.0f64 / 0.0f64; | ^^^^^^^^^^^^^^^ | - = help: Consider using `std::f64::NAN` if you would like a constant representing NaN + = help: Consider using `f64::NAN` if you would like a constant representing NaN error: aborting due to 8 previous errors diff --git a/util/gh-pages/versions.html b/util/gh-pages/versions.html index cd3611db300..6e810a349bf 100644 --- a/util/gh-pages/versions.html +++ b/util/gh-pages/versions.html @@ -65,6 +65,7 @@ $scope.versionOrder = function(v) { if (v === 'master') { return Infinity; } if (v === 'stable') { return Number.MAX_VALUE; } + if (v === 'beta') { return Number.MAX_VALUE - 1; } return $scope.normalizeVersion(v) .split('.') diff --git a/util/versions.py b/util/versions.py index 5798761ad75..5cdc7313f54 100755 --- a/util/versions.py +++ b/util/versions.py @@ -12,6 +12,8 @@ def key(v): return float('inf') if v == 'stable': return sys.maxsize + if v == 'beta': + return sys.maxsize - 1 v = v.replace('v', '').replace('rust-', '') |
