From 4ce100beb22800c865d831aebe949f244e860917 Mon Sep 17 00:00:00 2001 From: Andy Russell Date: Sun, 23 Jun 2019 15:57:37 -0400 Subject: [PATCH 001/133] don't strip blank lines in lint documentation --- util/export.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/util/export.py b/util/export.py index 827b1e319..06b867df3 100755 --- a/util/export.py +++ b/util/export.py @@ -2,6 +2,7 @@ # Build the gh-pages +from collections import OrderedDict import re import sys import json @@ -21,33 +22,29 @@ def parse_lint_def(lint): lint_dict['id'] = lint.name lint_dict['group'] = lint.group lint_dict['level'] = lint.level - lint_dict['docs'] = {} + lint_dict['docs'] = OrderedDict() last_section = None for line in lint.doc: - if len(line.strip()) == 0 and not last_section.startswith("Example"): - continue - match = re.match(lint_subheadline, line) if match: last_section = match.groups()[0] - if match: text = match.groups()[1] else: text = line if not last_section: - log.warn("Skipping comment line as it was not preceded by a heading") + log.warning("Skipping comment line as it was not preceded by a heading") log.debug("in lint `%s`, line `%s`", lint.name, line) - fragment = lint_dict['docs'].get(last_section, "") - if text == "\n": - line = fragment + text - else: - line = (fragment + "\n" + text).strip() + if last_section not in lint_dict['docs']: + lint_dict['docs'][last_section] = "" - lint_dict['docs'][last_section] = line + lint_dict['docs'][last_section] += text + "\n" + + for section in lint_dict['docs']: + lint_dict['docs'][section] = lint_dict['docs'][section].strip() return lint_dict From 4c771c3478d79d0d617752324f215d9bf5fe7512 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 25 Jun 2019 06:43:38 +0200 Subject: [PATCH 002/133] Add dev fmt subcommand --- clippy_dev/Cargo.toml | 1 + clippy_dev/src/fmt.rs | 167 ++++++++++++++++++++++++++ clippy_dev/src/main.rs | 40 ++++-- clippy_dev/src/stderr_length_check.rs | 19 ++- tests/fmt.rs | 20 +++ 5 files changed, 229 insertions(+), 18 deletions(-) create mode 100644 clippy_dev/src/fmt.rs create mode 100644 tests/fmt.rs diff --git a/clippy_dev/Cargo.toml b/clippy_dev/Cargo.toml index 602cd92da..e2e946d06 100644 --- a/clippy_dev/Cargo.toml +++ b/clippy_dev/Cargo.toml @@ -9,4 +9,5 @@ clap = "2.33" itertools = "0.8" regex = "1" lazy_static = "1.0" +shell-escape = "0.1" walkdir = "2" diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs new file mode 100644 index 000000000..72f8d836e --- /dev/null +++ b/clippy_dev/src/fmt.rs @@ -0,0 +1,167 @@ +use shell_escape::escape; +use std::ffi::OsStr; +use std::io; +use std::path::{Path, PathBuf}; +use std::process::{self, Command}; +use walkdir::WalkDir; + +#[derive(Debug)] +pub enum CliError { + CommandFailed(String), + IoError(io::Error), + ProjectRootNotFound, + WalkDirError(walkdir::Error), +} + +impl From for CliError { + fn from(error: io::Error) -> Self { + CliError::IoError(error) + } +} + +impl From for CliError { + fn from(error: walkdir::Error) -> Self { + CliError::WalkDirError(error) + } +} + +struct FmtContext { + check: bool, + verbose: bool, +} + +pub fn run(check: bool, verbose: bool) { + fn try_run(context: &FmtContext) -> Result { + let mut success = true; + + let project_root = project_root()?; + + success &= cargo_fmt(context, project_root.as_path())?; + success &= cargo_fmt(context, &project_root.join("clippy_dev"))?; + success &= cargo_fmt(context, &project_root.join("rustc_tools_util"))?; + + for entry in WalkDir::new(project_root.join("tests")) { + let entry = entry?; + let path = entry.path(); + + if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" { + continue; + } + + success &= rustfmt(context, &path)?; + } + + Ok(success) + } + + fn output_err(err: CliError) { + match err { + CliError::CommandFailed(command) => { + eprintln!("error: A command failed! `{}`", command); + }, + CliError::IoError(err) => { + eprintln!("error: {}", err); + }, + CliError::ProjectRootNotFound => { + eprintln!("error: Can't determine root of project. Please run inside a Clippy working dir."); + }, + CliError::WalkDirError(err) => { + eprintln!("error: {}", err); + }, + } + } + + let context = FmtContext { check, verbose }; + let result = try_run(&context); + let code = match result { + Ok(true) => 0, + Ok(false) => { + eprintln!(); + eprintln!("Formatting check failed."); + eprintln!("Run `./util/dev fmt` to update formatting."); + 1 + }, + Err(err) => { + output_err(err); + 1 + }, + }; + process::exit(code); +} + +fn format_command(program: impl AsRef, dir: impl AsRef, args: &[impl AsRef]) -> String { + let arg_display: Vec<_> = args + .iter() + .map(|a| escape(a.as_ref().to_string_lossy()).to_owned()) + .collect(); + + format!( + "cd {} && {} {}", + escape(dir.as_ref().to_string_lossy()), + escape(program.as_ref().to_string_lossy()), + arg_display.join(" ") + ) +} + +fn exec( + context: &FmtContext, + program: impl AsRef, + dir: impl AsRef, + args: &[impl AsRef], +) -> Result { + if context.verbose { + println!("{}", format_command(&program, &dir, args)); + } + + let mut child = Command::new(&program).current_dir(&dir).args(args.iter()).spawn()?; + let code = child.wait()?; + let success = code.success(); + + if !context.check && !success { + return Err(CliError::CommandFailed(format_command(&program, &dir, args))); + } + + Ok(success) +} + +fn cargo_fmt(context: &FmtContext, path: &Path) -> Result { + let mut args = vec!["+nightly", "fmt", "--all"]; + if context.check { + args.push("--"); + args.push("--check"); + } + let success = exec(context, "cargo", path, &args)?; + + Ok(success) +} + +fn rustfmt(context: &FmtContext, path: &Path) -> Result { + let mut args = vec!["+nightly".as_ref(), path.as_os_str()]; + if context.check { + args.push("--check".as_ref()); + } + let success = exec(context, "rustfmt", std::env::current_dir()?, &args)?; + if !success { + eprintln!("rustfmt failed on {}", path.display()); + } + Ok(success) +} + +fn project_root() -> Result { + let current_dir = std::env::current_dir()?; + for path in current_dir.ancestors() { + let result = std::fs::read_to_string(path.join("Cargo.toml")); + if let Err(err) = &result { + if err.kind() == io::ErrorKind::NotFound { + continue; + } + } + + let content = result?; + if content.contains("[package]\nname = \"clippy\"") { + return Ok(path.to_path_buf()); + } + } + + Err(CliError::ProjectRootNotFound) +} diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 302db24c7..8fdc4254d 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -4,6 +4,8 @@ extern crate regex; use clap::{App, Arg, SubCommand}; use clippy_dev::*; + +mod fmt; mod stderr_length_check; #[derive(PartialEq)] @@ -14,6 +16,21 @@ enum UpdateMode { fn main() { let matches = App::new("Clippy developer tooling") + .subcommand( + SubCommand::with_name("fmt") + .about("Run rustfmt on all projects and tests") + .arg( + Arg::with_name("check") + .long("check") + .help("Use the rustfmt --check option"), + ) + .arg( + Arg::with_name("verbose") + .short("v") + .long("verbose") + .help("Echo commands run"), + ), + ) .subcommand( SubCommand::with_name("update_lints") .about("Updates lint registration and information from the source code") @@ -46,14 +63,21 @@ fn main() { if matches.is_present("limit-stderr-length") { stderr_length_check::check(); } - if let Some(matches) = matches.subcommand_matches("update_lints") { - if matches.is_present("print-only") { - print_lints(); - } else if matches.is_present("check") { - update_lints(&UpdateMode::Check); - } else { - update_lints(&UpdateMode::Change); - } + + 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(); + } else if matches.is_present("check") { + update_lints(&UpdateMode::Check); + } else { + update_lints(&UpdateMode::Change); + } + }, + _ => unreachable!(), } } diff --git a/clippy_dev/src/stderr_length_check.rs b/clippy_dev/src/stderr_length_check.rs index 6c5107aeb..ba8e5f83e 100644 --- a/clippy_dev/src/stderr_length_check.rs +++ b/clippy_dev/src/stderr_length_check.rs @@ -23,16 +23,15 @@ pub fn check() { } fn exceeding_stderr_files(files: impl Iterator) -> impl Iterator { - files - .filter_map(|file| { - let path = file.path().to_str().expect("Could not convert path to str").to_string(); - let linecount = count_linenumbers(&path); - if linecount > LIMIT { - Some(path) - } else { - None - } - }) + files.filter_map(|file| { + let path = file.path().to_str().expect("Could not convert path to str").to_string(); + let linecount = count_linenumbers(&path); + if linecount > LIMIT { + Some(path) + } else { + None + } + }) } fn stderr_files() -> impl Iterator { diff --git a/tests/fmt.rs b/tests/fmt.rs new file mode 100644 index 000000000..d7544bc50 --- /dev/null +++ b/tests/fmt.rs @@ -0,0 +1,20 @@ +#[test] +fn fmt() { + if option_env!("RUSTC_TEST_SUITE").is_some() { + return; + } + + let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let dev_dir = root_dir.join("clippy_dev"); + let output = std::process::Command::new("cargo") + .current_dir(dev_dir) + .args(&["run", "--", "fmt", "--check"]) + .output() + .unwrap(); + + println!("status: {}", output.status); + println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); + println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); + + assert!(output.status.success()); +} From 11707f3443c44c2cdfe99a0873dacf26e8681352 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 25 Jun 2019 07:30:29 +0200 Subject: [PATCH 003/133] Fix crash on `dev --limit-stderr-length` --- clippy_dev/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/main.rs b/clippy_dev/src/main.rs index 8fdc4254d..5fa7a87a5 100644 --- a/clippy_dev/src/main.rs +++ b/clippy_dev/src/main.rs @@ -77,7 +77,7 @@ fn main() { update_lints(&UpdateMode::Change); } }, - _ => unreachable!(), + _ => {}, } } From aeac3da2c1e6774d8d2f3569d064fb756b2554ae Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 26 Jun 2019 06:08:33 +0200 Subject: [PATCH 004/133] Improve fmt test failure message --- tests/fmt.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index d7544bc50..47be4ec12 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -16,5 +16,8 @@ fn fmt() { println!("stdout: {}", String::from_utf8_lossy(&output.stdout)); println!("stderr: {}", String::from_utf8_lossy(&output.stderr)); - assert!(output.status.success()); + assert!( + output.status.success(), + "Formatting check failed. Run `./util/dev fmt` to update formatting." + ); } From 503474a647c4e0c0b025d7aabbf007317410b4f2 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Wed, 3 Jul 2019 07:35:55 +0200 Subject: [PATCH 005/133] Remove format checks from CI script --- ci/base-tests.sh | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index d67541f7d..125cc898a 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -24,7 +24,6 @@ export CARGO_TARGET_DIR=`pwd`/target/ # Perform various checks for lint registration ./util/dev update_lints --check ./util/dev --limit-stderr-length -cargo +nightly fmt --all -- --check # Check running clippy-driver without cargo ( @@ -60,16 +59,6 @@ rustup override set nightly # avoid loop spam and allow cmds with exit status != 0 set +ex -# Excluding `ice-3891.rs` because the code triggers a rustc parse error which -# makes rustfmt fail. -for file in `find tests -not -path "tests/ui/crashes/ice-3891.rs" | grep "\.rs$"` ; do - rustfmt ${file} --check - if [ $? -ne 0 ]; then - echo "${file} needs reformatting!" - tests_need_reformatting="true" - fi -done - set -ex # reset if [ "${tests_need_reformatting}" == "true" ] ; then From 0c00391ed060c9184f520639bf5f51e650057d3d Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 4 Jul 2019 06:35:33 +0200 Subject: [PATCH 006/133] Remove format checks from CI scripts again. --- ci/base-tests.sh | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 125cc898a..c5d3eb3c9 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -49,22 +49,3 @@ export CARGO_TARGET_DIR=`pwd`/target/ # TODO: CLIPPY_CONF_DIR / CARGO_MANIFEST_DIR ) - -# make sure tests are formatted - -# some lints are sensitive to formatting, exclude some files -tests_need_reformatting="false" -# switch to nightly -rustup override set nightly -# avoid loop spam and allow cmds with exit status != 0 -set +ex - -set -ex # reset - -if [ "${tests_need_reformatting}" == "true" ] ; then - echo "Tests need reformatting!" - exit 2 -fi - -# switch back to master -rustup override set master From 3977843ab5592f8fb9c20f7f8436bae362234c52 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 4 Jul 2019 14:35:27 +0200 Subject: [PATCH 007/133] Update documentation to the dev fmt command --- doc/adding_lints.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 2a8ef01ba..0e73bdba1 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -345,16 +345,18 @@ list][lint_list]. ### Running rustfmt -[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according -to style guidelines. Your code has to be formatted by `rustfmt` before a PR can be merged. +[Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust +code according to style guidelines. Your code has to be formatted by `rustfmt` +before a PR can be merged. Clippy uses nightly `rustfmt` in the CI. It can be installed via `rustup`: ```bash -rustup component add rustfmt +rustup component add rustfmt --toolchain=nightly ``` -Use `cargo fmt --all` to format the whole codebase. +Use `./util/dev fmt` to format the whole codebase. Make sure that `rustfmt` is +installed for the nightly toolchain. ### Debugging @@ -371,7 +373,7 @@ Before submitting your PR make sure you followed all of the basic requirements: - [ ] `cargo test` passes locally - [ ] Executed `util/dev update_lints` - [ ] Added lint documentation -- [ ] Run `cargo fmt` +- [ ] Run `./util/dev fmt` ### Cheatsheet From c0c2a8d9c1b2d4f41ad7d61d11a0980116dc795c Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Fri, 5 Jul 2019 07:49:19 +0200 Subject: [PATCH 008/133] Work around rustup fallback error on Windows --- tests/fmt.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index 47be4ec12..2500132d7 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -8,7 +8,7 @@ fn fmt() { let dev_dir = root_dir.join("clippy_dev"); let output = std::process::Command::new("cargo") .current_dir(dev_dir) - .args(&["run", "--", "fmt", "--check"]) + .args(&["+nightly", "run", "--", "fmt", "--check"]) .output() .unwrap(); From 186b5b2ee2870c4e92b718c53e2814364845e984 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 8 Jul 2019 07:20:11 +0200 Subject: [PATCH 009/133] Add rustfmt nightly to appveyor install --- appveyor.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/appveyor.yml b/appveyor.yml index 2d8704a70..66a1c83b2 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -23,6 +23,7 @@ install: - del rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master %RUSTC_HASH% -f -n master + - rustup component add rustfmt --toolchain nightly - rustup default master - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V From 6d1aaac6c373e4781f779bddf992242abb53c7c3 Mon Sep 17 00:00:00 2001 From: Jens Hausdorf Date: Sun, 10 Mar 2019 11:06:19 +0100 Subject: [PATCH 010/133] Avoid reporting string_lit_as_bytes for long strings Port of @jens1o code ([b76f939][jens1o_commit]) Fixes #1208 [jens1o_commit]: https://github.com/jens1o/rust-clippy/commit/b76f939ac2efcfe24900c286b3b7713d972d9088 Co-authored-by: Thiago Arrais --- clippy_lints/src/strings.rs | 1 + tests/ui/string_lit_as_bytes.fixed | 5 +++-- tests/ui/string_lit_as_bytes.rs | 5 +++-- tests/ui/string_lit_as_bytes.stderr | 6 +++--- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index eae464ee2..9be2d40ba 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -173,6 +173,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { ); } else if callsite == expanded && lit_content.as_str().chars().all(|c| c.is_ascii()) + && lit_content.as_str().len() <= 32 && !in_macro_or_desugar(args[0].span) { span_lint_and_sugg( diff --git a/tests/ui/string_lit_as_bytes.fixed b/tests/ui/string_lit_as_bytes.fixed index a70504656..192247816 100644 --- a/tests/ui/string_lit_as_bytes.fixed +++ b/tests/ui/string_lit_as_bytes.fixed @@ -6,10 +6,11 @@ fn str_lit_as_bytes() { let bs = b"hello there"; - let bs = br###"raw string with three ### in it and some " ""###; + let bs = br###"raw string with 3# plus " ""###; - // no warning, because this cannot be written as a byte string literal: + // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); + let ubs = "hello there! this is a very long string".as_bytes(); let strify = stringify!(foobar).as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.rs b/tests/ui/string_lit_as_bytes.rs index ea8c71285..560cbcb65 100644 --- a/tests/ui/string_lit_as_bytes.rs +++ b/tests/ui/string_lit_as_bytes.rs @@ -6,10 +6,11 @@ fn str_lit_as_bytes() { let bs = "hello there".as_bytes(); - let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); + let bs = r###"raw string with 3# plus " ""###.as_bytes(); - // no warning, because this cannot be written as a byte string literal: + // no warning, because these cannot be written as byte string literals: let ubs = "☃".as_bytes(); + let ubs = "hello there! this is a very long string".as_bytes(); let strify = stringify!(foobar).as_bytes(); diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index f51cd71a6..59aaec75b 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -9,11 +9,11 @@ LL | let bs = "hello there".as_bytes(); error: calling `as_bytes()` on a string literal --> $DIR/string_lit_as_bytes.rs:9:14 | -LL | let bs = r###"raw string with three ### in it and some " ""###.as_bytes(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with three ### in it and some " ""###` +LL | let bs = r###"raw string with 3# plus " ""###.as_bytes(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using a byte string literal instead: `br###"raw string with 3# plus " ""###` error: calling `as_bytes()` on `include_str!(..)` - --> $DIR/string_lit_as_bytes.rs:16:22 + --> $DIR/string_lit_as_bytes.rs:17:22 | LL | let includestr = include_str!("entry.rs").as_bytes(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using `include_bytes!(..)` instead: `include_bytes!("entry.rs")` From 2fb73fe03782f1485e6e2305afa66edec7f26d83 Mon Sep 17 00:00:00 2001 From: Bara Date: Mon, 8 Jul 2019 20:45:51 +0200 Subject: [PATCH 011/133] Use empty block instead of unit type for needless return --- clippy_lints/src/returns.rs | 10 +++++----- tests/ui/needless_return.stderr | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 2245b719c..f08945b53 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -86,7 +86,7 @@ declare_clippy_lint! { #[derive(PartialEq, Eq, Copy, Clone)] enum RetReplacement { Empty, - Unit, + Block, } declare_lint_pass!(Return => [NEEDLESS_RETURN, LET_AND_RETURN, UNUSED_UNIT]); @@ -139,7 +139,7 @@ impl Return { // a match expr, check all arms ast::ExprKind::Match(_, ref arms) => { for arm in arms { - self.check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Unit); + self.check_final_expr(cx, &arm.body, Some(arm.body.span), RetReplacement::Block); } }, _ => (), @@ -176,12 +176,12 @@ impl Return { ); }); }, - RetReplacement::Unit => { + RetReplacement::Block => { span_lint_and_then(cx, NEEDLESS_RETURN, ret_span, "unneeded return statement", |db| { db.span_suggestion( ret_span, - "replace `return` with the unit type", - "()".to_string(), + "replace `return` with an empty block", + "{}".to_string(), Applicability::MachineApplicable, ); }); diff --git a/tests/ui/needless_return.stderr b/tests/ui/needless_return.stderr index 7858ecfba..ee700ab84 100644 --- a/tests/ui/needless_return.stderr +++ b/tests/ui/needless_return.stderr @@ -70,7 +70,7 @@ error: unneeded return statement --> $DIR/needless_return.rs:64:14 | LL | _ => return, - | ^^^^^^ help: replace `return` with the unit type: `()` + | ^^^^^^ help: replace `return` with an empty block: `{}` error: aborting due to 12 previous errors From 7d1a9447ea15e7b7ce845876c8850f0feed54185 Mon Sep 17 00:00:00 2001 From: Thiago Arrais Date: Mon, 8 Jul 2019 13:12:51 -0300 Subject: [PATCH 012/133] Extract semantic constant --- clippy_lints/src/strings.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 9be2d40ba..57f63a600 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -138,6 +138,9 @@ fn is_add(cx: &LateContext<'_, '_>, src: &Expr, target: &Expr) -> bool { } } +// Max length a b"foo" string can take +const MAX_LENGTH_BYTE_STRING_LIT: usize = 32; + declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { @@ -173,7 +176,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for StringLitAsBytes { ); } else if callsite == expanded && lit_content.as_str().chars().all(|c| c.is_ascii()) - && lit_content.as_str().len() <= 32 + && lit_content.as_str().len() <= MAX_LENGTH_BYTE_STRING_LIT && !in_macro_or_desugar(args[0].span) { span_lint_and_sugg( From 70cffef3b24756b46ae5bb6f590b45f0e5c02e20 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 9 Jul 2019 13:34:22 +0200 Subject: [PATCH 013/133] Disable AppVeyor builds on the master branch AppVeyor is already checked on every merge of a PR, rechecking it immediately after on the master branch is not necessary. --- appveyor.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 2d8704a70..675c16bcc 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -8,11 +8,10 @@ environment: - TARGET: x86_64-pc-windows-msvc branches: - # Only build AppVeyor on r+, try and the master branch + # Only build AppVeyor on r+ and try branch only: - auto - try - - master install: - curl -sSf -o rustup-init.exe https://win.rustup.rs/ From f831b0979e6a694c499c37570252fe787e04123c Mon Sep 17 00:00:00 2001 From: Vinzent Steinberg Date: Tue, 9 Jul 2019 14:48:48 +0200 Subject: [PATCH 014/133] cast_ptr_alignment: Mention legal use under known problems Refs #2881. --- clippy_lints/src/types.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index b674b3888..7b1d832f2 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -789,7 +789,8 @@ declare_clippy_lint! { /// **Why is this bad?** Dereferencing the resulting pointer may be undefined /// behavior. /// - /// **Known problems:** None. + /// **Known problems:** Using `std::ptr::read_unaligned` and `std::ptr::write_unaligned` or similar + /// on the resulting pointer is fine. /// /// **Example:** /// ```rust From aa72cac87a81d4a0a87d90c0e0c9f5b94d1a93f6 Mon Sep 17 00:00:00 2001 From: Florian Gilcher Date: Sat, 6 Jul 2019 11:40:14 +0200 Subject: [PATCH 015/133] Improve cast_ptr_alignment lint * print alignment in bytes in the lint message * ignore ZST left-hand types --- clippy_lints/src/types.rs | 16 ++++++++++++---- tests/ui/cast_alignment.rs | 2 ++ tests/ui/cast_alignment.stderr | 4 ++-- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 36a4b699f..b5023e268 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1210,17 +1210,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Casts { if_chain! { if let ty::RawPtr(from_ptr_ty) = &cast_from.sty; if let ty::RawPtr(to_ptr_ty) = &cast_to.sty; - if let Some(from_align) = cx.layout_of(from_ptr_ty.ty).ok().map(|a| a.align.abi); - if let Some(to_align) = cx.layout_of(to_ptr_ty.ty).ok().map(|a| a.align.abi); - if from_align < to_align; + if let Ok(from_layout) = cx.layout_of(from_ptr_ty.ty); + if let Ok(to_layout) = cx.layout_of(to_ptr_ty.ty); + if from_layout.align.abi < to_layout.align.abi; // with c_void, we inherently need to trust the user if !is_c_void(cx, from_ptr_ty.ty); + // when casting from a ZST, we don't know enough to properly lint + if !from_layout.is_zst(); then { span_lint( cx, CAST_PTR_ALIGNMENT, expr.span, - &format!("casting from `{}` to a more-strictly-aligned pointer (`{}`)", cast_from, cast_to) + &format!( + "casting from `{}` to a more-strictly-aligned pointer (`{}`) ({} < {} bytes)", + cast_from, + cast_to, + from_layout.align.abi.bytes(), + to_layout.align.abi.bytes(), + ), ); } } diff --git a/tests/ui/cast_alignment.rs b/tests/ui/cast_alignment.rs index 08450ba11..4c0893563 100644 --- a/tests/ui/cast_alignment.rs +++ b/tests/ui/cast_alignment.rs @@ -22,4 +22,6 @@ fn main() { // For c_void, we should trust the user. See #2677 (&1u32 as *const u32 as *const std::os::raw::c_void) as *const u32; (&1u32 as *const u32 as *const libc::c_void) as *const u32; + // For ZST, we should trust the user. See #4256 + (&1u32 as *const u32 as *const ()) as *const u32; } diff --git a/tests/ui/cast_alignment.stderr b/tests/ui/cast_alignment.stderr index 0077be1b5..79219f861 100644 --- a/tests/ui/cast_alignment.stderr +++ b/tests/ui/cast_alignment.stderr @@ -1,4 +1,4 @@ -error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) +error: casting from `*const u8` to a more-strictly-aligned pointer (`*const u16`) (1 < 2 bytes) --> $DIR/cast_alignment.rs:12:5 | LL | (&1u8 as *const u8) as *const u16; @@ -6,7 +6,7 @@ LL | (&1u8 as *const u8) as *const u16; | = note: `-D clippy::cast-ptr-alignment` implied by `-D warnings` -error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) +error: casting from `*mut u8` to a more-strictly-aligned pointer (`*mut u16`) (1 < 2 bytes) --> $DIR/cast_alignment.rs:13:5 | LL | (&mut 1u8 as *mut u8) as *mut u16; From a9bec0c8a6020ed61ca150f046455b309283848d Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Wed, 10 Jul 2019 01:57:25 +0800 Subject: [PATCH 016/133] Ignore generated fresh lifetimes in elision check. --- clippy_lints/src/lifetimes.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index dbdb3c519..47cced9d9 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -283,6 +283,8 @@ impl<'v, 't> RefVisitor<'v, 't> { if let Some(ref lt) = *lifetime { if lt.name == LifetimeName::Static { self.lts.push(RefLt::Static); + } else if let LifetimeName::Param(ParamName::Fresh(_)) = lt.name { + // Fresh lifetimes generated should be ignored. } else if lt.is_elided() { self.lts.push(RefLt::Unnamed); } else { From 2c90083f6294f901e2e8b5640cc084feb02431ee Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 11 Jul 2019 05:21:44 +0000 Subject: [PATCH 017/133] Avoid rustfmt bug on Windows --- clippy_dev/src/fmt.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 72f8d836e..5ccdbec14 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -44,7 +44,11 @@ pub fn run(check: bool, verbose: bool) { let entry = entry?; let path = entry.path(); - if path.extension() != Some("rs".as_ref()) || entry.file_name() == "ice-3891.rs" { + if path.extension() != Some("rs".as_ref()) + || entry.file_name() == "ice-3891.rs" + // Avoid rustfmt bug rust-lang/rustfmt#1873 + || cfg!(windows) && entry.file_name() == "implicit_hasher.rs" + { continue; } From de7749832c5806de67011baa1264982308c73104 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 11 Jul 2019 08:47:05 +0200 Subject: [PATCH 018/133] Fix bug in `implicit_hasher` causing crashes Skip linting if the type is from an external macro. Closes #4260. --- clippy_lints/src/types.rs | 3 +++ tests/ui/auxiliary/implicit_hasher_macros.rs | 6 ++++++ tests/ui/implicit_hasher.rs | 7 +++++++ tests/ui/implicit_hasher.stderr | 20 ++++++++++---------- 4 files changed, 26 insertions(+), 10 deletions(-) create mode 100644 tests/ui/auxiliary/implicit_hasher_macros.rs diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index dd578176f..5a372cd04 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -2038,6 +2038,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitHasher { vis.visit_ty(ty); for target in &vis.found { + if in_external_macro(cx.sess(), generics.span) { + continue; + } let generics_suggestion_span = generics.span.substitute_dummy({ let pos = snippet_opt(cx, item.span.until(body.arguments[0].pat.span)) .and_then(|snip| { diff --git a/tests/ui/auxiliary/implicit_hasher_macros.rs b/tests/ui/auxiliary/implicit_hasher_macros.rs new file mode 100644 index 000000000..1eb77c531 --- /dev/null +++ b/tests/ui/auxiliary/implicit_hasher_macros.rs @@ -0,0 +1,6 @@ +#[macro_export] +macro_rules! implicit_hasher_fn { + () => { + pub fn f(input: &HashMap) {} + }; +} diff --git a/tests/ui/implicit_hasher.rs b/tests/ui/implicit_hasher.rs index 064760e73..c0ffa6879 100644 --- a/tests/ui/implicit_hasher.rs +++ b/tests/ui/implicit_hasher.rs @@ -1,5 +1,9 @@ +// aux-build:implicit_hasher_macros.rs #![allow(unused)] +#[macro_use] +extern crate implicit_hasher_macros; + use std::cmp::Eq; use std::collections::{HashMap, HashSet}; use std::hash::{BuildHasher, Hash}; @@ -88,4 +92,7 @@ gen!(fn bar); pub mod test_macro; __implicit_hasher_test_macro!(impl for HashMap where V: test_macro::A); +// #4260 +implicit_hasher_fn!(); + fn main() {} diff --git a/tests/ui/implicit_hasher.stderr b/tests/ui/implicit_hasher.stderr index 68e305f0c..a3bc08afd 100644 --- a/tests/ui/implicit_hasher.stderr +++ b/tests/ui/implicit_hasher.stderr @@ -1,5 +1,5 @@ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:11:35 + --> $DIR/implicit_hasher.rs:15:35 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ @@ -15,7 +15,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:20:36 + --> $DIR/implicit_hasher.rs:24:36 | LL | impl Foo for (HashMap,) { | ^^^^^^^^^^^^^ @@ -29,7 +29,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:25:19 + --> $DIR/implicit_hasher.rs:29:19 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,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:42:32 + --> $DIR/implicit_hasher.rs:46:32 | LL | impl Foo for HashSet { | ^^^^^^^^^^ @@ -57,7 +57,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:47:19 + --> $DIR/implicit_hasher.rs:51:19 | LL | impl Foo for HashSet { | ^^^^^^^^^^^^^^^ @@ -71,7 +71,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:64:23 + --> $DIR/implicit_hasher.rs:68:23 | LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ @@ -81,7 +81,7 @@ LL | pub fn foo(_map: &mut HashMap, _s | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^ error: parameter of type `HashSet` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:64:53 + --> $DIR/implicit_hasher.rs:68:53 | LL | pub fn foo(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ @@ -91,7 +91,7 @@ LL | pub fn foo(_map: &mut HashMap, _set: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ error: impl for `HashMap` should be generalized over different hashers - --> $DIR/implicit_hasher.rs:68:43 + --> $DIR/implicit_hasher.rs:72:43 | LL | impl Foo for HashMap { | ^^^^^^^^^^^^^ @@ -108,7 +108,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:76:33 + --> $DIR/implicit_hasher.rs:80:33 | LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^^^^^^ @@ -121,7 +121,7 @@ LL | pub fn $name(_map: &mut HashMap $DIR/implicit_hasher.rs:76:63 + --> $DIR/implicit_hasher.rs:80:63 | LL | pub fn $name(_map: &mut HashMap, _set: &mut HashSet) {} | ^^^^^^^^^^^^ From 27c53487937ffbd7a67aad4511a5d72f637b9ebb Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 11 Jul 2019 21:45:34 +0700 Subject: [PATCH 019/133] Rustup `macro expansion and resolution` --- clippy_lints/src/misc.rs | 14 +++++++++----- clippy_lints/src/returns.rs | 2 +- clippy_lints/src/types.rs | 4 ++-- clippy_lints/src/utils/mod.rs | 8 ++++---- 4 files changed, 16 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index d77f71c2a..acca50e3d 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -7,7 +7,7 @@ use rustc::ty; use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; use syntax::ast::LitKind; -use syntax::source_map::{ExpnFormat, Span}; +use syntax::source_map::{ExpnKind, Span}; use crate::consts::{constant, Constant}; use crate::utils::sugg::Sugg; @@ -596,10 +596,14 @@ fn is_used(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { /// Tests whether an expression is in a macro expansion (e.g., something /// generated by `#[derive(...)]` or the like). fn in_attributes_expansion(expr: &Expr) -> bool { - expr.span - .ctxt() - .outer_expn_info() - .map_or(false, |info| matches!(info.format, ExpnFormat::MacroAttribute(_))) + use syntax::ext::hygiene::MacroKind; + expr.span.ctxt().outer_expn_info().map_or(false, |info| { + if let ExpnKind::Macro(MacroKind::Attr, _) = info.kind { + true + } else { + false + } + }) } /// Tests whether `res` is a variable defined outside a macro. diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index f08945b53..0f2084e81 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -317,7 +317,7 @@ fn attr_is_cfg(attr: &ast::Attribute) -> bool { // get the def site fn get_def(span: Span) -> Option { - span.ctxt().outer_expn_info().and_then(|info| info.def_site) + span.ctxt().outer_expn_info().and_then(|info| Some(info.def_site)) } // is this expr a `()` unit? diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index dd578176f..4f3533729 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -621,9 +621,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnitArg { } fn is_questionmark_desugar_marked_call(expr: &Expr) -> bool { - use syntax_pos::hygiene::CompilerDesugaringKind; + use syntax_pos::hygiene::DesugaringKind; if let ExprKind::Call(ref callee, _) = expr.node { - callee.span.is_compiler_desugaring(CompilerDesugaringKind::QuestionMark) + callee.span.is_desugaring(DesugaringKind::QuestionMark) } else { false } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index 53665506c..9e45c453a 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -43,7 +43,7 @@ use rustc_errors::Applicability; use smallvec::SmallVec; use syntax::ast::{self, LitKind}; use syntax::attr; -use syntax::ext::hygiene::ExpnFormat; +use syntax::ext::hygiene::ExpnKind; use syntax::source_map::{Span, DUMMY_SP}; use syntax::symbol::{kw, Symbol}; @@ -100,7 +100,7 @@ pub fn in_macro_or_desugar(span: Span) -> bool { /// Returns `true` if this `expn_info` was expanded by any macro. pub fn in_macro(span: Span) -> bool { if let Some(info) = span.ctxt().outer_expn_info() { - if let ExpnFormat::CompilerDesugaring(..) = info.format { + if let ExpnKind::Desugaring(..) = info.kind { false } else { true @@ -686,7 +686,7 @@ pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool { /// See also `is_direct_expn_of`. pub fn is_expn_of(mut span: Span, name: &str) -> Option { loop { - let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.format.name(), ei.call_site)); + let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.kind.descr(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name.as_str() == name => return Some(new_span), @@ -706,7 +706,7 @@ pub fn is_expn_of(mut span: Span, name: &str) -> Option { /// `bar!` by /// `is_direct_expn_of`. pub fn is_direct_expn_of(span: Span, name: &str) -> Option { - let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.format.name(), ei.call_site)); + let span_name_span = span.ctxt().outer_expn_info().map(|ei| (ei.kind.descr(), ei.call_site)); match span_name_span { Some((mac_name, new_span)) if mac_name.as_str() == name => Some(new_span), From bd2c76824de8c22b1ed7a4f8d693143538f7a9ec Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 9 Nov 2018 07:13:34 +0100 Subject: [PATCH 020/133] Stop allowing failures in Travis windows build --- .travis.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index ee990111a..2d1d363d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -81,9 +81,6 @@ matrix: if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=chronotope/chrono if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - allow_failures: - - os: windows - env: CARGO_INCREMENTAL=0 BASE_TESTS=true # prevent these jobs with default env vars exclude: - os: linux From ac6e52a91c1baf8eaaaf1fedcae6267fb16128fd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 28 Nov 2018 07:29:05 +0100 Subject: [PATCH 021/133] Change conditional Maybe uname == Linux was true on the windows VM? This could be a way to avoid the secret environment variable issue with Travis CI. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2d1d363d0..2e8e205d4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -101,7 +101,7 @@ script: after_success: | #!/bin/bash - if [ $(uname) == Linux ]; then + if [ "$TRAVIS_OS_NAME" == "linux" ]; then set -ex if [ -z ${INTEGRATION} ]; then ./.github/deploy.sh From 2991f31c171f88e9feeb3e4fea157d89edb41dd4 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 12 Jul 2019 10:58:06 +0200 Subject: [PATCH 022/133] Add master toolchain binaries to the PATH --- .travis.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 2e8e205d4..b2ad9d5b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -91,7 +91,11 @@ script: - | rm rust-toolchain ./setup-toolchain.sh - export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib + if [ "$TRAVIS_OS_NAME" == "windows" ]; then + export PATH=$PATH:$(rustc --print sysroot)/bin + else + export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib + fi - | if [ -z ${INTEGRATION} ]; then travis_wait 30 ./ci/base-tests.sh && sleep 5 From 6b8ebcc0c8a441a7f871cab1b69c2433be42d5e2 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 12 Jul 2019 12:12:53 +0200 Subject: [PATCH 023/133] Don't re-set the LD_LIBRARY_PATH in base_tests.sh --- ci/base-tests.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/ci/base-tests.sh b/ci/base-tests.sh index c5d3eb3c9..34bc9a8ec 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -27,8 +27,6 @@ export CARGO_TARGET_DIR=`pwd`/target/ # Check running clippy-driver without cargo ( - export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib - # Check sysroot handling sysroot=$(./target/debug/clippy-driver --print sysroot) test $sysroot = $(rustc --print sysroot) From c100c70822aa960aa9ee0abff002ce313403e902 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 12 Jul 2019 14:13:15 +0200 Subject: [PATCH 024/133] Build sys_root in driver with PathBuf instead of String --- src/driver.rs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index e6b04bf0c..545c43f9a 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -12,7 +12,7 @@ extern crate rustc_plugin; use rustc_interface::interface; use rustc_tools_util::*; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::process::{exit, Command}; mod lintlist; @@ -270,12 +270,19 @@ pub fn main() { let sys_root_arg = arg_value(&orig_args, "--sysroot", |_| true); let have_sys_root_arg = sys_root_arg.is_some(); let sys_root = sys_root_arg - .map(std::string::ToString::to_string) - .or_else(|| std::env::var("SYSROOT").ok()) + .map(PathBuf::from) + .or_else(|| std::env::var("SYSROOT").ok().map(PathBuf::from)) .or_else(|| { let home = option_env!("RUSTUP_HOME").or(option_env!("MULTIRUST_HOME")); let toolchain = option_env!("RUSTUP_TOOLCHAIN").or(option_env!("MULTIRUST_TOOLCHAIN")); - home.and_then(|home| toolchain.map(|toolchain| format!("{}/toolchains/{}", home, toolchain))) + home.and_then(|home| { + toolchain.map(|toolchain| { + let mut path = PathBuf::from(home); + path.push("toolchains"); + path.push(toolchain); + path + }) + }) }) .or_else(|| { Command::new("rustc") @@ -284,9 +291,10 @@ pub fn main() { .output() .ok() .and_then(|out| String::from_utf8(out.stdout).ok()) - .map(|s| s.trim().to_owned()) + .map(|s| PathBuf::from(s.trim())) }) - .or_else(|| option_env!("SYSROOT").map(String::from)) + .or_else(|| option_env!("SYSROOT").map(PathBuf::from)) + .map(|pb| pb.to_string_lossy().to_string()) .expect("need to specify SYSROOT env var during clippy compilation, or use rustup or multirust"); // Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument. From 4817c2c38139b4bac85f201e93cb718d4f04e9d1 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 13 Jul 2019 11:42:44 +0200 Subject: [PATCH 025/133] Test with different sysroots dependent on the OS --- .travis.yml | 2 +- ci/base-tests.sh | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b2ad9d5b7..3f7c856a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ matrix: - os: linux env: BASE_TESTS=true - os: windows - env: CARGO_INCREMENTAL=0 BASE_TESTS=true + env: CARGO_INCREMENTAL=0 BASE_TESTS=true OS_WINDOWS=true # Builds that are only executed when a PR is r+ed or a try build is started # We don't want to run these always because they go towards diff --git a/ci/base-tests.sh b/ci/base-tests.sh index 34bc9a8ec..a53a0ea52 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -31,11 +31,16 @@ export CARGO_TARGET_DIR=`pwd`/target/ sysroot=$(./target/debug/clippy-driver --print sysroot) test $sysroot = $(rustc --print sysroot) - sysroot=$(./target/debug/clippy-driver --sysroot /tmp --print sysroot) - test $sysroot = /tmp + if [ -z $OS_WINDOWS ]; then + desired_sysroot=/tmp + else + desired_sysroot=C:/tmp + fi + sysroot=$(./target/debug/clippy-driver --sysroot $desired_sysroot --print sysroot) + test $sysroot = $desired_sysroot - sysroot=$(SYSROOT=/tmp ./target/debug/clippy-driver --print sysroot) - test $sysroot = /tmp + sysroot=$(SYSROOT=$desired_sysroot ./target/debug/clippy-driver --print sysroot) + test $sysroot = $desired_sysroot # Make sure this isn't set - clippy-driver should cope without it unset CARGO_MANIFEST_DIR From 876a7e1f01cb14a63eee54cb44524a87161d5454 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 13 Jul 2019 13:26:26 +0200 Subject: [PATCH 026/133] Remove `CARGO_INCREMENTAL=0` from windows build --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 3f7c856a7..eb3d4803b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ matrix: - os: linux env: BASE_TESTS=true - os: windows - env: CARGO_INCREMENTAL=0 BASE_TESTS=true OS_WINDOWS=true + env: BASE_TESTS=true OS_WINDOWS=true # Builds that are only executed when a PR is r+ed or a try build is started # We don't want to run these always because they go towards From 625051d3e7d3a3f1f9d7ac9818b10ed93eb31481 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 14 Jul 2019 15:13:47 +0200 Subject: [PATCH 027/133] Revert "Remove `CARGO_INCREMENTAL=0` from windows build" This reverts commit 876a7e1f01cb14a63eee54cb44524a87161d5454. Using incremental build on windows increases the build time on travis by about 8 minutes. --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index eb3d4803b..3f7c856a7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -45,7 +45,7 @@ matrix: - os: linux env: BASE_TESTS=true - os: windows - env: BASE_TESTS=true OS_WINDOWS=true + env: CARGO_INCREMENTAL=0 BASE_TESTS=true OS_WINDOWS=true # Builds that are only executed when a PR is r+ed or a try build is started # We don't want to run these always because they go towards From ce2a7b0160ea8220249d73a386edd0ca85015f66 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sun, 14 Jul 2019 15:21:50 +0200 Subject: [PATCH 028/133] Disable dogfood on windows for faster build time on travis --- tests/dogfood.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/dogfood.rs b/tests/dogfood.rs index 4153c9ef0..1f03ba395 100644 --- a/tests/dogfood.rs +++ b/tests/dogfood.rs @@ -1,6 +1,6 @@ #[test] fn dogfood() { - if option_env!("RUSTC_TEST_SUITE").is_some() { + if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; } let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -30,7 +30,7 @@ fn dogfood() { #[test] fn dogfood_tests() { - if option_env!("RUSTC_TEST_SUITE").is_some() { + if option_env!("RUSTC_TEST_SUITE").is_some() || cfg!(windows) { return; } let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); From b523d35d41c51bff255fd038b0d6acb695e42060 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 15 Jul 2019 07:35:02 +0200 Subject: [PATCH 029/133] Deny warnings in CI --- Cargo.toml | 1 + ci/base-tests.sh | 4 ++-- clippy_lints/src/lib.rs | 1 + src/driver.rs | 1 + src/main.rs | 2 ++ 5 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index f68251adb..8c70bb189 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,4 +61,5 @@ rustc-workspace-hack = "1.0.0" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} [features] +deny-warnings = [] debugging = [] diff --git a/ci/base-tests.sh b/ci/base-tests.sh index c5d3eb3c9..71f3d3830 100755 --- a/ci/base-tests.sh +++ b/ci/base-tests.sh @@ -7,8 +7,8 @@ if [ "$TRAVIS_OS_NAME" == "linux" ]; then remark -f *.md -f doc/*.md > /dev/null fi # build clippy in debug mode and run tests -cargo build --features debugging -cargo test --features debugging +cargo build --features "debugging deny-warnings" +cargo test --features "debugging deny-warnings" # for faster build, share target dir between subcrates export CARGO_TARGET_DIR=`pwd`/target/ (cd clippy_lints && cargo test) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 0d2c9e6b9..369a736aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -9,6 +9,7 @@ #![recursion_limit = "512"] #![warn(rust_2018_idioms, trivial_casts, trivial_numeric_casts)] #![deny(rustc::internal)] +#![cfg_attr(feature = "deny-warnings", deny(warnings))] #![feature(crate_visibility_modifier)] #![feature(concat_idents)] diff --git a/src/driver.rs b/src/driver.rs index e6b04bf0c..cd358ff35 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -1,3 +1,4 @@ +#![cfg_attr(feature = "deny-warnings", deny(warnings))] #![feature(rustc_private)] // FIXME: switch to something more ergonomic here, once available. diff --git a/src/main.rs b/src/main.rs index e0b2bcc72..8f9afb953 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,5 @@ +#![cfg_attr(feature = "deny-warnings", deny(warnings))] + use rustc_tools_util::*; const CARGO_CLIPPY_HELP: &str = r#"Checks a package to catch common mistakes and improve your Rust code. From 6c067bf50eeb503aa4781ffafc77496b5c260ba3 Mon Sep 17 00:00:00 2001 From: daxpedda <1645124+daxpedda@users.noreply.github.com> Date: Mon, 15 Jul 2019 16:02:50 +0200 Subject: [PATCH 030/133] false positives fixes of `implicit_return` - Handle returning macro statements properly - Handle functions that return never type - Handle functions that panic but do not return never type --- clippy_lints/src/implicit_return.rs | 171 +++++++++++++++++----------- tests/ui/implicit_return.rs | 14 +++ tests/ui/implicit_return.stderr | 34 ++++-- 3 files changed, 140 insertions(+), 79 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index e280ce4c8..409a10f82 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -1,9 +1,16 @@ -use crate::utils::{in_macro_or_desugar, is_expn_of, snippet_opt, span_lint_and_then}; -use rustc::hir::{intravisit::FnKind, Body, ExprKind, FnDecl, HirId, MatchSource}; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_lint_pass, declare_tool_lint}; +use crate::utils::{ + in_macro_or_desugar, match_def_path, + paths::{BEGIN_PANIC, BEGIN_PANIC_FMT}, + resolve_node, snippet_opt, span_lint_and_then, +}; +use if_chain::if_chain; +use rustc::{ + declare_lint_pass, declare_tool_lint, + hir::{intravisit::FnKind, Body, Expr, ExprKind, FnDecl, HirId, MatchSource, StmtKind}, + lint::{LateContext, LateLintPass, LintArray, LintPass}, +}; use rustc_errors::Applicability; -use syntax::source_map::Span; +use syntax_pos::Span; declare_clippy_lint! { /// **What it does:** Checks for missing return statements at the end of a block. @@ -35,71 +42,98 @@ declare_clippy_lint! { declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]); -impl ImplicitReturn { - fn lint(cx: &LateContext<'_, '_>, outer_span: syntax_pos::Span, inner_span: syntax_pos::Span, msg: &str) { - span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| { - if let Some(snippet) = snippet_opt(cx, inner_span) { - db.span_suggestion( - outer_span, - msg, - format!("return {}", snippet), - Applicability::MachineApplicable, +fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) { + let outer_span = span_to_outer_expn(outer_span); + let inner_span = span_to_outer_expn(inner_span); + + span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| { + if let Some(snippet) = snippet_opt(cx, inner_span) { + db.span_suggestion( + outer_span, + msg, + format!("return {}", snippet), + Applicability::MachineApplicable, + ); + } + }); +} + +fn span_to_outer_expn(span: Span) -> Span { + if let Some(expr) = span.ctxt().outer_expn_info() { + span_to_outer_expn(expr.call_site) + } else { + span + } +} + +fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) { + match &expr.node { + // loops could be using `break` instead of `return` + ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => { + if let Some(expr) = &block.expr { + expr_match(cx, expr, ret_ty_is_never); + } + // only needed in the case of `break` with `;` at the end + else if let Some(stmt) = block.stmts.last() { + if_chain! { + if let StmtKind::Semi(expr, ..) = &stmt.node; + // make sure it's a break, otherwise we want to skip + if let ExprKind::Break(.., break_expr) = &expr.node; + if let Some(break_expr) = break_expr; + then { + lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); + } + } + } + }, + // use `return` instead of `break` + ExprKind::Break(.., break_expr) => { + if let Some(break_expr) = break_expr { + lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); + } + }, + ExprKind::Match(.., arms, source) => { + let check_all_arms = match source { + MatchSource::IfLetDesugar { + contains_else_clause: has_else, + } => *has_else, + _ => true, + }; + + if check_all_arms { + for arm in arms { + expr_match(cx, &arm.body, ret_ty_is_never); + } + } else { + expr_match( + cx, + &arms.first().expect("if let doesn't have a single arm").body, + ret_ty_is_never, ); } - }); - } - - fn expr_match(cx: &LateContext<'_, '_>, expr: &rustc::hir::Expr) { - match &expr.node { - // loops could be using `break` instead of `return` - ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => { - if let Some(expr) = &block.expr { - Self::expr_match(cx, expr); - } - // only needed in the case of `break` with `;` at the end - else if let Some(stmt) = block.stmts.last() { - if let rustc::hir::StmtKind::Semi(expr, ..) = &stmt.node { - // make sure it's a break, otherwise we want to skip - if let ExprKind::Break(.., break_expr) = &expr.node { - if let Some(break_expr) = break_expr { - Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); - } - } + }, + // skip if it already has a return statement + ExprKind::Ret(..) => (), + // make sure it's not a call that panics unless we intend to return a panic + ExprKind::Call(expr, ..) => { + if_chain! { + if let ExprKind::Path(qpath) = &expr.node; + if let Some(path_def_id) = resolve_node(cx, qpath, expr.hir_id).opt_def_id(); + if match_def_path(cx, path_def_id, &BEGIN_PANIC) || + match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT); + then { + // only put `return` on panics if the return type of the function/closure is a panic + if ret_ty_is_never { + lint(cx, expr.span, expr.span, "add `return` as shown") } } - }, - // use `return` instead of `break` - ExprKind::Break(.., break_expr) => { - if let Some(break_expr) = break_expr { - Self::lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); + else { + lint(cx, expr.span, expr.span, "add `return` as shown") } - }, - ExprKind::Match(.., arms, source) => { - let check_all_arms = match source { - MatchSource::IfLetDesugar { - contains_else_clause: has_else, - } => *has_else, - _ => true, - }; - - if check_all_arms { - for arm in arms { - Self::expr_match(cx, &arm.body); - } - } else { - Self::expr_match(cx, &arms.first().expect("if let doesn't have a single arm").body); - } - }, - // skip if it already has a return statement - ExprKind::Ret(..) => (), - // everything else is missing `return` - _ => { - // make sure it's not just an unreachable expression - if is_expn_of(expr.span, "unreachable").is_none() { - Self::lint(cx, expr.span, expr.span, "add `return` as shown") - } - }, - } + } + }, + // everything else is missing `return` + _ => lint(cx, expr.span, expr.span, "add `return` as shown"), } } @@ -110,16 +144,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { _: FnKind<'tcx>, _: &'tcx FnDecl, body: &'tcx Body, - span: Span, + span: syntax::source_map::Span, _: HirId, ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); + let ret_ty = mir.return_ty(); // checking return type through MIR, HIR is not able to determine inferred closure return types // make sure it's not a macro - if !mir.return_ty().is_unit() && !in_macro_or_desugar(span) { - Self::expr_match(cx, &body.value); + if !ret_ty.is_unit() && !in_macro_or_desugar(span) { + expr_match(cx, &body.value, ret_ty.is_never()); } } } diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index d1c63ca16..ade3dc00a 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -5,6 +5,7 @@ fn test_end_of_fn() -> bool { // no error! return true; } + true } @@ -76,6 +77,18 @@ fn test_closure() { let _ = || true; } +fn test_return_never() -> ! { + panic!() +} + +fn test_panic() -> bool { + panic!() +} + +fn test_return_macro() -> String { + format!("test {}", "test") +} + fn main() { let _ = test_end_of_fn(); let _ = test_if_block(); @@ -86,4 +99,5 @@ fn main() { let _ = test_loop_with_nests(); let _ = test_loop_with_if_let(); test_closure(); + let _ = test_return_macro(); } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index 98b588f1a..ac6a76cd3 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -1,5 +1,5 @@ error: missing return statement - --> $DIR/implicit_return.rs:8:5 + --> $DIR/implicit_return.rs:9:5 | LL | true | ^^^^ help: add `return` as shown: `return true` @@ -7,58 +7,70 @@ LL | true = note: `-D clippy::implicit-return` implied by `-D warnings` error: missing return statement - --> $DIR/implicit_return.rs:14:9 + --> $DIR/implicit_return.rs:15:9 | LL | true | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:16:9 + --> $DIR/implicit_return.rs:17:9 | LL | false | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:24:17 + --> $DIR/implicit_return.rs:25:17 | LL | true => false, | ^^^^^ help: add `return` as shown: `return false` error: missing return statement - --> $DIR/implicit_return.rs:25:20 + --> $DIR/implicit_return.rs:26:20 | LL | false => { true }, | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:40:9 + --> $DIR/implicit_return.rs:41:9 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:48:13 + --> $DIR/implicit_return.rs:49:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:57:13 + --> $DIR/implicit_return.rs:58:13 | LL | break true; | ^^^^^^^^^^ help: change `break` to `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:75:18 + --> $DIR/implicit_return.rs:76:18 | LL | let _ = || { true }; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:76:16 + --> $DIR/implicit_return.rs:77:16 | LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` -error: aborting due to 10 previous errors +error: missing return statement + --> $DIR/implicit_return.rs:81:5 + | +LL | panic!() + | ^^^^^^^^ help: add `return` as shown: `return panic!()` + +error: missing return statement + --> $DIR/implicit_return.rs:89:5 + | +LL | format!("test {}", "test") + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")` + +error: aborting due to 12 previous errors From a0f6c9361b6ad653ebee27b73d63cb966be33d40 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 25 Apr 2019 15:45:52 +0200 Subject: [PATCH 031/133] Check PRs for changelog entry in the body --- .travis.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.travis.yml b/.travis.yml index 3f7c856a7..ba8fad5f3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -88,6 +88,19 @@ matrix: - os: windows script: + - | + if [ "$TRAVIS_BRANCH" == "auto" ] || [ "$TRAVIS_BRANCH" == "try" ]; then + output=$(curl -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$TRAVIS_PULL_REQUEST" | \ + python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ + grep "changelog: " | \ + sed "s/changelog: //g") + if [ -z "$output" ]; then + echo "ERROR: PR body must contain 'changelog: ...'" + exit 1 + elif [ "$output" = "none" ]; then + echo "WARNING: changelog is 'none'" + fi + fi - | rm rust-toolchain ./setup-toolchain.sh From cb6cec5695eff8ed58139b87075c0f05278d28e6 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 25 Apr 2019 17:08:20 +0200 Subject: [PATCH 032/133] Authenticate with github_api_token --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ba8fad5f3..6629f92a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -17,6 +17,7 @@ branches: env: global: - RUST_BACKTRACE=1 + - secure: "OKulfkA5OGd/d1IhvBKzRkHQwMcWjzrzbimo7+5NhkUkWxndAzl+719TB3wWvIh1i2wXXrEXsyZkXM5FtRrHm55v1VKQ5ibjEvFg1w3NIg81iDyoLq186fLqywvxGkOAFPrsePPsBj5USd5xvhwwbrjO6L7/RK6Z8shBwOSc41s=" install: - | @@ -90,7 +91,7 @@ matrix: script: - | if [ "$TRAVIS_BRANCH" == "auto" ] || [ "$TRAVIS_BRANCH" == "try" ]; then - output=$(curl -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$TRAVIS_PULL_REQUEST" | \ + output=$(curl -H "Authorization: token $GITHUB_API_TOKEN" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$TRAVIS_PULL_REQUEST" | \ python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ grep "changelog: " | \ sed "s/changelog: //g") From 61ca901e51be911ccc0664ffcfb908f8f477658b Mon Sep 17 00:00:00 2001 From: flip1995 Date: Sat, 15 Jun 2019 13:54:46 +0200 Subject: [PATCH 033/133] Get PR number from bors commit message --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6629f92a0..12c9f512f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -91,7 +91,8 @@ matrix: script: - | if [ "$TRAVIS_BRANCH" == "auto" ] || [ "$TRAVIS_BRANCH" == "try" ]; then - output=$(curl -H "Authorization: token $GITHUB_API_TOKEN" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$TRAVIS_PULL_REQUEST" | \ + pr=$(echo $TRAVIS_COMMIT_MESSAGE | grep -o "#[0-9]*" | head -1 | sed 's/^#//g') + output=$(curl -H "Authorization: token $GITHUB_API_TOKEN" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$pr" | \ python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ grep "changelog: " | \ sed "s/changelog: //g") From 1c87df486e44f46ef1860b497e9cc538bae09545 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 18 Jun 2019 12:14:02 +0200 Subject: [PATCH 034/133] grep only lines, that start with 'changelog: ' --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 12c9f512f..0a1bd0ea2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -94,7 +94,7 @@ script: pr=$(echo $TRAVIS_COMMIT_MESSAGE | grep -o "#[0-9]*" | head -1 | sed 's/^#//g') output=$(curl -H "Authorization: token $GITHUB_API_TOKEN" -s "https://api.github.com/repos/rust-lang/rust-clippy/pulls/$pr" | \ python -c "import sys, json; print(json.load(sys.stdin)['body'])" | \ - grep "changelog: " | \ + grep "^changelog: " | \ sed "s/changelog: //g") if [ -z "$output" ]; then echo "ERROR: PR body must contain 'changelog: ...'" From 8adbf7f2c1845cd8a23e1209eef7a0df34137f5a Mon Sep 17 00:00:00 2001 From: Jerry Hardee Date: Mon, 15 Jul 2019 12:46:58 -0500 Subject: [PATCH 035/133] Fix float_cmp false positive when comparing signum f1.signum() == f2.signum() f1.signum() != f2.signum() should not trigger a warning. --- clippy_lints/src/misc.rs | 27 +++++++++++++++++++++++++++ tests/ui/float_cmp.rs | 19 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index acca50e3d..04c0983db 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -364,6 +364,12 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MiscLints { if is_allowed(cx, left) || is_allowed(cx, right) { return; } + + // Allow comparing the results of signum() + if is_signum(cx, left) && is_signum(cx, right) { + return; + } + if let Some(name) = get_item_name(cx, expr) { let name = name.as_str(); if name == "eq" @@ -493,6 +499,27 @@ fn is_allowed<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) -> bool { } } +// Return true if `expr` is the result of `signum()` invoked on a float value. +fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { + // The negation of a signum is still a signum + if let ExprKind::Unary(UnNeg, ref child_expr) = expr.node { + return is_signum(cx, &child_expr); + } + + if_chain! { + if let ExprKind::MethodCall(ref method_name, _, ref expressions) = expr.node; + if sym!(signum) == method_name.ident.name; + // Check that the receiver of the signum() is a float (expressions[0] is the receiver of + // the method call) + if is_float(cx, &expressions[0]); + then { + true + } else { + false + } + } +} + fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { matches!(walk_ptrs_ty(cx.tables.expr_ty(expr)).sty, ty::Float(_)) } diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 92d38527b..1ec8af3e3 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -77,4 +77,23 @@ fn main() { let b: *const f32 = xs.as_ptr(); assert_eq!(a, b); // no errors + + // no errors - comparing signums is ok + let x32 = 3.21f32; + 1.23f32.signum() == x32.signum(); + 1.23f32.signum() == -(x32.signum()); + 1.23f32.signum() == 3.21f32.signum(); + + 1.23f32.signum() != x32.signum(); + 1.23f32.signum() != -(x32.signum()); + 1.23f32.signum() != 3.21f32.signum(); + + let x64 = 3.21f64; + 1.23f64.signum() == x64.signum(); + 1.23f64.signum() == -(x64.signum()); + 1.23f64.signum() == 3.21f64.signum(); + + 1.23f64.signum() != x64.signum(); + 1.23f64.signum() != -(x64.signum()); + 1.23f64.signum() != 3.21f64.signum(); } From 8a8eedf388a1613c5a084caa4c52ec520672576e Mon Sep 17 00:00:00 2001 From: Jerry Hardee Date: Mon, 15 Jul 2019 14:00:07 -0500 Subject: [PATCH 036/133] Lint --- clippy_lints/src/misc.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index 04c0983db..d89f886a3 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -511,13 +511,11 @@ fn is_signum(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { if sym!(signum) == method_name.ident.name; // Check that the receiver of the signum() is a float (expressions[0] is the receiver of // the method call) - if is_float(cx, &expressions[0]); then { - true - } else { - false + return is_float(cx, &expressions[0]); } } + false } fn is_float(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { From 33010ae7e60322a1f8b3db824c90fea79def5ae7 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Jul 2019 07:30:23 +0200 Subject: [PATCH 037/133] UI Test Cleanup: Split out out_of_bounds_indexing This moves the `out_of_bounds_indexing` lint tests to their own directory. --- tests/ui/indexing_slicing.rs | 36 +--- tests/ui/indexing_slicing.stderr | 156 ++++-------------- .../ui/out_of_bounds_indexing/empty_array.rs | 19 +++ .../out_of_bounds_indexing/empty_array.stderr | 54 ++++++ tests/ui/out_of_bounds_indexing/issue-3102.rs | 10 ++ .../out_of_bounds_indexing/issue-3102.stderr | 30 ++++ tests/ui/out_of_bounds_indexing/simple.rs | 22 +++ tests/ui/out_of_bounds_indexing/simple.stderr | 40 +++++ 8 files changed, 209 insertions(+), 158 deletions(-) create mode 100644 tests/ui/out_of_bounds_indexing/empty_array.rs create mode 100644 tests/ui/out_of_bounds_indexing/empty_array.stderr create mode 100644 tests/ui/out_of_bounds_indexing/issue-3102.rs create mode 100644 tests/ui/out_of_bounds_indexing/issue-3102.stderr create mode 100644 tests/ui/out_of_bounds_indexing/simple.rs create mode 100644 tests/ui/out_of_bounds_indexing/simple.stderr diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index f0bd39c02..bce6606b0 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -1,5 +1,8 @@ #![feature(plugin)] #![warn(clippy::indexing_slicing)] + +// We also check the out_of_bounds_indexing lint here, because it lints similar things and +// we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] #![allow(clippy::no_effect, clippy::unnecessary_operation)] @@ -15,21 +18,10 @@ fn main() { &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - &x[..=4]; - &x[1..5]; - &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. - &x[5..]; - &x[..5]; - &x[5..].iter().map(|x| 2 * x).collect::>(); - &x[0..=4]; + &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and another for slicing [..10]. &x[0..][..3]; &x[1..][..5]; - &x[4..]; // Ok, should not produce stderr. - &x[..4]; // Ok, should not produce stderr. - &x[..]; // Ok, should not produce stderr. - &x[1..]; // Ok, should not produce stderr. - &x[2..].iter().map(|x| 2 * x).collect::>(); // Ok, should not produce stderr. &x[0..].get(..3); // Ok, should not produce stderr. x[0]; // Ok, should not produce stderr. x[3]; // Ok, should not produce stderr. @@ -43,21 +35,6 @@ fn main() { &y[..]; // Ok, should not produce stderr. - let empty: [i8; 0] = []; - empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - &empty[1..5]; - &empty[0..=4]; - &empty[..=4]; - &empty[1..]; - &empty[..4]; - &empty[0..=0]; - &empty[..=0]; - - &empty[0..]; // Ok, should not produce stderr. - &empty[0..0]; // Ok, should not produce stderr. - &empty[..0]; // Ok, should not produce stderr. - &empty[..]; // Ok, should not produce stderr. - let v = vec![0; 5]; v[0]; v[10]; @@ -79,9 +56,4 @@ fn main() { x[M]; // Ok, should not produce stderr. v[N]; v[M]; - - // issue 3102 - let num = 1; - &x[num..10]; // should trigger out of bounds error - &x[10..num]; // should trigger out of bounds error } diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 129fec0e9..8d6030701 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,5 +1,5 @@ error: index out of bounds: the len is 4 but the index is 4 - --> $DIR/indexing_slicing.rs:16:5 + --> $DIR/indexing_slicing.rs:19:5 | LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ @@ -7,25 +7,19 @@ LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on ar = note: #[deny(const_err)] on by default error: index out of bounds: the len is 4 but the index is 8 - --> $DIR/indexing_slicing.rs:17:5 + --> $DIR/indexing_slicing.rs:20:5 | LL | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^^ -error: index out of bounds: the len is 0 but the index is 0 - --> $DIR/indexing_slicing.rs:47:5 - | -LL | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - | ^^^^^^^^ - error: index out of bounds: the len is 4 but the index is 15 - --> $DIR/indexing_slicing.rs:78:5 + --> $DIR/indexing_slicing.rs:55:5 | LL | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:11:5 + --> $DIR/indexing_slicing.rs:14:5 | LL | x[index]; | ^^^^^^^^ @@ -34,7 +28,7 @@ LL | x[index]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:12:6 + --> $DIR/indexing_slicing.rs:15:6 | LL | &x[index..]; | ^^^^^^^^^^ @@ -42,7 +36,7 @@ LL | &x[index..]; = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:13:6 + --> $DIR/indexing_slicing.rs:16:6 | LL | &x[..index]; | ^^^^^^^^^^ @@ -50,7 +44,7 @@ LL | &x[..index]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:14:6 + --> $DIR/indexing_slicing.rs:17:6 | LL | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +52,7 @@ LL | &x[index_from..index_to]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:15:6 + --> $DIR/indexing_slicing.rs:18:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -66,67 +60,31 @@ LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:15:6 + --> $DIR/indexing_slicing.rs:18:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ | = help: Consider using `.get(n..)` or .get_mut(n..)` instead -error: range is out of bounds - --> $DIR/indexing_slicing.rs:18:11 - | -LL | &x[..=4]; - | ^ - | - = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:19:11 - | -LL | &x[1..5]; - | ^ - error: slicing may panic. - --> $DIR/indexing_slicing.rs:20:6 + --> $DIR/indexing_slicing.rs:21:6 | -LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. +LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and another for slicing [..10]. | ^^^^^^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: range is out of bounds - --> $DIR/indexing_slicing.rs:20:8 - | -LL | &x[5..][..10]; // Two lint reports, one for [5..] and another for [..10]. - | ^ - error: range is out of bounds --> $DIR/indexing_slicing.rs:21:8 | -LL | &x[5..]; +LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and another for slicing [..10]. | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:22:10 | -LL | &x[..5]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:23:8 - | -LL | &x[5..].iter().map(|x| 2 * x).collect::>(); - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:24:12 - | -LL | &x[0..=4]; - | ^ + = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: slicing may panic. - --> $DIR/indexing_slicing.rs:25:6 + --> $DIR/indexing_slicing.rs:22:6 | LL | &x[0..][..3]; | ^^^^^^^^^^^ @@ -134,7 +92,7 @@ LL | &x[0..][..3]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:26:6 + --> $DIR/indexing_slicing.rs:23:6 | LL | &x[1..][..5]; | ^^^^^^^^^^^ @@ -142,7 +100,7 @@ LL | &x[1..][..5]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:39:5 + --> $DIR/indexing_slicing.rs:31:5 | LL | y[0]; | ^^^^ @@ -150,7 +108,7 @@ LL | y[0]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:40:6 + --> $DIR/indexing_slicing.rs:32:6 | LL | &y[1..2]; | ^^^^^^^ @@ -158,7 +116,7 @@ LL | &y[1..2]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:41:6 + --> $DIR/indexing_slicing.rs:33:6 | LL | &y[0..=4]; | ^^^^^^^^ @@ -166,57 +124,15 @@ LL | &y[0..=4]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:42:6 + --> $DIR/indexing_slicing.rs:34:6 | LL | &y[..=4]; | ^^^^^^^ | = help: Consider using `.get(..n)`or `.get_mut(..n)` instead -error: range is out of bounds - --> $DIR/indexing_slicing.rs:48:12 - | -LL | &empty[1..5]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:49:16 - | -LL | &empty[0..=4]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:50:15 - | -LL | &empty[..=4]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:51:12 - | -LL | &empty[1..]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:52:14 - | -LL | &empty[..4]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:53:16 - | -LL | &empty[0..=0]; - | ^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:54:15 - | -LL | &empty[..=0]; - | ^ - error: indexing may panic. - --> $DIR/indexing_slicing.rs:62:5 + --> $DIR/indexing_slicing.rs:39:5 | LL | v[0]; | ^^^^ @@ -224,7 +140,7 @@ LL | v[0]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:63:5 + --> $DIR/indexing_slicing.rs:40:5 | LL | v[10]; | ^^^^^ @@ -232,7 +148,7 @@ LL | v[10]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:64:5 + --> $DIR/indexing_slicing.rs:41:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -240,7 +156,7 @@ LL | v[1 << 3]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:65:6 + --> $DIR/indexing_slicing.rs:42:6 | LL | &v[10..100]; | ^^^^^^^^^^ @@ -248,7 +164,7 @@ LL | &v[10..100]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:66:6 + --> $DIR/indexing_slicing.rs:43:6 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ @@ -256,13 +172,13 @@ LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:66:8 + --> $DIR/indexing_slicing.rs:43:8 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:67:6 + --> $DIR/indexing_slicing.rs:44:6 | LL | &v[10..]; | ^^^^^^^ @@ -270,7 +186,7 @@ LL | &v[10..]; = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:68:6 + --> $DIR/indexing_slicing.rs:45:6 | LL | &v[..100]; | ^^^^^^^^ @@ -278,7 +194,7 @@ LL | &v[..100]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:80:5 + --> $DIR/indexing_slicing.rs:57:5 | LL | v[N]; | ^^^^ @@ -286,24 +202,12 @@ LL | v[N]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:81:5 + --> $DIR/indexing_slicing.rs:58:5 | LL | v[M]; | ^^^^ | = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: range is out of bounds - --> $DIR/indexing_slicing.rs:85:13 - | -LL | &x[num..10]; // should trigger out of bounds error - | ^^ - -error: range is out of bounds - --> $DIR/indexing_slicing.rs:86:8 - | -LL | &x[10..num]; // should trigger out of bounds error - | ^^ - -error: aborting due to 43 previous errors +error: aborting due to 27 previous errors diff --git a/tests/ui/out_of_bounds_indexing/empty_array.rs b/tests/ui/out_of_bounds_indexing/empty_array.rs new file mode 100644 index 000000000..b980a1bec --- /dev/null +++ b/tests/ui/out_of_bounds_indexing/empty_array.rs @@ -0,0 +1,19 @@ +#![warn(clippy::out_of_bounds_indexing)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] + +fn main() { + let empty: [i8; 0] = []; + empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + &empty[1..5]; + &empty[0..=4]; + &empty[..=4]; + &empty[1..]; + &empty[..4]; + &empty[0..=0]; + &empty[..=0]; + + &empty[0..]; // Ok, should not produce stderr. + &empty[0..0]; // Ok, should not produce stderr. + &empty[..0]; // Ok, should not produce stderr. + &empty[..]; // Ok, should not produce stderr. +} diff --git a/tests/ui/out_of_bounds_indexing/empty_array.stderr b/tests/ui/out_of_bounds_indexing/empty_array.stderr new file mode 100644 index 000000000..f6fb03383 --- /dev/null +++ b/tests/ui/out_of_bounds_indexing/empty_array.stderr @@ -0,0 +1,54 @@ +error: index out of bounds: the len is 0 but the index is 0 + --> $DIR/empty_array.rs:6:5 + | +LL | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + | ^^^^^^^^ + | + = note: #[deny(const_err)] on by default + +error: range is out of bounds + --> $DIR/empty_array.rs:7:12 + | +LL | &empty[1..5]; + | ^ + | + = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + +error: range is out of bounds + --> $DIR/empty_array.rs:8:16 + | +LL | &empty[0..=4]; + | ^ + +error: range is out of bounds + --> $DIR/empty_array.rs:9:15 + | +LL | &empty[..=4]; + | ^ + +error: range is out of bounds + --> $DIR/empty_array.rs:10:12 + | +LL | &empty[1..]; + | ^ + +error: range is out of bounds + --> $DIR/empty_array.rs:11:14 + | +LL | &empty[..4]; + | ^ + +error: range is out of bounds + --> $DIR/empty_array.rs:12:16 + | +LL | &empty[0..=0]; + | ^ + +error: range is out of bounds + --> $DIR/empty_array.rs:13:15 + | +LL | &empty[..=0]; + | ^ + +error: aborting due to 8 previous errors + diff --git a/tests/ui/out_of_bounds_indexing/issue-3102.rs b/tests/ui/out_of_bounds_indexing/issue-3102.rs new file mode 100644 index 000000000..9883548dd --- /dev/null +++ b/tests/ui/out_of_bounds_indexing/issue-3102.rs @@ -0,0 +1,10 @@ +#![warn(clippy::out_of_bounds_indexing)] + +fn main() { + let x = [1, 2, 3, 4]; + + // issue 3102 + let num = 1; + &x[num..10]; // should trigger out of bounds error + &x[10..num]; // should trigger out of bounds error +} diff --git a/tests/ui/out_of_bounds_indexing/issue-3102.stderr b/tests/ui/out_of_bounds_indexing/issue-3102.stderr new file mode 100644 index 000000000..f55aeee39 --- /dev/null +++ b/tests/ui/out_of_bounds_indexing/issue-3102.stderr @@ -0,0 +1,30 @@ +error: statement with no effect + --> $DIR/issue-3102.rs:8:5 + | +LL | &x[num..10]; // should trigger out of bounds error + | ^^^^^^^^^^^^ + | + = note: `-D clippy::no-effect` implied by `-D warnings` + +error: range is out of bounds + --> $DIR/issue-3102.rs:8:13 + | +LL | &x[num..10]; // should trigger out of bounds error + | ^^ + | + = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + +error: statement with no effect + --> $DIR/issue-3102.rs:9:5 + | +LL | &x[10..num]; // should trigger out of bounds error + | ^^^^^^^^^^^^ + +error: range is out of bounds + --> $DIR/issue-3102.rs:9:8 + | +LL | &x[10..num]; // should trigger out of bounds error + | ^^ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/out_of_bounds_indexing/simple.rs b/tests/ui/out_of_bounds_indexing/simple.rs new file mode 100644 index 000000000..4c541c23f --- /dev/null +++ b/tests/ui/out_of_bounds_indexing/simple.rs @@ -0,0 +1,22 @@ +#![warn(clippy::out_of_bounds_indexing)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] + +fn main() { + let x = [1, 2, 3, 4]; + + &x[..=4]; + &x[1..5]; + &x[5..]; + &x[..5]; + &x[5..].iter().map(|x| 2 * x).collect::>(); + &x[0..=4]; + + &x[4..]; // Ok, should not produce stderr. + &x[..4]; // Ok, should not produce stderr. + &x[..]; // Ok, should not produce stderr. + &x[1..]; // Ok, should not produce stderr. + &x[2..].iter().map(|x| 2 * x).collect::>(); // Ok, should not produce stderr. + + &x[0..].get(..3); // Ok, should not produce stderr. + &x[0..3]; // Ok, should not produce stderr. +} diff --git a/tests/ui/out_of_bounds_indexing/simple.stderr b/tests/ui/out_of_bounds_indexing/simple.stderr new file mode 100644 index 000000000..3d95afcda --- /dev/null +++ b/tests/ui/out_of_bounds_indexing/simple.stderr @@ -0,0 +1,40 @@ +error: range is out of bounds + --> $DIR/simple.rs:7:11 + | +LL | &x[..=4]; + | ^ + | + = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` + +error: range is out of bounds + --> $DIR/simple.rs:8:11 + | +LL | &x[1..5]; + | ^ + +error: range is out of bounds + --> $DIR/simple.rs:9:8 + | +LL | &x[5..]; + | ^ + +error: range is out of bounds + --> $DIR/simple.rs:10:10 + | +LL | &x[..5]; + | ^ + +error: range is out of bounds + --> $DIR/simple.rs:11:8 + | +LL | &x[5..].iter().map(|x| 2 * x).collect::>(); + | ^ + +error: range is out of bounds + --> $DIR/simple.rs:12:12 + | +LL | &x[0..=4]; + | ^ + +error: aborting due to 6 previous errors + From a2b63af74653ec4d7324f55aa8edf2460e739e1f Mon Sep 17 00:00:00 2001 From: daxpedda <1645124+daxpedda@users.noreply.github.com> Date: Tue, 16 Jul 2019 14:46:33 +0200 Subject: [PATCH 038/133] Removed lintining on never type. Abstracted repeating strings into statics. --- clippy_lints/src/implicit_return.rs | 37 ++++++++++++----------------- tests/ui/implicit_return.rs | 4 ---- tests/ui/implicit_return.stderr | 10 ++------ 3 files changed, 17 insertions(+), 34 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 409a10f82..a2a214831 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -42,6 +42,9 @@ declare_clippy_lint! { declare_lint_pass!(ImplicitReturn => [IMPLICIT_RETURN]); +static LINT_BREAK: &str = "change `break` to `return` as shown"; +static LINT_RETURN: &str = "add `return` as shown"; + fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) { let outer_span = span_to_outer_expn(outer_span); let inner_span = span_to_outer_expn(inner_span); @@ -66,12 +69,12 @@ fn span_to_outer_expn(span: Span) -> Span { } } -fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) { +fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr) { match &expr.node { // loops could be using `break` instead of `return` ExprKind::Block(block, ..) | ExprKind::Loop(block, ..) => { if let Some(expr) = &block.expr { - expr_match(cx, expr, ret_ty_is_never); + expr_match(cx, expr); } // only needed in the case of `break` with `;` at the end else if let Some(stmt) = block.stmts.last() { @@ -81,7 +84,7 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) { if let ExprKind::Break(.., break_expr) = &expr.node; if let Some(break_expr) = break_expr; then { - lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); + lint(cx, expr.span, break_expr.span, LINT_BREAK); } } } @@ -89,7 +92,7 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) { // use `return` instead of `break` ExprKind::Break(.., break_expr) => { if let Some(break_expr) = break_expr { - lint(cx, expr.span, break_expr.span, "change `break` to `return` as shown"); + lint(cx, expr.span, break_expr.span, LINT_BREAK); } }, ExprKind::Match(.., arms, source) => { @@ -102,38 +105,29 @@ fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr, ret_ty_is_never: bool) { if check_all_arms { for arm in arms { - expr_match(cx, &arm.body, ret_ty_is_never); + expr_match(cx, &arm.body); } } else { - expr_match( - cx, - &arms.first().expect("if let doesn't have a single arm").body, - ret_ty_is_never, - ); + expr_match(cx, &arms.first().expect("if let doesn't have a single arm").body); } }, // skip if it already has a return statement ExprKind::Ret(..) => (), - // make sure it's not a call that panics unless we intend to return a panic + // make sure it's not a call that panics ExprKind::Call(expr, ..) => { if_chain! { if let ExprKind::Path(qpath) = &expr.node; if let Some(path_def_id) = resolve_node(cx, qpath, expr.hir_id).opt_def_id(); if match_def_path(cx, path_def_id, &BEGIN_PANIC) || match_def_path(cx, path_def_id, &BEGIN_PANIC_FMT); - then { - // only put `return` on panics if the return type of the function/closure is a panic - if ret_ty_is_never { - lint(cx, expr.span, expr.span, "add `return` as shown") - } - } + then { } else { - lint(cx, expr.span, expr.span, "add `return` as shown") + lint(cx, expr.span, expr.span, LINT_RETURN) } } }, // everything else is missing `return` - _ => lint(cx, expr.span, expr.span, "add `return` as shown"), + _ => lint(cx, expr.span, expr.span, LINT_RETURN), } } @@ -149,12 +143,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); let mir = cx.tcx.optimized_mir(def_id); - let ret_ty = mir.return_ty(); // checking return type through MIR, HIR is not able to determine inferred closure return types // make sure it's not a macro - if !ret_ty.is_unit() && !in_macro_or_desugar(span) { - expr_match(cx, &body.value, ret_ty.is_never()); + if !mir.return_ty().is_unit() && !in_macro_or_desugar(span) { + expr_match(cx, &body.value); } } } diff --git a/tests/ui/implicit_return.rs b/tests/ui/implicit_return.rs index ade3dc00a..47e0679c4 100644 --- a/tests/ui/implicit_return.rs +++ b/tests/ui/implicit_return.rs @@ -77,10 +77,6 @@ fn test_closure() { let _ = || true; } -fn test_return_never() -> ! { - panic!() -} - fn test_panic() -> bool { panic!() } diff --git a/tests/ui/implicit_return.stderr b/tests/ui/implicit_return.stderr index ac6a76cd3..41b087331 100644 --- a/tests/ui/implicit_return.stderr +++ b/tests/ui/implicit_return.stderr @@ -61,16 +61,10 @@ LL | let _ = || true; | ^^^^ help: add `return` as shown: `return true` error: missing return statement - --> $DIR/implicit_return.rs:81:5 - | -LL | panic!() - | ^^^^^^^^ help: add `return` as shown: `return panic!()` - -error: missing return statement - --> $DIR/implicit_return.rs:89:5 + --> $DIR/implicit_return.rs:85:5 | LL | format!("test {}", "test") | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `return` as shown: `return format!("test {}", "test")` -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors From 48bff49484a358667810d68cc619f4fc972116af Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 15 Jul 2019 21:27:44 +0200 Subject: [PATCH 039/133] UI Test Cleanup: Split up checked_unwrap tests This splits up `tests/ui/checked_unwrap.rs` into: * `tests/ui/checked_unwrap/complex.rs` * `tests/ui/checked_unwrap/simple.rs` Based on the naming of the methods in the tests. cc #2038 --- .../complex_conditionals.rs} | 40 +---- .../complex_conditionals.stderr} | 170 ++++-------------- .../ui/checked_unwrap/simple_conditionals.rs | 40 +++++ .../checked_unwrap/simple_conditionals.stderr | 118 ++++++++++++ 4 files changed, 193 insertions(+), 175 deletions(-) rename tests/ui/{checked_unwrap.rs => checked_unwrap/complex_conditionals.rs} (62%) rename tests/ui/{checked_unwrap.stderr => checked_unwrap/complex_conditionals.stderr} (60%) create mode 100644 tests/ui/checked_unwrap/simple_conditionals.rs create mode 100644 tests/ui/checked_unwrap/simple_conditionals.stderr diff --git a/tests/ui/checked_unwrap.rs b/tests/ui/checked_unwrap/complex_conditionals.rs similarity index 62% rename from tests/ui/checked_unwrap.rs rename to tests/ui/checked_unwrap/complex_conditionals.rs index 21f9e3320..fbeee1b57 100644 --- a/tests/ui/checked_unwrap.rs +++ b/tests/ui/checked_unwrap/complex_conditionals.rs @@ -1,44 +1,6 @@ #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] #![allow(clippy::if_same_then_else)] -fn main() { - let x = Some(()); - if x.is_some() { - x.unwrap(); // unnecessary - } else { - x.unwrap(); // will panic - } - if x.is_none() { - x.unwrap(); // will panic - } else { - x.unwrap(); // unnecessary - } - let mut x: Result<(), ()> = Ok(()); - if x.is_ok() { - x.unwrap(); // unnecessary - x.unwrap_err(); // will panic - } else { - x.unwrap(); // will panic - x.unwrap_err(); // unnecessary - } - if x.is_err() { - x.unwrap(); // will panic - x.unwrap_err(); // unnecessary - } else { - x.unwrap(); // unnecessary - x.unwrap_err(); // will panic - } - if x.is_ok() { - x = Err(()); - x.unwrap(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enough to see this (it only checks if conditions). - } else { - x = Ok(()); - x.unwrap_err(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enough to see this (it only checks if conditions). - } -} - fn test_complex_conditions() { let x: Result<(), ()> = Ok(()); let y: Result<(), ()> = Ok(()); @@ -99,3 +61,5 @@ fn test_nested() { } } } + +fn main() {} diff --git a/tests/ui/checked_unwrap.stderr b/tests/ui/checked_unwrap/complex_conditionals.stderr similarity index 60% rename from tests/ui/checked_unwrap.stderr rename to tests/ui/checked_unwrap/complex_conditionals.stderr index 514814b0e..a2207314a 100644 --- a/tests/ui/checked_unwrap.stderr +++ b/tests/ui/checked_unwrap/complex_conditionals.stderr @@ -1,138 +1,34 @@ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:7:9 + --> $DIR/complex_conditionals.rs:8:9 | -LL | if x.is_some() { - | ----------- the check is happening here +LL | if x.is_ok() && y.is_err() { + | --------- the check is happening here LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:1:35 + --> $DIR/complex_conditionals.rs:1:35 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:9:9 +error: This call to `unwrap_err()` will always panic. + --> $DIR/complex_conditionals.rs:9:9 | -LL | if x.is_some() { - | ----------- because of this check -... -LL | x.unwrap(); // will panic - | ^^^^^^^^^^ +LL | if x.is_ok() && y.is_err() { + | --------- because of this check +LL | x.unwrap(); // unnecessary +LL | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ | note: lint level defined here - --> $DIR/checked_unwrap.rs:1:9 + --> $DIR/complex_conditionals.rs:1:9 | LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] | ^^^^^^^^^^^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:12:9 - | -LL | if x.is_none() { - | ----------- because of this check -LL | x.unwrap(); // will panic - | ^^^^^^^^^^ - -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:14:9 - | -LL | if x.is_none() { - | ----------- the check is happening here -... -LL | x.unwrap(); // unnecessary - | ^^^^^^^^^^ - -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:18:9 - | -LL | if x.is_ok() { - | --------- the check is happening here -LL | x.unwrap(); // unnecessary - | ^^^^^^^^^^ - -error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:19:9 - | -LL | if x.is_ok() { - | --------- because of this check -LL | x.unwrap(); // unnecessary -LL | x.unwrap_err(); // will panic - | ^^^^^^^^^^^^^^ - -error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:21:9 - | -LL | if x.is_ok() { - | --------- because of this check -... -LL | x.unwrap(); // will panic - | ^^^^^^^^^^ - -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:22:9 - | -LL | if x.is_ok() { - | --------- the check is happening here -... -LL | x.unwrap_err(); // unnecessary - | ^^^^^^^^^^^^^^ - -error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:25:9 - | -LL | if x.is_err() { - | ---------- because of this check -LL | x.unwrap(); // will panic - | ^^^^^^^^^^ - -error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:26:9 - | -LL | if x.is_err() { - | ---------- the check is happening here -LL | x.unwrap(); // will panic -LL | x.unwrap_err(); // unnecessary - | ^^^^^^^^^^^^^^ - -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:28:9 - | -LL | if x.is_err() { - | ---------- the check is happening here -... -LL | x.unwrap(); // unnecessary - | ^^^^^^^^^^ - -error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:29:9 - | -LL | if x.is_err() { - | ---------- because of this check -... -LL | x.unwrap_err(); // will panic - | ^^^^^^^^^^^^^^ - -error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:46:9 - | -LL | if x.is_ok() && y.is_err() { - | --------- the check is happening here -LL | x.unwrap(); // unnecessary - | ^^^^^^^^^^ - -error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:47:9 - | -LL | if x.is_ok() && y.is_err() { - | --------- because of this check -LL | x.unwrap(); // unnecessary -LL | x.unwrap_err(); // will panic - | ^^^^^^^^^^^^^^ - -error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:48:9 + --> $DIR/complex_conditionals.rs:10:9 | LL | if x.is_ok() && y.is_err() { | ---------- because of this check @@ -141,7 +37,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:49:9 + --> $DIR/complex_conditionals.rs:11:9 | LL | if x.is_ok() && y.is_err() { | ---------- the check is happening here @@ -150,7 +46,7 @@ LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:63:9 + --> $DIR/complex_conditionals.rs:25:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -159,7 +55,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:64:9 + --> $DIR/complex_conditionals.rs:26:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -168,7 +64,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:65:9 + --> $DIR/complex_conditionals.rs:27:9 | LL | if x.is_ok() || y.is_ok() { | --------- because of this check @@ -177,7 +73,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:66:9 + --> $DIR/complex_conditionals.rs:28:9 | LL | if x.is_ok() || y.is_ok() { | --------- the check is happening here @@ -186,7 +82,7 @@ LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:70:9 + --> $DIR/complex_conditionals.rs:32:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -194,7 +90,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:71:9 + --> $DIR/complex_conditionals.rs:33:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -203,7 +99,7 @@ LL | x.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:72:9 + --> $DIR/complex_conditionals.rs:34:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- because of this check @@ -212,7 +108,7 @@ LL | y.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:73:9 + --> $DIR/complex_conditionals.rs:35:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | --------- the check is happening here @@ -221,7 +117,7 @@ LL | y.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:74:9 + --> $DIR/complex_conditionals.rs:36:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- the check is happening here @@ -230,7 +126,7 @@ LL | z.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:75:9 + --> $DIR/complex_conditionals.rs:37:9 | LL | if x.is_ok() && !(y.is_ok() || z.is_err()) { | ---------- because of this check @@ -239,7 +135,7 @@ LL | z.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:83:9 + --> $DIR/complex_conditionals.rs:45:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -248,7 +144,7 @@ LL | x.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:84:9 + --> $DIR/complex_conditionals.rs:46:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -257,7 +153,7 @@ LL | x.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:85:9 + --> $DIR/complex_conditionals.rs:47:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- the check is happening here @@ -266,7 +162,7 @@ LL | y.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap_err()` will always panic. - --> $DIR/checked_unwrap.rs:86:9 + --> $DIR/complex_conditionals.rs:48:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | --------- because of this check @@ -275,7 +171,7 @@ LL | y.unwrap_err(); // will panic | ^^^^^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:87:9 + --> $DIR/complex_conditionals.rs:49:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- because of this check @@ -284,7 +180,7 @@ LL | z.unwrap(); // will panic | ^^^^^^^^^^ error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:88:9 + --> $DIR/complex_conditionals.rs:50:9 | LL | if x.is_ok() || !(y.is_ok() && z.is_err()) { | ---------- the check is happening here @@ -293,7 +189,7 @@ LL | z.unwrap_err(); // unnecessary | ^^^^^^^^^^^^^^ error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. - --> $DIR/checked_unwrap.rs:96:13 + --> $DIR/complex_conditionals.rs:58:13 | LL | if x.is_some() { | ----------- the check is happening here @@ -301,7 +197,7 @@ LL | x.unwrap(); // unnecessary | ^^^^^^^^^^ error: This call to `unwrap()` will always panic. - --> $DIR/checked_unwrap.rs:98:13 + --> $DIR/complex_conditionals.rs:60:13 | LL | if x.is_some() { | ----------- because of this check @@ -309,5 +205,5 @@ LL | if x.is_some() { LL | x.unwrap(); // will panic | ^^^^^^^^^^ -error: aborting due to 34 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs new file mode 100644 index 000000000..c20c4a7a7 --- /dev/null +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -0,0 +1,40 @@ +#![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] +#![allow(clippy::if_same_then_else)] + +fn main() { + let x = Some(()); + if x.is_some() { + x.unwrap(); // unnecessary + } else { + x.unwrap(); // will panic + } + if x.is_none() { + x.unwrap(); // will panic + } else { + x.unwrap(); // unnecessary + } + let mut x: Result<(), ()> = Ok(()); + if x.is_ok() { + x.unwrap(); // unnecessary + x.unwrap_err(); // will panic + } else { + x.unwrap(); // will panic + x.unwrap_err(); // unnecessary + } + if x.is_err() { + x.unwrap(); // will panic + x.unwrap_err(); // unnecessary + } else { + x.unwrap(); // unnecessary + x.unwrap_err(); // will panic + } + if x.is_ok() { + x = Err(()); + x.unwrap(); // not unnecessary because of mutation of x + // it will always panic but the lint is not smart enough to see this (it only checks if conditions). + } else { + x = Ok(()); + x.unwrap_err(); // not unnecessary because of mutation of x + // it will always panic but the lint is not smart enough to see this (it only checks if conditions). + } +} diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr new file mode 100644 index 000000000..58a38cd82 --- /dev/null +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -0,0 +1,118 @@ +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/simple_conditionals.rs:7:9 + | +LL | if x.is_some() { + | ----------- the check is happening here +LL | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/simple_conditionals.rs:1:35 + | +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/simple_conditionals.rs:9:9 + | +LL | if x.is_some() { + | ----------- because of this check +... +LL | x.unwrap(); // will panic + | ^^^^^^^^^^ + | +note: lint level defined here + --> $DIR/simple_conditionals.rs:1:9 + | +LL | #![deny(clippy::panicking_unwrap, clippy::unnecessary_unwrap)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/simple_conditionals.rs:12:9 + | +LL | if x.is_none() { + | ----------- because of this check +LL | x.unwrap(); // will panic + | ^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/simple_conditionals.rs:14:9 + | +LL | if x.is_none() { + | ----------- the check is happening here +... +LL | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/simple_conditionals.rs:18:9 + | +LL | if x.is_ok() { + | --------- the check is happening here +LL | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/simple_conditionals.rs:19:9 + | +LL | if x.is_ok() { + | --------- because of this check +LL | x.unwrap(); // unnecessary +LL | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/simple_conditionals.rs:21:9 + | +LL | if x.is_ok() { + | --------- because of this check +... +LL | x.unwrap(); // will panic + | ^^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/simple_conditionals.rs:22:9 + | +LL | if x.is_ok() { + | --------- the check is happening here +... +LL | x.unwrap_err(); // unnecessary + | ^^^^^^^^^^^^^^ + +error: This call to `unwrap()` will always panic. + --> $DIR/simple_conditionals.rs:25:9 + | +LL | if x.is_err() { + | ---------- because of this check +LL | x.unwrap(); // will panic + | ^^^^^^^^^^ + +error: You checked before that `unwrap_err()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/simple_conditionals.rs:26:9 + | +LL | if x.is_err() { + | ---------- the check is happening here +LL | x.unwrap(); // will panic +LL | x.unwrap_err(); // unnecessary + | ^^^^^^^^^^^^^^ + +error: You checked before that `unwrap()` cannot fail. Instead of checking and unwrapping, it's better to use `if let` or `match`. + --> $DIR/simple_conditionals.rs:28:9 + | +LL | if x.is_err() { + | ---------- the check is happening here +... +LL | x.unwrap(); // unnecessary + | ^^^^^^^^^^ + +error: This call to `unwrap_err()` will always panic. + --> $DIR/simple_conditionals.rs:29:9 + | +LL | if x.is_err() { + | ---------- because of this check +... +LL | x.unwrap_err(); // will panic + | ^^^^^^^^^^^^^^ + +error: aborting due to 12 previous errors + From 633934da18e5ba31f187f83f4745fe44e4cb367d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Jul 2019 21:28:03 +0200 Subject: [PATCH 040/133] cargo fmt --- tests/ui/indexing_slicing.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/indexing_slicing.rs b/tests/ui/indexing_slicing.rs index bce6606b0..8dd6ae146 100644 --- a/tests/ui/indexing_slicing.rs +++ b/tests/ui/indexing_slicing.rs @@ -1,6 +1,5 @@ #![feature(plugin)] #![warn(clippy::indexing_slicing)] - // We also check the out_of_bounds_indexing lint here, because it lints similar things and // we want to avoid false positives. #![warn(clippy::out_of_bounds_indexing)] From 65e9477b84541c42b3b435cb0dcbffec9aeeb054 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Jul 2019 21:28:37 +0200 Subject: [PATCH 041/133] Remove comment Co-Authored-By: Philipp Krones --- tests/ui/out_of_bounds_indexing/empty_array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/out_of_bounds_indexing/empty_array.rs b/tests/ui/out_of_bounds_indexing/empty_array.rs index b980a1bec..884e46eb4 100644 --- a/tests/ui/out_of_bounds_indexing/empty_array.rs +++ b/tests/ui/out_of_bounds_indexing/empty_array.rs @@ -3,7 +3,7 @@ fn main() { let empty: [i8; 0] = []; - empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. + empty[0]; &empty[1..5]; &empty[0..=4]; &empty[..=4]; From 7a888968f941a8abcf6ce66f7a747ad9307e70e5 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Jul 2019 21:29:03 +0200 Subject: [PATCH 042/133] Allow no_effect lint for cleaner stderr file Co-Authored-By: Philipp Krones --- tests/ui/out_of_bounds_indexing/issue-3102.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/out_of_bounds_indexing/issue-3102.rs b/tests/ui/out_of_bounds_indexing/issue-3102.rs index 9883548dd..edd2123d4 100644 --- a/tests/ui/out_of_bounds_indexing/issue-3102.rs +++ b/tests/ui/out_of_bounds_indexing/issue-3102.rs @@ -1,4 +1,5 @@ #![warn(clippy::out_of_bounds_indexing)] +#![allow(clippy::no_effect)] fn main() { let x = [1, 2, 3, 4]; From 38b6156a51f119f9ad4fd75e190434726de3f0a3 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 16 Jul 2019 22:26:47 +0200 Subject: [PATCH 043/133] Update UI tests --- tests/ui/indexing_slicing.stderr | 54 +++++++++---------- .../out_of_bounds_indexing/empty_array.stderr | 2 +- .../out_of_bounds_indexing/issue-3102.stderr | 20 ++----- 3 files changed, 31 insertions(+), 45 deletions(-) diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index 8d6030701..f075de506 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,5 +1,5 @@ error: index out of bounds: the len is 4 but the index is 4 - --> $DIR/indexing_slicing.rs:19:5 + --> $DIR/indexing_slicing.rs:18:5 | LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ @@ -7,19 +7,19 @@ LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on ar = note: #[deny(const_err)] on by default error: index out of bounds: the len is 4 but the index is 8 - --> $DIR/indexing_slicing.rs:20:5 + --> $DIR/indexing_slicing.rs:19:5 | LL | x[1 << 3]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^^^^^^ error: index out of bounds: the len is 4 but the index is 15 - --> $DIR/indexing_slicing.rs:55:5 + --> $DIR/indexing_slicing.rs:54:5 | LL | x[N]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ error: indexing may panic. - --> $DIR/indexing_slicing.rs:14:5 + --> $DIR/indexing_slicing.rs:13:5 | LL | x[index]; | ^^^^^^^^ @@ -28,7 +28,7 @@ LL | x[index]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:15:6 + --> $DIR/indexing_slicing.rs:14:6 | LL | &x[index..]; | ^^^^^^^^^^ @@ -36,7 +36,7 @@ LL | &x[index..]; = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:16:6 + --> $DIR/indexing_slicing.rs:15:6 | LL | &x[..index]; | ^^^^^^^^^^ @@ -44,7 +44,7 @@ LL | &x[..index]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:17:6 + --> $DIR/indexing_slicing.rs:16:6 | LL | &x[index_from..index_to]; | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL | &x[index_from..index_to]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:18:6 + --> $DIR/indexing_slicing.rs:17:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -60,7 +60,7 @@ LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:18:6 + --> $DIR/indexing_slicing.rs:17:6 | LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from..] and another for [..index_to]. | ^^^^^^^^^^^^^^^ @@ -68,7 +68,7 @@ LL | &x[index_from..][..index_to]; // Two lint reports, one for [index_from. = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:21:6 + --> $DIR/indexing_slicing.rs:20:6 | LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and another for slicing [..10]. | ^^^^^^^^^^^^ @@ -76,7 +76,7 @@ LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and ano = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:21:8 + --> $DIR/indexing_slicing.rs:20:8 | LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and another for slicing [..10]. | ^ @@ -84,7 +84,7 @@ LL | &x[5..][..10]; // Two lint reports, one for out of bounds [5..] and ano = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` error: slicing may panic. - --> $DIR/indexing_slicing.rs:22:6 + --> $DIR/indexing_slicing.rs:21:6 | LL | &x[0..][..3]; | ^^^^^^^^^^^ @@ -92,7 +92,7 @@ LL | &x[0..][..3]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:23:6 + --> $DIR/indexing_slicing.rs:22:6 | LL | &x[1..][..5]; | ^^^^^^^^^^^ @@ -100,7 +100,7 @@ LL | &x[1..][..5]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:31:5 + --> $DIR/indexing_slicing.rs:30:5 | LL | y[0]; | ^^^^ @@ -108,7 +108,7 @@ LL | y[0]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:32:6 + --> $DIR/indexing_slicing.rs:31:6 | LL | &y[1..2]; | ^^^^^^^ @@ -116,7 +116,7 @@ LL | &y[1..2]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:33:6 + --> $DIR/indexing_slicing.rs:32:6 | LL | &y[0..=4]; | ^^^^^^^^ @@ -124,7 +124,7 @@ LL | &y[0..=4]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:34:6 + --> $DIR/indexing_slicing.rs:33:6 | LL | &y[..=4]; | ^^^^^^^ @@ -132,7 +132,7 @@ LL | &y[..=4]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:39:5 + --> $DIR/indexing_slicing.rs:38:5 | LL | v[0]; | ^^^^ @@ -140,7 +140,7 @@ LL | v[0]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:40:5 + --> $DIR/indexing_slicing.rs:39:5 | LL | v[10]; | ^^^^^ @@ -148,7 +148,7 @@ LL | v[10]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:41:5 + --> $DIR/indexing_slicing.rs:40:5 | LL | v[1 << 3]; | ^^^^^^^^^ @@ -156,7 +156,7 @@ LL | v[1 << 3]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:42:6 + --> $DIR/indexing_slicing.rs:41:6 | LL | &v[10..100]; | ^^^^^^^^^^ @@ -164,7 +164,7 @@ LL | &v[10..100]; = help: Consider using `.get(n..m)` or `.get_mut(n..m)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:43:6 + --> $DIR/indexing_slicing.rs:42:6 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^^^^^^^^^^^^^ @@ -172,13 +172,13 @@ LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [. = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: range is out of bounds - --> $DIR/indexing_slicing.rs:43:8 + --> $DIR/indexing_slicing.rs:42:8 | LL | &x[10..][..100]; // Two lint reports, one for [10..] and another for [..100]. | ^^ error: slicing may panic. - --> $DIR/indexing_slicing.rs:44:6 + --> $DIR/indexing_slicing.rs:43:6 | LL | &v[10..]; | ^^^^^^^ @@ -186,7 +186,7 @@ LL | &v[10..]; = help: Consider using `.get(n..)` or .get_mut(n..)` instead error: slicing may panic. - --> $DIR/indexing_slicing.rs:45:6 + --> $DIR/indexing_slicing.rs:44:6 | LL | &v[..100]; | ^^^^^^^^ @@ -194,7 +194,7 @@ LL | &v[..100]; = help: Consider using `.get(..n)`or `.get_mut(..n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:57:5 + --> $DIR/indexing_slicing.rs:56:5 | LL | v[N]; | ^^^^ @@ -202,7 +202,7 @@ LL | v[N]; = help: Consider using `.get(n)` or `.get_mut(n)` instead error: indexing may panic. - --> $DIR/indexing_slicing.rs:58:5 + --> $DIR/indexing_slicing.rs:57:5 | LL | v[M]; | ^^^^ diff --git a/tests/ui/out_of_bounds_indexing/empty_array.stderr b/tests/ui/out_of_bounds_indexing/empty_array.stderr index f6fb03383..2372bf860 100644 --- a/tests/ui/out_of_bounds_indexing/empty_array.stderr +++ b/tests/ui/out_of_bounds_indexing/empty_array.stderr @@ -1,7 +1,7 @@ error: index out of bounds: the len is 0 but the index is 0 --> $DIR/empty_array.rs:6:5 | -LL | empty[0]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. +LL | empty[0]; | ^^^^^^^^ | = note: #[deny(const_err)] on by default diff --git a/tests/ui/out_of_bounds_indexing/issue-3102.stderr b/tests/ui/out_of_bounds_indexing/issue-3102.stderr index f55aeee39..516c1df40 100644 --- a/tests/ui/out_of_bounds_indexing/issue-3102.stderr +++ b/tests/ui/out_of_bounds_indexing/issue-3102.stderr @@ -1,30 +1,16 @@ -error: statement with no effect - --> $DIR/issue-3102.rs:8:5 - | -LL | &x[num..10]; // should trigger out of bounds error - | ^^^^^^^^^^^^ - | - = note: `-D clippy::no-effect` implied by `-D warnings` - error: range is out of bounds - --> $DIR/issue-3102.rs:8:13 + --> $DIR/issue-3102.rs:9:13 | LL | &x[num..10]; // should trigger out of bounds error | ^^ | = note: `-D clippy::out-of-bounds-indexing` implied by `-D warnings` -error: statement with no effect - --> $DIR/issue-3102.rs:9:5 - | -LL | &x[10..num]; // should trigger out of bounds error - | ^^^^^^^^^^^^ - error: range is out of bounds - --> $DIR/issue-3102.rs:9:8 + --> $DIR/issue-3102.rs:10:8 | LL | &x[10..num]; // should trigger out of bounds error | ^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors From 022b9876c2c70ac80174a4c78826113b9a965cbc Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 17 Jul 2019 08:08:26 +0200 Subject: [PATCH 044/133] UI Test Cleanup: Extract match_ref_pats tests --- tests/ui/match_ref_pats.rs | 73 +++++++++++++++++ tests/ui/match_ref_pats.stderr | 86 +++++++++++++++++++ tests/ui/matches.rs | 68 +-------------- tests/ui/matches.stderr | 146 +++++++-------------------------- 4 files changed, 191 insertions(+), 182 deletions(-) create mode 100644 tests/ui/match_ref_pats.rs create mode 100644 tests/ui/match_ref_pats.stderr diff --git a/tests/ui/match_ref_pats.rs b/tests/ui/match_ref_pats.rs new file mode 100644 index 000000000..d26b59db9 --- /dev/null +++ b/tests/ui/match_ref_pats.rs @@ -0,0 +1,73 @@ +#![warn(clippy::match_ref_pats)] + +fn ref_pats() { + { + let v = &Some(0); + match v { + &Some(v) => println!("{:?}", v), + &None => println!("none"), + } + match v { + // This doesn't trigger; we have a different pattern. + &Some(v) => println!("some"), + other => println!("other"), + } + } + let tup = &(1, 2); + match tup { + &(v, 1) => println!("{}", v), + _ => println!("none"), + } + // Special case: using `&` both in expr and pats. + let w = Some(0); + match &w { + &Some(v) => println!("{:?}", v), + &None => println!("none"), + } + // False positive: only wildcard pattern. + let w = Some(0); + match w { + _ => println!("none"), + } + + let a = &Some(0); + if let &None = a { + println!("none"); + } + + let b = Some(0); + if let &None = &b { + println!("none"); + } +} + +mod ice_3719 { + macro_rules! foo_variant( + ($idx:expr) => (Foo::get($idx).unwrap()) + ); + + enum Foo { + A, + B, + } + + impl Foo { + fn get(idx: u8) -> Option<&'static Self> { + match idx { + 0 => Some(&Foo::A), + 1 => Some(&Foo::B), + _ => None, + } + } + } + + fn ice_3719() { + // ICE #3719 + match foo_variant!(0) { + &Foo::A => println!("A"), + _ => println!("Wild"), + } + } +} + +fn main() {} diff --git a/tests/ui/match_ref_pats.stderr b/tests/ui/match_ref_pats.stderr new file mode 100644 index 000000000..80e862c8e --- /dev/null +++ b/tests/ui/match_ref_pats.stderr @@ -0,0 +1,86 @@ +error: you don't need to add `&` to all patterns + --> $DIR/match_ref_pats.rs:6:9 + | +LL | / match v { +LL | | &Some(v) => println!("{:?}", v), +LL | | &None => println!("none"), +LL | | } + | |_________^ + | + = note: `-D clippy::match-ref-pats` implied by `-D warnings` +help: instead of prefixing all patterns with `&`, you can dereference the expression + | +LL | match *v { +LL | Some(v) => println!("{:?}", v), +LL | None => println!("none"), + | + +error: you don't need to add `&` to all patterns + --> $DIR/match_ref_pats.rs:17:5 + | +LL | / match tup { +LL | | &(v, 1) => println!("{}", v), +LL | | _ => println!("none"), +LL | | } + | |_____^ +help: instead of prefixing all patterns with `&`, you can dereference the expression + | +LL | match *tup { +LL | (v, 1) => println!("{}", v), + | + +error: you don't need to add `&` to both the expression and the patterns + --> $DIR/match_ref_pats.rs:23:5 + | +LL | / match &w { +LL | | &Some(v) => println!("{:?}", v), +LL | | &None => println!("none"), +LL | | } + | |_____^ +help: try + | +LL | match w { +LL | Some(v) => println!("{:?}", v), +LL | None => println!("none"), + | + +error: you don't need to add `&` to all patterns + --> $DIR/match_ref_pats.rs:34:5 + | +LL | / if let &None = a { +LL | | println!("none"); +LL | | } + | |_____^ +help: instead of prefixing all patterns with `&`, you can dereference the expression + | +LL | if let None = *a { + | ^^^^ ^^ + +error: you don't need to add `&` to both the expression and the patterns + --> $DIR/match_ref_pats.rs:39:5 + | +LL | / if let &None = &b { +LL | | println!("none"); +LL | | } + | |_____^ +help: try + | +LL | if let None = b { + | ^^^^ ^ + +error: you don't need to add `&` to all patterns + --> $DIR/match_ref_pats.rs:66:9 + | +LL | / match foo_variant!(0) { +LL | | &Foo::A => println!("A"), +LL | | _ => println!("Wild"), +LL | | } + | |_________^ +help: instead of prefixing all patterns with `&`, you can dereference the expression + | +LL | match *foo_variant!(0) { +LL | Foo::A => println!("A"), + | + +error: aborting due to 6 previous errors + diff --git a/tests/ui/matches.rs b/tests/ui/matches.rs index 0360cc739..44725db97 100644 --- a/tests/ui/matches.rs +++ b/tests/ui/matches.rs @@ -5,47 +5,6 @@ fn dummy() {} -fn ref_pats() { - { - let v = &Some(0); - match v { - &Some(v) => println!("{:?}", v), - &None => println!("none"), - } - match v { - // This doesn't trigger; we have a different pattern. - &Some(v) => println!("some"), - other => println!("other"), - } - } - let tup = &(1, 2); - match tup { - &(v, 1) => println!("{}", v), - _ => println!("none"), - } - // Special case: using `&` both in expr and pats. - let w = Some(0); - match &w { - &Some(v) => println!("{:?}", v), - &None => println!("none"), - } - // False positive: only wildcard pattern. - let w = Some(0); - match w { - _ => println!("none"), - } - - let a = &Some(0); - if let &None = a { - println!("none"); - } - - let b = Some(0); - if let &None = &b { - println!("none"); - } -} - fn match_wild_err_arm() { let x: Result = Ok(3); @@ -136,29 +95,4 @@ fn match_wild_err_arm() { } } -macro_rules! foo_variant( - ($idx:expr) => (Foo::get($idx).unwrap()) -); - -enum Foo { - A, - B, -} - -impl Foo { - fn get(idx: u8) -> Option<&'static Self> { - match idx { - 0 => Some(&Foo::A), - 1 => Some(&Foo::B), - _ => None, - } - } -} - -fn main() { - // ICE #3719 - match foo_variant!(0) { - &Foo::A => println!("A"), - _ => println!("Wild"), - } -} +fn main() {} diff --git a/tests/ui/matches.stderr b/tests/ui/matches.stderr index 232ae2800..f47e976e8 100644 --- a/tests/ui/matches.stderr +++ b/tests/ui/matches.stderr @@ -1,75 +1,5 @@ -error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:11:9 - | -LL | / match v { -LL | | &Some(v) => println!("{:?}", v), -LL | | &None => println!("none"), -LL | | } - | |_________^ - | - = note: `-D clippy::match-ref-pats` implied by `-D warnings` -help: instead of prefixing all patterns with `&`, you can dereference the expression - | -LL | match *v { -LL | Some(v) => println!("{:?}", v), -LL | None => println!("none"), - | - -error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:22:5 - | -LL | / match tup { -LL | | &(v, 1) => println!("{}", v), -LL | | _ => println!("none"), -LL | | } - | |_____^ -help: instead of prefixing all patterns with `&`, you can dereference the expression - | -LL | match *tup { -LL | (v, 1) => println!("{}", v), - | - -error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:28:5 - | -LL | / match &w { -LL | | &Some(v) => println!("{:?}", v), -LL | | &None => println!("none"), -LL | | } - | |_____^ -help: try - | -LL | match w { -LL | Some(v) => println!("{:?}", v), -LL | None => println!("none"), - | - -error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:39:5 - | -LL | / if let &None = a { -LL | | println!("none"); -LL | | } - | |_____^ -help: instead of prefixing all patterns with `&`, you can dereference the expression - | -LL | if let None = *a { - | ^^^^ ^^ - -error: you don't need to add `&` to both the expression and the patterns - --> $DIR/matches.rs:44:5 - | -LL | / if let &None = &b { -LL | | println!("none"); -LL | | } - | |_____^ -help: try - | -LL | if let None = b { - | ^^^^ ^ - error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:55:9 + --> $DIR/matches.rs:14:9 | LL | Err(_) => panic!("err"), | ^^^^^^ @@ -78,26 +8,26 @@ LL | Err(_) => panic!("err"), = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:54:18 + --> $DIR/matches.rs:13:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | = note: `-D clippy::match-same-arms` implied by `-D warnings` note: same as this - --> $DIR/matches.rs:53:18 + --> $DIR/matches.rs:12:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:53:9 + --> $DIR/matches.rs:12:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:61:9 + --> $DIR/matches.rs:20:9 | LL | Err(_) => panic!(), | ^^^^^^ @@ -105,25 +35,25 @@ LL | Err(_) => panic!(), = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:60:18 + --> $DIR/matches.rs:19:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:59:18 + --> $DIR/matches.rs:18:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:59:9 + --> $DIR/matches.rs:18:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: Err(_) will match all errors, maybe not a good idea - --> $DIR/matches.rs:67:9 + --> $DIR/matches.rs:26:9 | LL | Err(_) => { | ^^^^^^ @@ -131,144 +61,130 @@ LL | Err(_) => { = note: to remove this warning, match each error separately or use unreachable macro error: this `match` has identical arm bodies - --> $DIR/matches.rs:66:18 + --> $DIR/matches.rs:25:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:65:18 + --> $DIR/matches.rs:24:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:65:9 + --> $DIR/matches.rs:24:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:75:18 + --> $DIR/matches.rs:34:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:74:18 + --> $DIR/matches.rs:33:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:74:9 + --> $DIR/matches.rs:33:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:82:18 + --> $DIR/matches.rs:41:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:81:18 + --> $DIR/matches.rs:40:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:81:9 + --> $DIR/matches.rs:40:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:88:18 + --> $DIR/matches.rs:47:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:87:18 + --> $DIR/matches.rs:46:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:87:9 + --> $DIR/matches.rs:46:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:94:18 + --> $DIR/matches.rs:53:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:93:18 + --> $DIR/matches.rs:52:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:93:9 + --> $DIR/matches.rs:52:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:117:29 + --> $DIR/matches.rs:76:29 | LL | (Ok(_), Some(x)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:116:29 + --> $DIR/matches.rs:75:29 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^^^^^ help: consider refactoring into `(Ok(x), Some(_)) | (Ok(_), Some(x))` - --> $DIR/matches.rs:116:9 + --> $DIR/matches.rs:75:9 | LL | (Ok(x), Some(_)) => println!("ok {}", x), | ^^^^^^^^^^^^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: this `match` has identical arm bodies - --> $DIR/matches.rs:132:18 + --> $DIR/matches.rs:91:18 | LL | Ok(_) => println!("ok"), | ^^^^^^^^^^^^^^ | note: same as this - --> $DIR/matches.rs:131:18 + --> $DIR/matches.rs:90:18 | LL | Ok(3) => println!("ok"), | ^^^^^^^^^^^^^^ help: consider refactoring into `Ok(3) | Ok(_)` - --> $DIR/matches.rs:131:9 + --> $DIR/matches.rs:90:9 | LL | Ok(3) => println!("ok"), | ^^^^^ = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) -error: you don't need to add `&` to all patterns - --> $DIR/matches.rs:160:5 - | -LL | / match foo_variant!(0) { -LL | | &Foo::A => println!("A"), -LL | | _ => println!("Wild"), -LL | | } - | |_____^ -help: instead of prefixing all patterns with `&`, you can dereference the expression - | -LL | match *foo_variant!(0) { -LL | Foo::A => println!("A"), - | - -error: aborting due to 18 previous errors +error: aborting due to 12 previous errors From 0513202d25c67ebeb5a02f9fe9dad5dea3296140 Mon Sep 17 00:00:00 2001 From: Darth-Revan Date: Sat, 6 Jul 2019 20:13:38 +0200 Subject: [PATCH 045/133] Implement lint for inherent to_string() method. --- CHANGELOG.md | 2 + README.md | 2 +- clippy_lints/src/inherent_to_string.rs | 148 +++++++++++++++++++++++++ clippy_lints/src/lib.rs | 6 + src/lintlist/mod.rs | 16 ++- tests/ui/inherent_to_string.rs | 84 ++++++++++++++ tests/ui/inherent_to_string.stderr | 24 ++++ 7 files changed, 280 insertions(+), 2 deletions(-) create mode 100644 clippy_lints/src/inherent_to_string.rs create mode 100644 tests/ui/inherent_to_string.rs create mode 100644 tests/ui/inherent_to_string.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 461adb729..ff5aebbc8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -973,6 +973,8 @@ Released 2018-09-13 [`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask [`infallible_destructuring_match`]: https://rust-lang.github.io/rust-clippy/master/index.html#infallible_destructuring_match [`infinite_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#infinite_iter +[`inherent_to_string`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string +[`inherent_to_string_shadow_display`]: https://rust-lang.github.io/rust-clippy/master/index.html#inherent_to_string_shadow_display [`inline_always`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_always [`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one diff --git a/README.md b/README.md index 24bda9bbe..1e649d898 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 306 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 308 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: diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs new file mode 100644 index 000000000..57ffdf78d --- /dev/null +++ b/clippy_lints/src/inherent_to_string.rs @@ -0,0 +1,148 @@ +use if_chain::if_chain; +use rustc::hir::{ImplItem, ImplItemKind}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_lint_pass, declare_tool_lint}; + +use crate::utils::{ + get_trait_def_id, implements_trait, in_macro_or_desugar, match_type, paths, return_ty, span_help_and_lint, + trait_ref_of_method, walk_ptrs_ty, +}; + +declare_clippy_lint! { + /// **What id does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String`. + /// + /// **Why is this bad?** This method is also implicitly defined if a type implements the `Display` trait. As the functionality of `Display` is much more versatile, it should be preferred. + /// + /// **Known problems:** None + /// + /// ** Example:** + /// + /// ```rust,ignore + /// // Bad + /// pub struct A; + /// + /// impl A { + /// pub fn to_string(&self) -> String { + /// "I am A".to_string() + /// } + /// } + /// // Good + /// use std::fmt; + /// + /// pub struct A; + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "I am A") + /// } + /// } + /// ``` + pub INHERENT_TO_STRING, + style, + "type implements inherent method 'to_string()', but should instead implement the 'Display' trait" +} + +declare_clippy_lint! { + /// **What id does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait. + /// + /// **Why is this bad?** This method is also implicitly defined if a type implements the 'Display' trait. The less versatile inherent method will then shadow the implementation introduced by `Display`. + /// + /// **Known problems:** The inherent method will shadow the implementation by `Display`. If they behave differently, this may lead to confusing situations for users of the respective type. + /// + /// ** Example:** + /// + /// ```rust,ignore + /// // Bad + /// use std::fmt; + /// + /// pub struct A; + /// + /// impl A { + /// pub fn to_string(&self) -> String { + /// "I am A".to_string() + /// } + /// } + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "I am A, too") + /// } + /// } + /// // Good + /// use std::fmt; + /// + /// pub struct A; + /// + /// impl fmt::Display for A { + /// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + /// write!(f, "I am A") + /// } + /// } + /// ``` + pub INHERENT_TO_STRING_SHADOW_DISPLAY, + correctness, + "type implements inherent method 'to_string()', which gets shadowed by the implementation of the 'Display' trait " +} + +declare_lint_pass!(InherentToString => [INHERENT_TO_STRING, INHERENT_TO_STRING_SHADOW_DISPLAY]); + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString { + fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, impl_item: &'tcx ImplItem) { + if in_macro_or_desugar(impl_item.span) { + return; + } + + if_chain! { + // Check if item is a method, called to_string and has a parameter 'self' + if let ImplItemKind::Method(ref signature, _) = impl_item.node; + if impl_item.ident.name.as_str() == "to_string"; + let decl = &signature.decl; + if decl.implicit_self.has_implicit_self(); + + // Check if return type is String + if match_type(cx, return_ty(cx, impl_item.hir_id), &paths::STRING); + + // Filters instances of to_string which are required by a trait + if trait_ref_of_method(cx, impl_item.hir_id).is_none(); + + then { + show_lint(cx, impl_item); + } + } + } +} + +fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem) { + let display_trait_id = + get_trait_def_id(cx, &["core", "fmt", "Display"]).expect("Failed to get trait ID of 'Display'!"); + + // Get the real type of 'self' + let fn_def_id = cx.tcx.hir().local_def_id(item.hir_id); + let self_type = cx.tcx.fn_sig(fn_def_id).input(0); + let self_type = walk_ptrs_ty(self_type.skip_binder()); + + // Emit either a warning or an error + if implements_trait(cx, self_type, display_trait_id, &[]) { + span_help_and_lint( + cx, + INHERENT_TO_STRING_SHADOW_DISPLAY, + item.span, + &format!( + "type '{}' implements inherent method 'to_string() -> String' which shadows the implementation of 'Display'", + self_type.to_string() + ), + &format!("remove the inherent method from type '{}'", self_type.to_string()) + ); + } else { + span_help_and_lint( + cx, + INHERENT_TO_STRING, + item.span, + &format!( + "implementation of inherent method 'to_string() -> String' for type '{}'", + self_type.to_string() + ), + &format!("implement trait 'Display' for type '{}' instead", self_type.to_string()), + ); + } +} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 369a736aa..de7a213d7 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -195,6 +195,7 @@ pub mod indexing_slicing; pub mod infallible_destructuring_match; 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; @@ -585,6 +586,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite); reg.register_late_lint_pass(box checked_conversions::CheckedConversions); reg.register_late_lint_pass(box integer_division::IntegerDivision); + reg.register_late_lint_pass(box inherent_to_string::InherentToString); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -725,6 +727,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { indexing_slicing::OUT_OF_BOUNDS_INDEXING, infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, infinite_iter::INFINITE_ITER, + inherent_to_string::INHERENT_TO_STRING, + inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, int_plus_one::INT_PLUS_ONE, invalid_ref::INVALID_REF, @@ -913,6 +917,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { formatting::SUSPICIOUS_ASSIGNMENT_FORMATTING, formatting::SUSPICIOUS_ELSE_FORMATTING, infallible_destructuring_match::INFALLIBLE_DESTRUCTURING_MATCH, + inherent_to_string::INHERENT_TO_STRING, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, let_if_seq::USELESS_LET_IF_SEQ, @@ -1075,6 +1080,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { functions::NOT_UNSAFE_PTR_ARG_DEREF, indexing_slicing::OUT_OF_BOUNDS_INDEXING, infinite_iter::INFINITE_ITER, + inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, invalid_ref::INVALID_REF, literal_representation::MISTYPED_LITERAL_SUFFIXES, diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 8c49a3b18..59eb92593 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 306] = [ +pub const ALL_LINTS: [Lint; 308] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -728,6 +728,20 @@ pub const ALL_LINTS: [Lint; 306] = [ deprecation: None, module: "infinite_iter", }, + Lint { + name: "inherent_to_string", + group: "style", + desc: "type implements inherent method \'to_string()\', but should instead implement the \'Display\' trait", + deprecation: None, + module: "inherent_to_string", + }, + Lint { + name: "inherent_to_string_shadow_display", + group: "correctness", + desc: "type implements inherent method \'to_string()\', which gets shadowed by the implementation of the \'Display\' trait ", + deprecation: None, + module: "inherent_to_string", + }, Lint { name: "inline_always", group: "pedantic", diff --git a/tests/ui/inherent_to_string.rs b/tests/ui/inherent_to_string.rs new file mode 100644 index 000000000..78f24a3c9 --- /dev/null +++ b/tests/ui/inherent_to_string.rs @@ -0,0 +1,84 @@ +#![warn(clippy::inherent_to_string)] +//#![deny(clippy::inherent_to_string_shadow)] + +use std::fmt; + +trait FalsePositive { + fn to_string(&self) -> String; +} + +struct A; +struct B; +struct C; +struct D; +struct E; + +impl A { + // Should be detected; emit warning + fn to_string(&self) -> String { + "A.to_string()".to_string() + } + + // Should not be detected as it does not match the function signature + fn to_str(&self) -> String { + "A.to_str()".to_string() + } +} + +// Should not be detected as it is a free function +fn to_string() -> String { + "free to_string()".to_string() +} + +impl B { + // Should not be detected, wrong return type + fn to_string(&self) -> i32 { + 42 + } +} + +impl C { + // Should be detected and emit error as C also implements Display + fn to_string(&self) -> String { + "C.to_string()".to_string() + } +} + +impl fmt::Display for C { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "impl Display for C") + } +} + +impl FalsePositive for D { + // Should not be detected, as it is a trait function + fn to_string(&self) -> String { + "impl FalsePositive for D".to_string() + } +} + +impl E { + // Should not be detected, as it is not bound to an instance + fn to_string() -> String { + "E::to_string()".to_string() + } +} + +fn main() { + let a = A; + a.to_string(); + a.to_str(); + + to_string(); + + let b = B; + b.to_string(); + + let c = C; + C.to_string(); + + let d = D; + d.to_string(); + + E::to_string(); +} diff --git a/tests/ui/inherent_to_string.stderr b/tests/ui/inherent_to_string.stderr new file mode 100644 index 000000000..85fb06a22 --- /dev/null +++ b/tests/ui/inherent_to_string.stderr @@ -0,0 +1,24 @@ +error: implementation of inherent method 'to_string() -> String' for type 'A' + --> $DIR/inherent_to_string.rs:18:5 + | +LL | / fn to_string(&self) -> String { +LL | | "A.to_string()".to_string() +LL | | } + | |_____^ + | + = note: `-D clippy::inherent-to-string` implied by `-D warnings` + = help: implement trait 'Display' for type 'A' instead + +error: type 'C' implements inherent method 'to_string() -> String' which shadows the implementation of 'Display' + --> $DIR/inherent_to_string.rs:42:5 + | +LL | / fn to_string(&self) -> String { +LL | | "C.to_string()".to_string() +LL | | } + | |_____^ + | + = note: #[deny(clippy::inherent_to_string_shadow_display)] on by default + = help: remove the inherent method from type 'C' + +error: aborting due to 2 previous errors + From f0dc97965a6c69109d836671905f299f955928b4 Mon Sep 17 00:00:00 2001 From: Darth-Revan <18002263+Darth-Revan@users.noreply.github.com> Date: Mon, 15 Jul 2019 18:43:47 +0200 Subject: [PATCH 046/133] Corrections for PR review. --- clippy_lints/src/inherent_to_string.rs | 28 ++++++++++++++++---------- tests/ui/inherent_to_string.rs | 2 +- tests/ui/inherent_to_string.stderr | 18 ++++++++++++----- 3 files changed, 31 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index 57ffdf78d..ef0a75438 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -17,7 +17,7 @@ declare_clippy_lint! { /// /// ** Example:** /// - /// ```rust,ignore + /// ```rust /// // Bad /// pub struct A; /// @@ -26,6 +26,9 @@ declare_clippy_lint! { /// "I am A".to_string() /// } /// } + /// ``` + /// + /// ```rust /// // Good /// use std::fmt; /// @@ -39,19 +42,19 @@ declare_clippy_lint! { /// ``` pub INHERENT_TO_STRING, style, - "type implements inherent method 'to_string()', but should instead implement the 'Display' trait" + "type implements inherent method `to_string()`, but should instead implement the `Display` trait" } declare_clippy_lint! { /// **What id does:** Checks for the definition of inherent methods with a signature of `to_string(&self) -> String` and if the type implementing this method also implements the `Display` trait. /// - /// **Why is this bad?** This method is also implicitly defined if a type implements the 'Display' trait. The less versatile inherent method will then shadow the implementation introduced by `Display`. + /// **Why is this bad?** This method is also implicitly defined if a type implements the `Display` trait. The less versatile inherent method will then shadow the implementation introduced by `Display`. /// - /// **Known problems:** The inherent method will shadow the implementation by `Display`. If they behave differently, this may lead to confusing situations for users of the respective type. + /// **Known problems:** None /// /// ** Example:** /// - /// ```rust,ignore + /// ```rust /// // Bad /// use std::fmt; /// @@ -68,6 +71,9 @@ declare_clippy_lint! { /// write!(f, "I am A, too") /// } /// } + /// ``` + /// + /// ```rust /// // Good /// use std::fmt; /// @@ -81,7 +87,7 @@ declare_clippy_lint! { /// ``` pub INHERENT_TO_STRING_SHADOW_DISPLAY, correctness, - "type implements inherent method 'to_string()', which gets shadowed by the implementation of the 'Display' trait " + "type implements inherent method `to_string()`, which gets shadowed by the implementation of the `Display` trait " } declare_lint_pass!(InherentToString => [INHERENT_TO_STRING, INHERENT_TO_STRING_SHADOW_DISPLAY]); @@ -114,7 +120,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InherentToString { fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem) { let display_trait_id = - get_trait_def_id(cx, &["core", "fmt", "Display"]).expect("Failed to get trait ID of 'Display'!"); + get_trait_def_id(cx, &["core", "fmt", "Display"]).expect("Failed to get trait ID of `Display`!"); // Get the real type of 'self' let fn_def_id = cx.tcx.hir().local_def_id(item.hir_id); @@ -128,10 +134,10 @@ fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem) { INHERENT_TO_STRING_SHADOW_DISPLAY, item.span, &format!( - "type '{}' implements inherent method 'to_string() -> String' which shadows the implementation of 'Display'", + "type `{}` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display`", self_type.to_string() ), - &format!("remove the inherent method from type '{}'", self_type.to_string()) + &format!("remove the inherent method from type `{}`", self_type.to_string()) ); } else { span_help_and_lint( @@ -139,10 +145,10 @@ fn show_lint(cx: &LateContext<'_, '_>, item: &ImplItem) { INHERENT_TO_STRING, item.span, &format!( - "implementation of inherent method 'to_string() -> String' for type '{}'", + "implementation of inherent method `to_string(&self) -> String` for type `{}`", self_type.to_string() ), - &format!("implement trait 'Display' for type '{}' instead", self_type.to_string()), + &format!("implement trait `Display` for type `{}` instead", self_type.to_string()), ); } } diff --git a/tests/ui/inherent_to_string.rs b/tests/ui/inherent_to_string.rs index 78f24a3c9..9f81c027f 100644 --- a/tests/ui/inherent_to_string.rs +++ b/tests/ui/inherent_to_string.rs @@ -1,5 +1,5 @@ #![warn(clippy::inherent_to_string)] -//#![deny(clippy::inherent_to_string_shadow)] +#![deny(clippy::inherent_to_string_shadow)] use std::fmt; diff --git a/tests/ui/inherent_to_string.stderr b/tests/ui/inherent_to_string.stderr index 85fb06a22..4a967f349 100644 --- a/tests/ui/inherent_to_string.stderr +++ b/tests/ui/inherent_to_string.stderr @@ -1,4 +1,4 @@ -error: implementation of inherent method 'to_string() -> String' for type 'A' +error: implementation of inherent method `to_string(&self) -> String` for type `A` --> $DIR/inherent_to_string.rs:18:5 | LL | / fn to_string(&self) -> String { @@ -7,9 +7,9 @@ LL | | } | |_____^ | = note: `-D clippy::inherent-to-string` implied by `-D warnings` - = help: implement trait 'Display' for type 'A' instead + = help: implement trait `Display` for type `A` instead -error: type 'C' implements inherent method 'to_string() -> String' which shadows the implementation of 'Display' +error: type `C` implements inherent method `to_string(&self) -> String` which shadows the implementation of `Display` --> $DIR/inherent_to_string.rs:42:5 | LL | / fn to_string(&self) -> String { @@ -18,7 +18,15 @@ LL | | } | |_____^ | = note: #[deny(clippy::inherent_to_string_shadow_display)] on by default - = help: remove the inherent method from type 'C' + = help: remove the inherent method from type `C` -error: aborting due to 2 previous errors +error: unknown clippy lint: clippy::inherent_to_string_shadow + --> $DIR/inherent_to_string.rs:2:9 + | +LL | #![deny(clippy::inherent_to_string_shadow)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` + +error: aborting due to 3 previous errors From b7145fbb660fa0dfad14b9ba7d47d1459b103e15 Mon Sep 17 00:00:00 2001 From: Darth-Revan <18002263+Darth-Revan@users.noreply.github.com> Date: Tue, 16 Jul 2019 18:29:37 +0200 Subject: [PATCH 047/133] Fix "unkown clippy lint" error in UI test. --- src/lintlist/mod.rs | 4 ++-- tests/ui/inherent_to_string.rs | 2 +- tests/ui/inherent_to_string.stderr | 14 +++++--------- 3 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 59eb92593..2d9e800b6 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -731,14 +731,14 @@ pub const ALL_LINTS: [Lint; 308] = [ Lint { name: "inherent_to_string", group: "style", - desc: "type implements inherent method \'to_string()\', but should instead implement the \'Display\' trait", + desc: "type implements inherent method `to_string()`, but should instead implement the `Display` trait", deprecation: None, module: "inherent_to_string", }, Lint { name: "inherent_to_string_shadow_display", group: "correctness", - desc: "type implements inherent method \'to_string()\', which gets shadowed by the implementation of the \'Display\' trait ", + desc: "type implements inherent method `to_string()`, which gets shadowed by the implementation of the `Display` trait ", deprecation: None, module: "inherent_to_string", }, diff --git a/tests/ui/inherent_to_string.rs b/tests/ui/inherent_to_string.rs index 9f81c027f..fc21b5cbc 100644 --- a/tests/ui/inherent_to_string.rs +++ b/tests/ui/inherent_to_string.rs @@ -1,5 +1,5 @@ #![warn(clippy::inherent_to_string)] -#![deny(clippy::inherent_to_string_shadow)] +#![deny(clippy::inherent_to_string_shadow_display)] use std::fmt; diff --git a/tests/ui/inherent_to_string.stderr b/tests/ui/inherent_to_string.stderr index 4a967f349..5252a1688 100644 --- a/tests/ui/inherent_to_string.stderr +++ b/tests/ui/inherent_to_string.stderr @@ -17,16 +17,12 @@ LL | | "C.to_string()".to_string() LL | | } | |_____^ | - = note: #[deny(clippy::inherent_to_string_shadow_display)] on by default - = help: remove the inherent method from type `C` - -error: unknown clippy lint: clippy::inherent_to_string_shadow +note: lint level defined here --> $DIR/inherent_to_string.rs:2:9 | -LL | #![deny(clippy::inherent_to_string_shadow)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: `-D clippy::unknown-clippy-lints` implied by `-D warnings` +LL | #![deny(clippy::inherent_to_string_shadow_display)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: remove the inherent method from type `C` -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors From 9e5e0f8f8425e6421699409a099ac4303162db25 Mon Sep 17 00:00:00 2001 From: daxpedda Date: Wed, 17 Jul 2019 20:44:09 +0200 Subject: [PATCH 048/133] Improved imports --- clippy_lints/src/implicit_return.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index a2a214831..4df9789f3 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -10,7 +10,7 @@ use rustc::{ lint::{LateContext, LateLintPass, LintArray, LintPass}, }; use rustc_errors::Applicability; -use syntax_pos::Span; +use syntax::source_map::Span; declare_clippy_lint! { /// **What it does:** Checks for missing return statements at the end of a block. @@ -138,7 +138,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImplicitReturn { _: FnKind<'tcx>, _: &'tcx FnDecl, body: &'tcx Body, - span: syntax::source_map::Span, + span: Span, _: HirId, ) { let def_id = cx.tcx.hir().body_owner_def_id(body.id()); From 35b7a98f4fd228a826c88499c5374acdd772e09f Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 17 Jul 2019 21:13:33 +0200 Subject: [PATCH 049/133] Decrease maximum length for stderr files Now at 275. --- clippy_dev/src/stderr_length_check.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_dev/src/stderr_length_check.rs b/clippy_dev/src/stderr_length_check.rs index ba8e5f83e..3049c45dd 100644 --- a/clippy_dev/src/stderr_length_check.rs +++ b/clippy_dev/src/stderr_length_check.rs @@ -7,7 +7,7 @@ use std::io::prelude::*; // The maximum length allowed for stderr files. // // We limit this because small files are easier to deal with than bigger files. -const LIMIT: usize = 320; +const LIMIT: usize = 275; pub fn check() { let stderr_files = stderr_files(); From fc57b43f79f2e89dfb8d0e0f789fb9dd671e0d36 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 18 Jul 2019 17:23:22 +0200 Subject: [PATCH 050/133] Format code --- clippy_lints/src/double_comparison.rs | 1 + mini-macro/src/lib.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 228d53ff1..0c7c81f40 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -63,6 +63,7 @@ impl<'a, 'tcx> DoubleComparisons { ); }}; } + #[rustfmt::skip] match (op, lkind, rkind) { (BinOpKind::Or, BinOpKind::Eq, BinOpKind::Lt) | (BinOpKind::Or, BinOpKind::Lt, BinOpKind::Eq) => { lint_double_comparison!(<=) diff --git a/mini-macro/src/lib.rs b/mini-macro/src/lib.rs index ec489344a..ddb40dace 100644 --- a/mini-macro/src/lib.rs +++ b/mini-macro/src/lib.rs @@ -2,13 +2,17 @@ #![deny(rust_2018_idioms)] extern crate proc_macro; -use proc_macro::{TokenStream, quote}; +use proc_macro::{quote, TokenStream}; #[proc_macro_derive(ClippyMiniMacroTest)] pub fn mini_macro(_: TokenStream) -> TokenStream { quote!( - #[allow(unused)] fn needless_take_by_value(s: String) { println!("{}", s.len()); } - #[allow(unused)] fn needless_loop(items: &[u8]) { + #[allow(unused)] + fn needless_take_by_value(s: String) { + println!("{}", s.len()); + } + #[allow(unused)] + fn needless_loop(items: &[u8]) { for i in 0..items.len() { println!("{}", items[i]); } From e6bbed909ee516b5e50bfb1a3b2b86a6b2988bc3 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Fri, 19 Jul 2019 02:43:10 +0800 Subject: [PATCH 051/133] Add test --- tests/ui/issue_4266.rs | 24 ++++++++++++++++++++++++ tests/ui/issue_4266.stderr | 16 ++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/ui/issue_4266.rs create mode 100644 tests/ui/issue_4266.stderr diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs new file mode 100644 index 000000000..dbf482ea1 --- /dev/null +++ b/tests/ui/issue_4266.rs @@ -0,0 +1,24 @@ +// compile-flags: --edition 2018 +#![feature(async_await)] +#![allow(dead_code)] + +async fn sink1<'a>(_: &'a str) {} // lint +async fn sink1_elided(_: &str) {} // ok + +async fn one_to_one<'a>(s: &'a str) -> &'a str { s } // lint +async fn one_to_one_elided(s: &str) -> &str { s } // ok +async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { a } // ok +// async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn + +// #3988 +struct Foo; +impl Foo { + pub async fn foo(&mut self) {} // ok +} + +// rust-lang/rust#61115 +async fn print(s: &str) { // ok + println!("{}", s); +} + +fn main() {} diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr new file mode 100644 index 000000000..3c9740c4a --- /dev/null +++ b/tests/ui/issue_4266.stderr @@ -0,0 +1,16 @@ +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) + --> $DIR/issue_4266.rs:5:1 + | +LL | async fn sink1<'a>(_: &'a str) {} // lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::needless-lifetimes` implied by `-D warnings` + +error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) + --> $DIR/issue_4266.rs:8:1 + | +LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { s } // lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From deb586a0c6987d6babd94f466765b97242592a7c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 19 Jul 2019 00:35:32 +0200 Subject: [PATCH 052/133] rustup https://github.com/rust-lang/rust/pull/62764 (was merged as part of https://github.com/rust-lang/rust/pull/62782 ) --- tests/ui/absurd-extreme-comparisons.stderr | 2 +- tests/ui/bit_masks.stderr | 2 +- tests/ui/cstring.stderr | 2 +- tests/ui/derive.stderr | 2 +- tests/ui/drop_bounds.stderr | 2 +- tests/ui/for_loop_over_option_result.stderr | 4 ++-- tests/ui/if_same_then_else.stderr | 2 +- tests/ui/indexing_slicing.stderr | 2 +- tests/ui/infinite_iter.stderr | 2 +- tests/ui/infinite_loop.stderr | 2 +- tests/ui/invalid_ref.stderr | 2 +- tests/ui/lint_without_lint_pass.stderr | 2 +- tests/ui/match_bool.stderr | 2 +- tests/ui/mistyped_literal_suffix.stderr | 2 +- tests/ui/never_loop.stderr | 2 +- tests/ui/non_copy_const.stderr | 4 ++-- tests/ui/out_of_bounds_indexing/empty_array.stderr | 2 +- tests/ui/outer_expn_info.stderr | 2 +- tests/ui/proc_macro.stderr | 2 +- tests/ui/suspicious_arithmetic_impl.stderr | 2 +- tests/ui/unnecessary_clone.stderr | 2 +- tests/ui/zero_div_zero.stderr | 2 +- 22 files changed, 24 insertions(+), 24 deletions(-) diff --git a/tests/ui/absurd-extreme-comparisons.stderr b/tests/ui/absurd-extreme-comparisons.stderr index b18a943c5..c22c7eb75 100644 --- a/tests/ui/absurd-extreme-comparisons.stderr +++ b/tests/ui/absurd-extreme-comparisons.stderr @@ -141,7 +141,7 @@ error: <-comparison of unit values detected. This will always be false LL | () < {}; | ^^^^^^^ | - = note: #[deny(clippy::unit_cmp)] on by default + = note: `#[deny(clippy::unit_cmp)]` on by default error: aborting due to 18 previous errors diff --git a/tests/ui/bit_masks.stderr b/tests/ui/bit_masks.stderr index 159db0374..dc5ad6dfb 100644 --- a/tests/ui/bit_masks.stderr +++ b/tests/ui/bit_masks.stderr @@ -12,7 +12,7 @@ error: this operation will always return zero. This is likely not the intended o LL | x & 0 == 0; | ^^^^^ | - = note: #[deny(clippy::erasing_op)] on by default + = note: `#[deny(clippy::erasing_op)]` on by default error: incompatible bit mask: `_ & 2` can never be equal to `1` --> $DIR/bit_masks.rs:17:5 diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index a2fc07d4a..8c86249dc 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -4,7 +4,7 @@ error: you are getting the inner pointer of a temporary `CString` LL | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: #[deny(clippy::temporary_cstring_as_ptr)] on by default + = note: `#[deny(clippy::temporary_cstring_as_ptr)]` on by default = note: that pointer will be invalid outside this expression help: assign the `CString` to a variable to extend its lifetime --> $DIR/cstring.rs:7:5 diff --git a/tests/ui/derive.stderr b/tests/ui/derive.stderr index fc87c7d15..875018961 100644 --- a/tests/ui/derive.stderr +++ b/tests/ui/derive.stderr @@ -4,7 +4,7 @@ error: you are deriving `Hash` but have implemented `PartialEq` explicitly LL | #[derive(Hash)] | ^^^^ | - = note: #[deny(clippy::derive_hash_xor_eq)] on by default + = note: `#[deny(clippy::derive_hash_xor_eq)]` on by default note: `PartialEq` implemented here --> $DIR/derive.rs:19:1 | diff --git a/tests/ui/drop_bounds.stderr b/tests/ui/drop_bounds.stderr index cc87913ec..5d360ef30 100644 --- a/tests/ui/drop_bounds.stderr +++ b/tests/ui/drop_bounds.stderr @@ -4,7 +4,7 @@ error: Bounds of the form `T: Drop` are useless. Use `std::mem::needs_drop` to d LL | fn foo() {} | ^^^^ | - = note: #[deny(clippy::drop_bounds)] on by default + = note: `#[deny(clippy::drop_bounds)]` on by default error: Bounds of the form `T: Drop` are useless. Use `std::mem::needs_drop` to detect if a type has drop glue. --> $DIR/drop_bounds.rs:5:8 diff --git a/tests/ui/for_loop_over_option_result.stderr b/tests/ui/for_loop_over_option_result.stderr index 5414bfcf9..194a0bfec 100644 --- a/tests/ui/for_loop_over_option_result.stderr +++ b/tests/ui/for_loop_over_option_result.stderr @@ -30,7 +30,7 @@ error: you are iterating over `Iterator::next()` which is an Option; this will c LL | for x in v.iter().next() { | ^^^^^^^^^^^^^^^ | - = note: #[deny(clippy::iter_next_loop)] on by default + = note: `#[deny(clippy::iter_next_loop)]` on by default error: for loop over `v.iter().next().and(Some(0))`, which is an `Option`. This is more readably written as an `if let` statement. --> $DIR/for_loop_over_option_result.rs:31:14 @@ -57,7 +57,7 @@ LL | | break; LL | | } | |_____^ | - = note: #[deny(clippy::never_loop)] on by default + = note: `#[deny(clippy::never_loop)]` on by default error: this loop never actually loops --> $DIR/for_loop_over_option_result.rs:53:5 diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index fa42afff0..d9424334c 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -236,7 +236,7 @@ error: this `if` has the same condition as a previous if LL | } else if true { | ^^^^ | - = note: #[deny(clippy::ifs_same_cond)] on by default + = note: `#[deny(clippy::ifs_same_cond)]` on by default note: same as this --> $DIR/if_same_then_else.rs:235:8 | diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index f075de506..b2840f7b5 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -4,7 +4,7 @@ error: index out of bounds: the len is 4 but the index is 4 LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. | ^^^^ | - = note: #[deny(const_err)] on by default + = note: `#[deny(const_err)]` on by default error: index out of bounds: the len is 4 but the index is 8 --> $DIR/indexing_slicing.rs:19:5 diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index 564c2b437..ec30a54d3 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -111,7 +111,7 @@ error: infinite iteration detected LL | let _: HashSet = (0..).collect(); // Infinite iter | ^^^^^^^^^^^^^^^ | - = note: #[deny(clippy::infinite_iter)] on by default + = note: `#[deny(clippy::infinite_iter)]` on by default error: aborting due to 15 previous errors diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index a3fc591c1..6f0332fa8 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -4,7 +4,7 @@ error: Variable in the condition are not mutated in the loop body. This either l LL | while y < 10 { | ^^^^^^ | - = note: #[deny(clippy::while_immutable_condition)] on by default + = note: `#[deny(clippy::while_immutable_condition)]` on by default error: Variable in the condition are not mutated in the loop body. This either leads to an infinite or to a never running loop. --> $DIR/infinite_loop.rs:28:11 diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr index 42a11fe7e..aeef3892d 100644 --- a/tests/ui/invalid_ref.stderr +++ b/tests/ui/invalid_ref.stderr @@ -4,7 +4,7 @@ error: reference to zeroed memory LL | let ref_zero: &T = std::mem::zeroed(); // warning | ^^^^^^^^^^^^^^^^^^ | - = note: #[deny(clippy::invalid_ref)] on by default + = note: `#[deny(clippy::invalid_ref)]` on by default = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html error: reference to zeroed memory diff --git a/tests/ui/lint_without_lint_pass.stderr b/tests/ui/lint_without_lint_pass.stderr index 9d0b0d627..0559cee70 100644 --- a/tests/ui/lint_without_lint_pass.stderr +++ b/tests/ui/lint_without_lint_pass.stderr @@ -13,7 +13,7 @@ note: lint level defined here | LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ - = note: #[deny(clippy::lint_without_lint_pass)] implied by #[deny(clippy::internal)] + = note: `#[deny(clippy::lint_without_lint_pass)]` implied by `#[deny(clippy::internal)]` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) error: aborting due to previous error diff --git a/tests/ui/match_bool.stderr b/tests/ui/match_bool.stderr index 193e6c172..5c65d2fed 100644 --- a/tests/ui/match_bool.stderr +++ b/tests/ui/match_bool.stderr @@ -83,7 +83,7 @@ error: equal expressions as operands to `&&` LL | match test && test { | ^^^^^^^^^^^^ | - = note: #[deny(clippy::eq_op)] on by default + = note: `#[deny(clippy::eq_op)]` on by default error: you seem to be trying to match on a boolean expression --> $DIR/match_bool.rs:36:5 diff --git a/tests/ui/mistyped_literal_suffix.stderr b/tests/ui/mistyped_literal_suffix.stderr index c3fed6ae8..17c8b3230 100644 --- a/tests/ui/mistyped_literal_suffix.stderr +++ b/tests/ui/mistyped_literal_suffix.stderr @@ -4,7 +4,7 @@ error: mistyped literal suffix LL | let fail14 = 2_32; | ^^^^ help: did you mean to write: `2_i32` | - = note: #[deny(clippy::mistyped_literal_suffixes)] on by default + = note: `#[deny(clippy::mistyped_literal_suffixes)]` on by default error: mistyped literal suffix --> $DIR/mistyped_literal_suffix.rs:7:18 diff --git a/tests/ui/never_loop.stderr b/tests/ui/never_loop.stderr index 416e14d67..c00b4c78c 100644 --- a/tests/ui/never_loop.stderr +++ b/tests/ui/never_loop.stderr @@ -10,7 +10,7 @@ LL | | break; LL | | } | |_____^ | - = note: #[deny(clippy::never_loop)] on by default + = note: `#[deny(clippy::never_loop)]` on by default error: this loop never actually loops --> $DIR/never_loop.rs:32:5 diff --git a/tests/ui/non_copy_const.stderr b/tests/ui/non_copy_const.stderr index 127649112..634933eac 100644 --- a/tests/ui/non_copy_const.stderr +++ b/tests/ui/non_copy_const.stderr @@ -6,7 +6,7 @@ LL | const ATOMIC: AtomicUsize = AtomicUsize::new(5); //~ ERROR interior mutable | | | help: make this a static item: `static` | - = note: #[deny(clippy::declare_interior_mutable_const)] on by default + = note: `#[deny(clippy::declare_interior_mutable_const)]` on by default error: a const item should never be interior mutable --> $DIR/non_copy_const.rs:11:1 @@ -132,7 +132,7 @@ error: a const item with interior mutability should not be borrowed LL | ATOMIC.store(1, Ordering::SeqCst); //~ ERROR interior mutability | ^^^^^^ | - = note: #[deny(clippy::borrow_interior_mutable_const)] on by default + = note: `#[deny(clippy::borrow_interior_mutable_const)]` on by default = help: assign this const to a local or static variable, and use the variable here error: a const item with interior mutability should not be borrowed diff --git a/tests/ui/out_of_bounds_indexing/empty_array.stderr b/tests/ui/out_of_bounds_indexing/empty_array.stderr index 2372bf860..cda78a47e 100644 --- a/tests/ui/out_of_bounds_indexing/empty_array.stderr +++ b/tests/ui/out_of_bounds_indexing/empty_array.stderr @@ -4,7 +4,7 @@ error: index out of bounds: the len is 0 but the index is 0 LL | empty[0]; | ^^^^^^^^ | - = note: #[deny(const_err)] on by default + = note: `#[deny(const_err)]` on by default error: range is out of bounds --> $DIR/empty_array.rs:7:12 diff --git a/tests/ui/outer_expn_info.stderr b/tests/ui/outer_expn_info.stderr index 2bd3a9835..d9efc91da 100644 --- a/tests/ui/outer_expn_info.stderr +++ b/tests/ui/outer_expn_info.stderr @@ -9,7 +9,7 @@ note: lint level defined here | LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ - = note: #[deny(clippy::outer_expn_info)] implied by #[deny(clippy::internal)] + = note: `#[deny(clippy::outer_expn_info)]` implied by `#[deny(clippy::internal)]` error: aborting due to previous error diff --git a/tests/ui/proc_macro.stderr b/tests/ui/proc_macro.stderr index ec19cd8fc..78c3880db 100644 --- a/tests/ui/proc_macro.stderr +++ b/tests/ui/proc_macro.stderr @@ -4,7 +4,7 @@ error: approximate value of `f{32, 64}::consts::PI` found. Consider using it dir LL | let _x = 3.14; | ^^^^ | - = note: #[deny(clippy::approx_constant)] on by default + = note: `#[deny(clippy::approx_constant)]` on by default error: aborting due to previous error diff --git a/tests/ui/suspicious_arithmetic_impl.stderr b/tests/ui/suspicious_arithmetic_impl.stderr index f818f7b3d..e8a6efc4c 100644 --- a/tests/ui/suspicious_arithmetic_impl.stderr +++ b/tests/ui/suspicious_arithmetic_impl.stderr @@ -12,7 +12,7 @@ error: Suspicious use of binary operator in `AddAssign` impl LL | *self = *self - other; | ^ | - = note: #[deny(clippy::suspicious_op_assign_impl)] on by default + = note: `#[deny(clippy::suspicious_op_assign_impl)]` on by default error: aborting due to 2 previous errors diff --git a/tests/ui/unnecessary_clone.stderr b/tests/ui/unnecessary_clone.stderr index 8d5d54e7d..79b99ff1d 100644 --- a/tests/ui/unnecessary_clone.stderr +++ b/tests/ui/unnecessary_clone.stderr @@ -68,7 +68,7 @@ error: using `clone` on a double-reference; this will copy the reference instead LL | let z: &Vec<_> = y.clone(); | ^^^^^^^^^ | - = note: #[deny(clippy::clone_double_ref)] on by default + = note: `#[deny(clippy::clone_double_ref)]` on by default help: try dereferencing it | LL | let z: &Vec<_> = &(*y).clone(); diff --git a/tests/ui/zero_div_zero.stderr b/tests/ui/zero_div_zero.stderr index 763859f54..c599da8ba 100644 --- a/tests/ui/zero_div_zero.stderr +++ b/tests/ui/zero_div_zero.stderr @@ -4,7 +4,7 @@ error: equal expressions as operands to `/` LL | let nan = 0.0 / 0.0; | ^^^^^^^^^ | - = note: #[deny(clippy::eq_op)] on by default + = note: `#[deny(clippy::eq_op)]` on by default error: constant division of 0.0 with 0.0 will always result in NaN --> $DIR/zero_div_zero.rs:4:15 From 8dc6a462f8cd747ae79ddf5433187ffe57d913df Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 19 Jul 2019 07:18:10 +0200 Subject: [PATCH 053/133] Update pulldown-cmark to 0.5.3 --- clippy_lints/Cargo.toml | 2 +- tests/ui/doc.rs | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index ba67a3ac5..53d7f317f 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -27,7 +27,7 @@ semver = "0.9.0" serde = { version = "1.0", features = ["derive"] } toml = "0.5" unicode-normalization = "0.1" -pulldown-cmark = "0.5.2" +pulldown-cmark = "0.5.3" url = "1.7.0" if_chain = "1.0.0" smallvec = { version = "0.6.5", features = ["union"] } diff --git a/tests/ui/doc.rs b/tests/ui/doc.rs index 039ce5d9c..77620c857 100644 --- a/tests/ui/doc.rs +++ b/tests/ui/doc.rs @@ -178,3 +178,7 @@ fn issue_2210() {} /// This should not cause the lint to trigger: /// #REQ-data-family.lint_partof_exists fn issue_2343() {} + +/// This should not cause an ICE: +/// __|_ _|__||_| +fn pulldown_cmark_crash() {} From a865fe607ca277a55f6715cb254d47681f7fdec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 19 Jul 2019 16:41:10 +0200 Subject: [PATCH 054/133] rustup https://github.com/rust-lang/rust/pull/62679/ --- src/driver.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/driver.rs b/src/driver.rs index 146e3fe2d..cec88be7e 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -63,7 +63,7 @@ fn test_arg_value() { struct ClippyCallbacks; impl rustc_driver::Callbacks for ClippyCallbacks { - fn after_parsing(&mut self, compiler: &interface::Compiler) -> bool { + fn after_parsing(&mut self, compiler: &interface::Compiler) -> rustc_driver::Compilation { let sess = compiler.session(); let mut registry = rustc_plugin::registry::Registry::new( sess, @@ -107,7 +107,7 @@ impl rustc_driver::Callbacks for ClippyCallbacks { sess.plugin_attributes.borrow_mut().extend(attributes); // Continue execution - true + rustc_driver::Compilation::Continue } } From 2cc373ac54e7d244cea22b305cefc1c2d08d81f6 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Fri, 19 Jul 2019 23:03:34 +0800 Subject: [PATCH 055/133] Fix fmt --- rustfmt.toml | 2 +- tests/ui/issue_4266.rs | 24 +++++++++++++++++++----- tests/ui/issue_4266.stderr | 8 +++++--- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 797eccdad..f1241e74b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,5 +2,5 @@ max_width = 120 comment_width = 100 match_block_trailing_comma = true wrap_comments = true - +edition = "2018" error_on_line_overflow = true diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs index dbf482ea1..953879f7b 100644 --- a/tests/ui/issue_4266.rs +++ b/tests/ui/issue_4266.rs @@ -5,19 +5,33 @@ async fn sink1<'a>(_: &'a str) {} // lint async fn sink1_elided(_: &str) {} // ok -async fn one_to_one<'a>(s: &'a str) -> &'a str { s } // lint -async fn one_to_one_elided(s: &str) -> &str { s } // ok -async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { a } // ok +// lint +async fn one_to_one<'a>(s: &'a str) -> &'a str { + s +} + +// ok +async fn one_to_one_elided(s: &str) -> &str { + s +} + +// ok +async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { + a +} + // async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn // #3988 struct Foo; impl Foo { - pub async fn foo(&mut self) {} // ok + // ok + pub async fn foo(&mut self) {} } // rust-lang/rust#61115 -async fn print(s: &str) { // ok +// ok +async fn print(s: &str) { println!("{}", s); } diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index 3c9740c4a..8b4e70eb9 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -7,10 +7,12 @@ LL | async fn sink1<'a>(_: &'a str) {} // lint = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:8:1 + --> $DIR/issue_4266.rs:9:1 | -LL | async fn one_to_one<'a>(s: &'a str) -> &'a str { s } // lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str { +LL | | s +LL | | } + | |_^ error: aborting due to 2 previous errors From b70b3b14aa3125fe4f74a6a71fb7a7b7e78ab13f Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Sat, 20 Jul 2019 00:50:18 +0800 Subject: [PATCH 056/133] Revert global fmt config and use `rustfmt::skip` --- rustfmt.toml | 2 +- tests/ui/issue_4266.rs | 58 ++++++++++++++++++++------------------ tests/ui/issue_4266.stderr | 16 +++++------ 3 files changed, 40 insertions(+), 36 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index f1241e74b..797eccdad 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,5 +2,5 @@ max_width = 120 comment_width = 100 match_block_trailing_comma = true wrap_comments = true -edition = "2018" + error_on_line_overflow = true diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs index 953879f7b..737e718c4 100644 --- a/tests/ui/issue_4266.rs +++ b/tests/ui/issue_4266.rs @@ -2,37 +2,41 @@ #![feature(async_await)] #![allow(dead_code)] -async fn sink1<'a>(_: &'a str) {} // lint -async fn sink1_elided(_: &str) {} // ok +// No edition 2018 +#[rustfmt::skip] +mod m { + async fn sink1<'a>(_: &'a str) {} // lint + async fn sink1_elided(_: &str) {} // ok -// lint -async fn one_to_one<'a>(s: &'a str) -> &'a str { - s -} + // lint + async fn one_to_one<'a>(s: &'a str) -> &'a str { + s + } -// ok -async fn one_to_one_elided(s: &str) -> &str { - s -} - -// ok -async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { - a -} - -// async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn - -// #3988 -struct Foo; -impl Foo { // ok - pub async fn foo(&mut self) {} -} + async fn one_to_one_elided(s: &str) -> &str { + s + } -// rust-lang/rust#61115 -// ok -async fn print(s: &str) { - println!("{}", s); + // ok + async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { + a + } + + // async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn + + // #3988 + struct Foo; + impl Foo { + // ok + pub async fn foo(&mut self) {} + } + + // rust-lang/rust#61115 + // ok + async fn print(s: &str) { + println!("{}", s); + } } fn main() {} diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index 8b4e70eb9..649d01dca 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -1,18 +1,18 @@ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:5:1 + --> $DIR/issue_4266.rs:8:5 | -LL | async fn sink1<'a>(_: &'a str) {} // lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | async fn sink1<'a>(_: &'a str) {} // lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:9:1 + --> $DIR/issue_4266.rs:12:5 | -LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str { -LL | | s -LL | | } - | |_^ +LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str { +LL | | s +LL | | } + | |_____^ error: aborting due to 2 previous errors From 67db88f6450401b3333e9d92a06420a8504a847d Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 21 Jul 2019 09:36:31 +0200 Subject: [PATCH 057/133] Fix breakage due to rust-lang/rust#62705 Also rename `OUTER_EXPN_INFO` to `OUTER_EXPN_EXPN_INFO` to match new function names. --- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/utils/internal_lints.rs | 12 ++++++------ tests/ui/outer_expn_info.rs | 2 +- tests/ui/outer_expn_info.stderr | 8 ++++---- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index de7a213d7..9009207bb 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -668,7 +668,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { utils::internal_lints::CLIPPY_LINTS_INTERNAL, utils::internal_lints::COMPILER_LINT_FUNCTIONS, utils::internal_lints::LINT_WITHOUT_LINT_PASS, - utils::internal_lints::OUTER_EXPN_INFO, + utils::internal_lints::OUTER_EXPN_EXPN_INFO, ]); reg.register_lint_group("clippy::all", Some("clippy"), vec![ diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index aba2543b1..6393bf2ad 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -93,9 +93,9 @@ declare_clippy_lint! { /// ```rust /// expr.span.ctxt().outer_expn_info() /// ``` - pub OUTER_EXPN_INFO, + pub OUTER_EXPN_EXPN_INFO, internal, - "using `cx.outer().expn_info()` instead of `cx.outer_expn_info()`" + "using `cx.outer_expn().expn_info()` instead of `cx.outer_expn_info()`" } declare_lint_pass!(ClippyLintsInternal => [CLIPPY_LINTS_INTERNAL]); @@ -280,7 +280,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CompilerLintFunctions { pub struct OuterExpnInfoPass; -impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_INFO]); +impl_lint_pass!(OuterExpnInfoPass => [OUTER_EXPN_EXPN_INFO]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) { @@ -288,7 +288,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass { let method_names: Vec = method_names.iter().map(|s| s.as_str()).collect(); let method_names: Vec<&str> = method_names.iter().map(std::convert::AsRef::as_ref).collect(); if_chain! { - if let ["expn_info", "outer"] = method_names.as_slice(); + if let ["expn_info", "outer_expn"] = method_names.as_slice(); let args = arg_lists[1]; if args.len() == 1; let self_arg = &args[0]; @@ -297,9 +297,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for OuterExpnInfoPass { then { span_lint_and_sugg( cx, - OUTER_EXPN_INFO, + OUTER_EXPN_EXPN_INFO, expr.span.trim_start(self_arg.span).unwrap_or(expr.span), - "usage of `outer().expn_info()`", + "usage of `outer_expn().expn_info()`", "try", ".outer_expn_info()".to_string(), Applicability::MachineApplicable, diff --git a/tests/ui/outer_expn_info.rs b/tests/ui/outer_expn_info.rs index 1bc6f6888..ed0542c92 100644 --- a/tests/ui/outer_expn_info.rs +++ b/tests/ui/outer_expn_info.rs @@ -16,7 +16,7 @@ declare_lint_pass!(Pass => [TEST_LINT]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, _cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - let _ = expr.span.ctxt().outer().expn_info(); + let _ = expr.span.ctxt().outer_expn().expn_info(); } } diff --git a/tests/ui/outer_expn_info.stderr b/tests/ui/outer_expn_info.stderr index d9efc91da..4bbd1493d 100644 --- a/tests/ui/outer_expn_info.stderr +++ b/tests/ui/outer_expn_info.stderr @@ -1,15 +1,15 @@ -error: usage of `outer().expn_info()` +error: usage of `outer_expn().expn_info()` --> $DIR/outer_expn_info.rs:19:33 | -LL | let _ = expr.span.ctxt().outer().expn_info(); - | ^^^^^^^^^^^^^^^^^^^^ help: try: `.outer_expn_info()` +LL | let _ = expr.span.ctxt().outer_expn().expn_info(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `.outer_expn_info()` | note: lint level defined here --> $DIR/outer_expn_info.rs:1:9 | LL | #![deny(clippy::internal)] | ^^^^^^^^^^^^^^^^ - = note: `#[deny(clippy::outer_expn_info)]` implied by `#[deny(clippy::internal)]` + = note: `#[deny(clippy::outer_expn_expn_info)]` implied by `#[deny(clippy::internal)]` error: aborting due to previous error From f05e295685d56a59fbc220e281f022c7a3db4306 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 21 Jul 2019 12:52:14 +0200 Subject: [PATCH 058/133] Fix breakage due to rust-lang/rust#60913 --- clippy_lints/src/lib.rs | 1 + clippy_lints/src/redundant_clone.rs | 45 +++++++++++++++++++---------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 9009207bb..6d90d315f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -1,6 +1,7 @@ // error-pattern:cargo-clippy #![feature(box_syntax)] +#![feature(box_patterns)] #![feature(never_type)] #![feature(rustc_private)] #![feature(slice_patterns)] diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index edcf41f75..d24a20b07 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -132,7 +132,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for RedundantClone { let pred_arg = if_chain! { if let Some((pred_fn_def_id, pred_arg, pred_arg_ty, Some(res))) = is_call_with_ref_arg(cx, mir, &pred_terminator.kind); - if *res == mir::Place::Base(mir::PlaceBase::Local(cloned)); + if res.base == mir::PlaceBase::Local(cloned); if match_def_path(cx, pred_fn_def_id, &paths::DEREF_TRAIT_METHOD); if match_type(cx, pred_arg_ty, &paths::PATH_BUF) || match_type(cx, pred_arg_ty, &paths::OS_STRING); @@ -218,7 +218,7 @@ fn is_call_with_ref_arg<'tcx>( if_chain! { if let TerminatorKind::Call { func, args, destination, .. } = kind; if args.len() == 1; - if let mir::Operand::Move(mir::Place::Base(mir::PlaceBase::Local(local))) = &args[0]; + if let mir::Operand::Move(mir::Place { base: mir::PlaceBase::Local(local), .. }) = &args[0]; if let ty::FnDef(def_id, _) = func.ty(&*mir, cx.tcx).sty; if let (inner_ty, 1) = walk_ptrs_ty_depth(args[0].ty(&*mir, cx.tcx)); if !is_copy(cx, inner_ty); @@ -244,7 +244,14 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( stmts .rev() .find_map(|stmt| { - if let mir::StatementKind::Assign(mir::Place::Base(mir::PlaceBase::Local(local)), v) = &stmt.kind { + if let mir::StatementKind::Assign( + mir::Place { + base: mir::PlaceBase::Local(local), + .. + }, + v, + ) = &stmt.kind + { if *local == to { return Some(v); } @@ -271,28 +278,34 @@ fn find_stmt_assigns_to<'a, 'tcx: 'a>( fn base_local_and_movability<'tcx>( cx: &LateContext<'_, 'tcx>, mir: &mir::Body<'tcx>, - mut place: &mir::Place<'tcx>, + place: &mir::Place<'tcx>, ) -> Option<(mir::Local, CannotMoveOut)> { - use rustc::mir::Place::*; + use rustc::mir::Place; use rustc::mir::PlaceBase; + use rustc::mir::PlaceRef; + use rustc::mir::Projection; // 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; - loop { - match place { - Base(PlaceBase::Local(local)) => return Some((*local, deref || field)), - Projection(proj) => { - place = &proj.base; - deref = deref || matches!(proj.elem, mir::ProjectionElem::Deref); - if !field && matches!(proj.elem, mir::ProjectionElem::Field(..)) { - field = has_drop(cx, place.ty(&mir.local_decls, cx.tcx).ty); - } - }, - _ => return None, + let PlaceRef { + base: place_base, + mut projection, + } = place.as_place_ref(); + if let PlaceBase::Local(local) = place_base { + while let Some(box Projection { base, elem }) = projection { + projection = base; + deref = matches!(elem, mir::ProjectionElem::Deref); + field = !field + && matches!(elem, mir::ProjectionElem::Field(..)) + && has_drop(cx, Place::ty_from(place_base, projection, &mir.local_decls, cx.tcx).ty); } + + Some((*local, deref || field)) + } else { + None } } From 434f83a6c7e6973b12bd59918b059f5d35fe3075 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Tue, 23 Jul 2019 02:57:49 +0800 Subject: [PATCH 059/133] Revert "Revert global fmt config and use `rustfmt::skip`" This reverts commit b70b3b14aa3125fe4f74a6a71fb7a7b7e78ab13f. --- rustfmt.toml | 2 +- tests/ui/issue_4266.rs | 58 ++++++++++++++++++-------------------- tests/ui/issue_4266.stderr | 16 +++++------ 3 files changed, 36 insertions(+), 40 deletions(-) diff --git a/rustfmt.toml b/rustfmt.toml index 797eccdad..f1241e74b 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -2,5 +2,5 @@ max_width = 120 comment_width = 100 match_block_trailing_comma = true wrap_comments = true - +edition = "2018" error_on_line_overflow = true diff --git a/tests/ui/issue_4266.rs b/tests/ui/issue_4266.rs index 737e718c4..953879f7b 100644 --- a/tests/ui/issue_4266.rs +++ b/tests/ui/issue_4266.rs @@ -2,41 +2,37 @@ #![feature(async_await)] #![allow(dead_code)] -// No edition 2018 -#[rustfmt::skip] -mod m { - async fn sink1<'a>(_: &'a str) {} // lint - async fn sink1_elided(_: &str) {} // ok +async fn sink1<'a>(_: &'a str) {} // lint +async fn sink1_elided(_: &str) {} // ok - // lint - async fn one_to_one<'a>(s: &'a str) -> &'a str { - s - } +// lint +async fn one_to_one<'a>(s: &'a str) -> &'a str { + s +} +// ok +async fn one_to_one_elided(s: &str) -> &str { + s +} + +// ok +async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { + a +} + +// async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn + +// #3988 +struct Foo; +impl Foo { // ok - async fn one_to_one_elided(s: &str) -> &str { - s - } + pub async fn foo(&mut self) {} +} - // ok - async fn all_to_one<'a>(a: &'a str, _b: &'a str) -> &'a str { - a - } - - // async fn unrelated(_: &str, _: &str) {} // Not allowed in async fn - - // #3988 - struct Foo; - impl Foo { - // ok - pub async fn foo(&mut self) {} - } - - // rust-lang/rust#61115 - // ok - async fn print(s: &str) { - println!("{}", s); - } +// rust-lang/rust#61115 +// ok +async fn print(s: &str) { + println!("{}", s); } fn main() {} diff --git a/tests/ui/issue_4266.stderr b/tests/ui/issue_4266.stderr index 649d01dca..8b4e70eb9 100644 --- a/tests/ui/issue_4266.stderr +++ b/tests/ui/issue_4266.stderr @@ -1,18 +1,18 @@ error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:8:5 + --> $DIR/issue_4266.rs:5:1 | -LL | async fn sink1<'a>(_: &'a str) {} // lint - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | async fn sink1<'a>(_: &'a str) {} // lint + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::needless-lifetimes` implied by `-D warnings` error: explicit lifetimes given in parameter types where they could be elided (or replaced with `'_` if needed by type declaration) - --> $DIR/issue_4266.rs:12:5 + --> $DIR/issue_4266.rs:9:1 | -LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str { -LL | | s -LL | | } - | |_____^ +LL | / async fn one_to_one<'a>(s: &'a str) -> &'a str { +LL | | s +LL | | } + | |_^ error: aborting due to 2 previous errors From 5265ab8723d675262fe065bbb2bd0ff3225b5255 Mon Sep 17 00:00:00 2001 From: uHOOCCOOHu Date: Tue, 23 Jul 2019 03:59:09 +0800 Subject: [PATCH 060/133] Fix tests for edition 2018 compatibility --- tests/ui/cognitive_complexity.rs | 18 +++++++++--------- tests/ui/cognitive_complexity.stderr | 8 ++++---- tests/ui/dlist.rs | 2 +- tests/ui/dlist.stderr | 6 +++--- tests/ui/if_same_then_else.rs | 4 ++-- tests/ui/if_same_then_else.stderr | 4 ++-- tests/ui/unused_io_amount.rs | 4 ++-- tests/ui/unused_io_amount.stderr | 8 ++++---- 8 files changed, 27 insertions(+), 27 deletions(-) diff --git a/tests/ui/cognitive_complexity.rs b/tests/ui/cognitive_complexity.rs index 4e4016e78..a1f1c586e 100644 --- a/tests/ui/cognitive_complexity.rs +++ b/tests/ui/cognitive_complexity.rs @@ -313,7 +313,7 @@ fn mcarton_sees_all() { } #[clippy::cognitive_complexity = "0"] -fn try() -> Result { +fn try_() -> Result { match 5 { 5 => Ok(5), _ => return Err("bla"), @@ -322,14 +322,14 @@ fn try() -> Result { #[clippy::cognitive_complexity = "0"] fn try_again() -> Result { - let _ = try!(Ok(42)); - let _ = try!(Ok(43)); - let _ = try!(Ok(44)); - let _ = try!(Ok(45)); - let _ = try!(Ok(46)); - let _ = try!(Ok(47)); - let _ = try!(Ok(48)); - let _ = try!(Ok(49)); + let _ = r#try!(Ok(42)); + let _ = r#try!(Ok(43)); + let _ = r#try!(Ok(44)); + let _ = r#try!(Ok(45)); + let _ = r#try!(Ok(46)); + let _ = r#try!(Ok(47)); + let _ = r#try!(Ok(48)); + let _ = r#try!(Ok(49)); match 5 { 5 => Ok(5), _ => return Err("bla"), diff --git a/tests/ui/cognitive_complexity.stderr b/tests/ui/cognitive_complexity.stderr index 168653b97..e1c5863f4 100644 --- a/tests/ui/cognitive_complexity.stderr +++ b/tests/ui/cognitive_complexity.stderr @@ -216,7 +216,7 @@ LL | | } error: the function has a cognitive complexity of 1 --> $DIR/cognitive_complexity.rs:316:1 | -LL | / fn try() -> Result { +LL | / fn try_() -> Result { LL | | match 5 { LL | | 5 => Ok(5), LL | | _ => return Err("bla"), @@ -230,9 +230,9 @@ error: the function has a cognitive complexity of 1 --> $DIR/cognitive_complexity.rs:324:1 | LL | / fn try_again() -> Result { -LL | | let _ = try!(Ok(42)); -LL | | let _ = try!(Ok(43)); -LL | | let _ = try!(Ok(44)); +LL | | let _ = r#try!(Ok(42)); +LL | | let _ = r#try!(Ok(43)); +LL | | let _ = r#try!(Ok(44)); ... | LL | | } LL | | } diff --git a/tests/ui/dlist.rs b/tests/ui/dlist.rs index 5af79f9c5..2940d2d29 100644 --- a/tests/ui/dlist.rs +++ b/tests/ui/dlist.rs @@ -7,7 +7,7 @@ use alloc::collections::linked_list::LinkedList; trait Foo { type Baz = LinkedList; - fn foo(LinkedList); + fn foo(_: LinkedList); const BAR: Option>; } diff --git a/tests/ui/dlist.stderr b/tests/ui/dlist.stderr index e4712e5d0..1f6646ec9 100644 --- a/tests/ui/dlist.stderr +++ b/tests/ui/dlist.stderr @@ -8,10 +8,10 @@ LL | type Baz = LinkedList; = help: a VecDeque might work error: I see you're using a LinkedList! Perhaps you meant some other data structure? - --> $DIR/dlist.rs:10:12 + --> $DIR/dlist.rs:10:15 | -LL | fn foo(LinkedList); - | ^^^^^^^^^^^^^^ +LL | fn foo(_: LinkedList); + | ^^^^^^^^^^^^^^ | = help: a VecDeque might work diff --git a/tests/ui/if_same_then_else.rs b/tests/ui/if_same_then_else.rs index d1213e5e5..f9923c9bb 100644 --- a/tests/ui/if_same_then_else.rs +++ b/tests/ui/if_same_then_else.rs @@ -215,10 +215,10 @@ fn if_same_then_else() -> Result<&'static str, ()> { }; if true { - try!(Ok("foo")); + r#try!(Ok("foo")); } else { //~ ERROR same body as `if` block - try!(Ok("foo")); + r#try!(Ok("foo")); } if true { diff --git a/tests/ui/if_same_then_else.stderr b/tests/ui/if_same_then_else.stderr index fa42afff0..f1710382b 100644 --- a/tests/ui/if_same_then_else.stderr +++ b/tests/ui/if_same_then_else.stderr @@ -197,7 +197,7 @@ error: this `if` has identical blocks LL | } else { | ____________^ LL | | //~ ERROR same body as `if` block -LL | | try!(Ok("foo")); +LL | | r#try!(Ok("foo")); LL | | } | |_____^ | @@ -206,7 +206,7 @@ note: same as this | LL | if true { | _____________^ -LL | | try!(Ok("foo")); +LL | | r#try!(Ok("foo")); LL | | } else { | |_____^ diff --git a/tests/ui/unused_io_amount.rs b/tests/ui/unused_io_amount.rs index c8a38f9fe..409688224 100644 --- a/tests/ui/unused_io_amount.rs +++ b/tests/ui/unused_io_amount.rs @@ -4,9 +4,9 @@ use std::io; fn try_macro(s: &mut T) -> io::Result<()> { - try!(s.write(b"test")); + r#try!(s.write(b"test")); let mut buf = [0u8; 4]; - try!(s.read(&mut buf)); + r#try!(s.read(&mut buf)); Ok(()) } diff --git a/tests/ui/unused_io_amount.stderr b/tests/ui/unused_io_amount.stderr index 2d0033819..dbf701e06 100644 --- a/tests/ui/unused_io_amount.stderr +++ b/tests/ui/unused_io_amount.stderr @@ -1,8 +1,8 @@ error: handle written amount returned or use `Write::write_all` instead --> $DIR/unused_io_amount.rs:7:5 | -LL | try!(s.write(b"test")); - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | r#try!(s.write(b"test")); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::unused-io-amount` implied by `-D warnings` = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) @@ -10,8 +10,8 @@ LL | try!(s.write(b"test")); error: handle read amount returned or use `Read::read_exact` instead --> $DIR/unused_io_amount.rs:9:5 | -LL | try!(s.read(&mut buf)); - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | r#try!(s.read(&mut buf)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) From 2221fc81249eb91ca5f318ca29fea34d2cf14bb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 24 Jul 2019 02:20:36 +0200 Subject: [PATCH 061/133] rustup https://github.com/rust-lang/rust/pull/62859 --- clippy_lints/src/redundant_clone.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index d24a20b07..e85538615 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -293,7 +293,7 @@ fn base_local_and_movability<'tcx>( let PlaceRef { base: place_base, mut projection, - } = place.as_place_ref(); + } = place.as_ref(); if let PlaceBase::Local(local) = place_base { while let Some(box Projection { base, elem }) = projection { projection = base; From b0373a5f6b6d4aa61c4ef9322a7b34c6b7507934 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 24 Jul 2019 02:24:27 +0200 Subject: [PATCH 062/133] update test stderr, not sure which rustc pull request caused this. --- tests/ui/issue-3145.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/issue-3145.stderr b/tests/ui/issue-3145.stderr index f3984f991..cb0d95f5e 100644 --- a/tests/ui/issue-3145.stderr +++ b/tests/ui/issue-3145.stderr @@ -2,7 +2,7 @@ error: expected token: `,` --> $DIR/issue-3145.rs:2:19 | LL | println!("{}" a); //~ERROR expected token: `,` - | ^ + | ^ expected `,` error: aborting due to previous error From f71d59e6a63d8624a121d29230a83ae39c856c6c Mon Sep 17 00:00:00 2001 From: xd009642 Date: Fri, 15 Feb 2019 20:21:13 +0000 Subject: [PATCH 063/133] Lint for type repetition in trait bounds. This lint adds warning if types are redundantly repeated in trait bounds i.e. `T: Copy, T: Clone` instead of `T: Copy + Clone`. This is a late pass trait lint and has necessitated the addition of code to allow hashing of TyKinds without taking into account Span information. --- clippy_lints/src/lib.rs | 3 + clippy_lints/src/trait_bounds.rs | 63 ++++++++++++ clippy_lints/src/utils/hir_utils.rs | 119 +++++++++++++++++++++- tests/ui/type_repetition_in_bounds.rs | 14 +++ tests/ui/type_repetition_in_bounds.stderr | 15 +++ 5 files changed, 210 insertions(+), 4 deletions(-) create mode 100644 clippy_lints/src/trait_bounds.rs create mode 100644 tests/ui/type_repetition_in_bounds.rs create mode 100644 tests/ui/type_repetition_in_bounds.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6d90d315f..faffb1a67 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -265,6 +265,7 @@ pub mod swap; pub mod temporary_assignment; pub mod transmute; pub mod transmuting_null; +pub mod trait_bounds; pub mod trivially_copy_pass_by_ref; pub mod try_err; pub mod types; @@ -588,6 +589,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box checked_conversions::CheckedConversions); reg.register_late_lint_pass(box integer_division::IntegerDivision); reg.register_late_lint_pass(box inherent_to_string::InherentToString); + reg.register_late_lint_pass(box trait_bounds::TraitBounds); reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![ arithmetic::FLOAT_ARITHMETIC, @@ -868,6 +870,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, transmuting_null::TRANSMUTING_NULL, + trait_bounds::TYPE_REPETITION_IN_BOUNDS, trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, try_err::TRY_ERR, types::ABSURD_EXTREME_COMPARISONS, diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs new file mode 100644 index 000000000..1f4c68507 --- /dev/null +++ b/clippy_lints/src/trait_bounds.rs @@ -0,0 +1,63 @@ +use crate::utils::{in_macro, span_help_and_lint, SpanlessHash}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashMap; +use rustc::hir::*; + +declare_clippy_lint! { + pub TYPE_REPETITION_IN_BOUNDS, + complexity, + "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" +} + +#[derive(Copy, Clone)] +pub struct TraitBounds; + +impl LintPass for TraitBounds { + fn get_lints(&self) -> LintArray { + lint_array!(TYPE_REPETITION_IN_BOUNDS) + } + + fn name(&self) -> &'static str { + "TypeRepetitionInBounds" + } +} + + + +impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { + fn check_generics(&mut self, cx: &LateContext<'a, 'tcx>, gen: &'tcx Generics) { + if in_macro(gen.span) { + return; + } + let hash = | ty | -> u64 { + let mut hasher = SpanlessHash::new(cx, cx.tables); + hasher.hash_ty(ty); + hasher.finish() + }; + let mut map = FxHashMap::default(); + for bound in &gen.where_clause.predicates { + if let WherePredicate::BoundPredicate(ref p) = bound { + let h = hash(&p.bounded_ty); + if let Some(ref v) = map.insert(h, p.bounds) { + let mut hint_string = format!("consider combining the bounds: `{:?}: ", p.bounded_ty); + for &b in v.iter() { + hint_string.push_str(&format!("{:?}, ", b)); + } + for &b in p.bounds.iter() { + hint_string.push_str(&format!("{:?}, ", b)); + } + hint_string.truncate(hint_string.len() - 2); + hint_string.push('`'); + span_help_and_lint( + cx, + TYPE_REPETITION_IN_BOUNDS, + p.span, + "this type has already been used as a bound predicate", + &hint_string, + ); + } + } + } + } +} diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index e9b5cee43..929c15a6e 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -3,7 +3,7 @@ use crate::utils::differing_macro_contexts; use rustc::hir::ptr::P; use rustc::hir::*; use rustc::lint::LateContext; -use rustc::ty::TypeckTables; +use rustc::ty::{Ty, TypeckTables}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use syntax::ast::Name; @@ -438,9 +438,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(fun); self.hash_exprs(args); }, - ExprKind::Cast(ref e, ref _ty) | ExprKind::Type(ref e, ref _ty) => { + ExprKind::Cast(ref e, ref ty) => { + let c: fn(_, _) -> _ = ExprKind::Cast; + c.hash(&mut self.s); self.hash_expr(e); - // TODO: _ty + self.hash_ty(ty); }, ExprKind::Closure(cap, _, eid, _, _) => { match cap { @@ -512,9 +514,22 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(e); } }, - ExprKind::Tup(ref v) | ExprKind::Array(ref v) => { + ExprKind::Tup(ref tup) => { + let c: fn(_) -> _ = ExprKind::Tup; + c.hash(&mut self.s); + self.hash_exprs(tup); + }, + ExprKind::Array(ref v) => { + let c: fn(_) -> _ = ExprKind::Array; + c.hash(&mut self.s); self.hash_exprs(v); }, + ExprKind::Type(ref e, ref ty) => { + let c: fn(_, _) -> _ = ExprKind::Type; + c.hash(&mut self.s); + self.hash_expr(e); + self.hash_ty(ty); + }, ExprKind::Unary(lop, ref le) => { lop.hash(&mut self.s); self.hash_expr(le); @@ -574,4 +589,100 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, } } + + pub fn hash_lifetime(&mut self, lifetime: &Lifetime) { + if let LifetimeName::Param(ref name) = lifetime.name { + match name { + ParamName::Plain(ref ident) => { + ident.name.hash(&mut self.s); + }, + ParamName::Fresh(ref size) => { + size.hash(&mut self.s); + }, + _ => {}, + } + } + } + + pub fn hash_ty(&mut self, ty: &Ty) { + std::mem::discriminant(&ty.node).hash(&mut self.s); + match ty.node { + Ty::Slice(ty) => { + self.hash_ty(ty); + }, + Ty::Array(ty, anon_const) => { + self.hash_ty(ty); + self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); + }, + Ty::Ptr(mut_ty) => { + self.hash_ty(&mut_ty.ty); + mut_ty.mutbl.hash(&mut self.s); + }, + Ty::Rptr(lifetime, mut_ty) => { + self.hash_lifetime(lifetime); + self.hash_ty(&mut_ty.ty); + mut_ty.mutbl.hash(&mut self.s); + }, + Ty::BareFn(bfn) => { + bfn.unsafety.hash(&mut self.s); + bfn.abi.hash(&mut self.s); + for arg in &bfn.decl.inputs { + self.hash_ty(&arg); + } + match bfn.decl.output { + FunctionRetTy::DefaultReturn(_) => { + ().hash(&mut self.s); + }, + FunctionRetTy::Return(ref ty) => { + self.hash_ty(ty); + }, + } + bfn.decl.c_variadic.hash(&mut self.s); + }, + Ty::Tup(ty_list) => { + for ty in ty_list { + self.hash_ty(ty); + } + + }, + Ty::Path(qpath) => { + match qpath { + QPath::Resolved(ref maybe_ty, ref path) => { + if let Some(ref ty) = maybe_ty { + self.hash_ty(ty); + } + for segment in &path.segments { + segment.ident.name.hash(&mut self.s); + } + }, + QPath::TypeRelative(ref ty, ref segment) => { + self.hash_ty(ty); + segment.ident.name.hash(&mut self.s); + }, + } + }, + Ty::Def(_, arg_list) => { + for arg in arg_list { + match arg { + GenericArg::Lifetime(ref l) => self.hash_lifetime(l), + GenericArg::Type(ref ty) => self.hash_ty(ty), + GenericArg::Const(ref ca) => { + self.hash_expr(&self.cx.tcx.hir().body(ca.value.body).value); + }, + } + } + }, + Ty::TraitObject(_, lifetime) => { + self.hash_lifetime(lifetime); + + }, + Ty::Typeof(anon_const) => { + self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); + }, + Ty::CVarArgs(lifetime) => { + self.hash_lifetime(lifetime); + }, + Ty::Err | Ty::Infer | Ty::Never => {}, + } + } } diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs new file mode 100644 index 000000000..3aa0d0da5 --- /dev/null +++ b/tests/ui/type_repetition_in_bounds.rs @@ -0,0 +1,14 @@ +#[deny(clippy::type_repetition_in_bounds)] + +pub fn foo(_t: T) where T: Copy, T: Clone { + unimplemented!(); +} + +pub fn bar(_t: T, _u: U) where T: Copy, U: Clone { + unimplemented!(); +} + + +fn main() { + +} diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr new file mode 100644 index 000000000..1b49c6953 --- /dev/null +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -0,0 +1,15 @@ +error: this type has already been used as a bound predicate + --> $DIR/type_repetition_in_bounds.rs:3:37 + | +LL | pub fn foo(_t: T) where T: Copy, T: Clone { + | ^^^^^^^^ + | +note: lint level defined here + --> $DIR/type_repetition_in_bounds.rs:1:8 + | +LL | #[deny(clippy::type_repetition_in_bounds)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = help: consider combining the bounds: `T: Copy + Clone` + +error: aborting due to previous error + From f3e4467c109364c557bfd998dabfeab6a045c605 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 22 Jun 2019 22:22:11 +0100 Subject: [PATCH 064/133] Changed Ty to ty, added lifetime 'tcx --- clippy_lints/src/utils/hir_utils.rs | 34 ++++++++++++++--------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 929c15a6e..276d984f8 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -3,7 +3,7 @@ use crate::utils::differing_macro_contexts; use rustc::hir::ptr::P; use rustc::hir::*; use rustc::lint::LateContext; -use rustc::ty::{Ty, TypeckTables}; +use rustc::ty::{self, Ty, TypeckTables}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use syntax::ast::Name; @@ -45,7 +45,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => { self.eq_pat(&l.pat, &r.pat) - && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) + && both(&l.ty, &r.ty, |l, r| self.eq_ty(*l, *r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) }, (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => { @@ -257,7 +257,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { } } - pub fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool { + pub fn eq_ty(&mut self, left: &Ty<'tcx>, right: &Ty<'tcx>) -> bool { self.eq_ty_kind(&left.node, &right.node) } @@ -604,26 +604,26 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_ty(&mut self, ty: &Ty) { + pub fn hash_ty(&mut self, ty: &Ty<'tcx>) { std::mem::discriminant(&ty.node).hash(&mut self.s); - match ty.node { - Ty::Slice(ty) => { + match ty.sty { + ty::Slice(ty) => { self.hash_ty(ty); }, - Ty::Array(ty, anon_const) => { + ty::Array(ty, anon_const) => { self.hash_ty(ty); self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); }, - Ty::Ptr(mut_ty) => { + ty::Ptr(mut_ty) => { self.hash_ty(&mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - Ty::Rptr(lifetime, mut_ty) => { + ty::Rptr(lifetime, mut_ty) => { self.hash_lifetime(lifetime); self.hash_ty(&mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - Ty::BareFn(bfn) => { + ty::BareFn(bfn) => { bfn.unsafety.hash(&mut self.s); bfn.abi.hash(&mut self.s); for arg in &bfn.decl.inputs { @@ -639,13 +639,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } bfn.decl.c_variadic.hash(&mut self.s); }, - Ty::Tup(ty_list) => { + ty::Tup(ty_list) => { for ty in ty_list { self.hash_ty(ty); } }, - Ty::Path(qpath) => { + ty::Path(qpath) => { match qpath { QPath::Resolved(ref maybe_ty, ref path) => { if let Some(ref ty) = maybe_ty { @@ -661,7 +661,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, } }, - Ty::Def(_, arg_list) => { + ty::Def(_, arg_list) => { for arg in arg_list { match arg { GenericArg::Lifetime(ref l) => self.hash_lifetime(l), @@ -672,17 +672,17 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } }, - Ty::TraitObject(_, lifetime) => { + ty::TraitObject(_, lifetime) => { self.hash_lifetime(lifetime); }, - Ty::Typeof(anon_const) => { + ty::Typeof(anon_const) => { self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); }, - Ty::CVarArgs(lifetime) => { + ty::CVarArgs(lifetime) => { self.hash_lifetime(lifetime); }, - Ty::Err | Ty::Infer | Ty::Never => {}, + ty::Err | ty::Infer | ty::Never => {}, } } } From 792153104c5af9948df6d8def8ab4b2611731eb6 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Wed, 24 Jul 2019 22:27:12 +0100 Subject: [PATCH 065/133] Fix some of the compile errors --- clippy_lints/src/trait_bounds.rs | 22 ++++++-------------- clippy_lints/src/utils/hir_utils.rs | 32 ++++++++++++++--------------- 2 files changed, 22 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 1f4c68507..e41437bf1 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,29 +1,19 @@ use crate::utils::{in_macro, span_help_and_lint, SpanlessHash}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array}; +use rustc::{declare_tool_lint, lint_array, impl_lint_pass}; use rustc_data_structures::fx::FxHashMap; use rustc::hir::*; +#[derive(Copy, Clone)] +pub struct TraitBounds; + declare_clippy_lint! { pub TYPE_REPETITION_IN_BOUNDS, complexity, "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" } -#[derive(Copy, Clone)] -pub struct TraitBounds; - -impl LintPass for TraitBounds { - fn get_lints(&self) -> LintArray { - lint_array!(TYPE_REPETITION_IN_BOUNDS) - } - - fn name(&self) -> &'static str { - "TypeRepetitionInBounds" - } -} - - +impl_lint_pass!(TraitBounds => [TYPE_REPETITION_IN_BOUNDS]); impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { fn check_generics(&mut self, cx: &LateContext<'a, 'tcx>, gen: &'tcx Generics) { @@ -38,7 +28,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { let mut map = FxHashMap::default(); for bound in &gen.where_clause.predicates { if let WherePredicate::BoundPredicate(ref p) = bound { - let h = hash(&p.bounded_ty); + let h = hash(&p.bounded_ty.node); if let Some(ref v) = map.insert(h, p.bounds) { let mut hint_string = format!("consider combining the bounds: `{:?}: ", p.bounded_ty); for &b in v.iter() { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 276d984f8..5304a9226 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -258,7 +258,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { } pub fn eq_ty(&mut self, left: &Ty<'tcx>, right: &Ty<'tcx>) -> bool { - self.eq_ty_kind(&left.node, &right.node) + self.eq_ty_kind(&left.sty, &right.sty) } #[allow(clippy::similar_names)] @@ -604,26 +604,26 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_ty(&mut self, ty: &Ty<'tcx>) { + pub fn hash_ty(&mut self, ty: &TyKind) { std::mem::discriminant(&ty.node).hash(&mut self.s); - match ty.sty { - ty::Slice(ty) => { + match ty { + TyKind::Slice(ty) => { self.hash_ty(ty); }, - ty::Array(ty, anon_const) => { + TyKind::Array(ty, anon_const) => { self.hash_ty(ty); self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); }, - ty::Ptr(mut_ty) => { + TyKind::Ptr(mut_ty) => { self.hash_ty(&mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - ty::Rptr(lifetime, mut_ty) => { + TyKind::Rptr(lifetime, mut_ty) => { self.hash_lifetime(lifetime); self.hash_ty(&mut_ty.ty); mut_ty.mutbl.hash(&mut self.s); }, - ty::BareFn(bfn) => { + TyKind::BareFn(bfn) => { bfn.unsafety.hash(&mut self.s); bfn.abi.hash(&mut self.s); for arg in &bfn.decl.inputs { @@ -639,13 +639,13 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } bfn.decl.c_variadic.hash(&mut self.s); }, - ty::Tup(ty_list) => { + TyKind::Tup(ty_list) => { for ty in ty_list { self.hash_ty(ty); } }, - ty::Path(qpath) => { + TyKind::Path(qpath) => { match qpath { QPath::Resolved(ref maybe_ty, ref path) => { if let Some(ref ty) = maybe_ty { @@ -661,7 +661,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, } }, - ty::Def(_, arg_list) => { + TyKind::Def(_, arg_list) => { for arg in arg_list { match arg { GenericArg::Lifetime(ref l) => self.hash_lifetime(l), @@ -672,17 +672,17 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } }, - ty::TraitObject(_, lifetime) => { + TyKind::TraitObject(_, lifetime) => { self.hash_lifetime(lifetime); }, - ty::Typeof(anon_const) => { + TyKind::Typeof(anon_const) => { self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); }, - ty::CVarArgs(lifetime) => { - self.hash_lifetime(lifetime); + TyKind::CVarArgs(lifetime) => { + self.hash_lifetime(lifetime) }, - ty::Err | ty::Infer | ty::Never => {}, + TyKind::Err | TyKind::Infer | TyKind::Never => {}, } } } From c0259179c3c867e9b25894bf8139145d34359acc Mon Sep 17 00:00:00 2001 From: xd009642 Date: Wed, 24 Jul 2019 22:59:32 +0100 Subject: [PATCH 066/133] Fixed more compile errors Moved to rustc::hir::Ty --- clippy_lints/src/trait_bounds.rs | 6 +++--- clippy_lints/src/utils/hir_utils.rs | 18 +++++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index e41437bf1..02514377d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -28,13 +28,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { let mut map = FxHashMap::default(); for bound in &gen.where_clause.predicates { if let WherePredicate::BoundPredicate(ref p) = bound { - let h = hash(&p.bounded_ty.node); + let h = hash(&p.bounded_ty); if let Some(ref v) = map.insert(h, p.bounds) { let mut hint_string = format!("consider combining the bounds: `{:?}: ", p.bounded_ty); - for &b in v.iter() { + for b in v.iter() { hint_string.push_str(&format!("{:?}, ", b)); } - for &b in p.bounds.iter() { + for b in p.bounds.iter() { hint_string.push_str(&format!("{:?}, ", b)); } hint_string.truncate(hint_string.len() - 2); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 5304a9226..4330b5587 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -3,7 +3,7 @@ use crate::utils::differing_macro_contexts; use rustc::hir::ptr::P; use rustc::hir::*; use rustc::lint::LateContext; -use rustc::ty::{self, Ty, TypeckTables}; +use rustc::ty::{self, TypeckTables}; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use syntax::ast::Name; @@ -45,7 +45,7 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&StmtKind::Local(ref l), &StmtKind::Local(ref r)) => { self.eq_pat(&l.pat, &r.pat) - && both(&l.ty, &r.ty, |l, r| self.eq_ty(*l, *r)) + && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) }, (&StmtKind::Expr(ref l), &StmtKind::Expr(ref r)) | (&StmtKind::Semi(ref l), &StmtKind::Semi(ref r)) => { @@ -257,8 +257,8 @@ impl<'a, 'tcx> SpanlessEq<'a, 'tcx> { } } - pub fn eq_ty(&mut self, left: &Ty<'tcx>, right: &Ty<'tcx>) -> bool { - self.eq_ty_kind(&left.sty, &right.sty) + pub fn eq_ty(&mut self, left: &Ty, right: &Ty) -> bool { + self.eq_ty_kind(&left.node, &right.node) } #[allow(clippy::similar_names)] @@ -604,8 +604,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } } - pub fn hash_ty(&mut self, ty: &TyKind) { - std::mem::discriminant(&ty.node).hash(&mut self.s); + pub fn hash_ty(&mut self, ty: &Ty) { + self.hash_tykind(&ty.node); + } + + pub fn hash_tykind(&mut self, ty: &TyKind) { + std::mem::discriminant(&ty).hash(&mut self.s); match ty { TyKind::Slice(ty) => { self.hash_ty(ty); @@ -665,7 +669,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { for arg in arg_list { match arg { GenericArg::Lifetime(ref l) => self.hash_lifetime(l), - GenericArg::Type(ref ty) => self.hash_ty(ty), + GenericArg::Type(ref ty) => self.hash_ty(&ty), GenericArg::Const(ref ca) => { self.hash_expr(&self.cx.tcx.hir().body(ca.value.body).value); }, From 7853dac66245d88bace4cdc62b38837aa3e54568 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Fri, 26 Jul 2019 16:46:47 +0100 Subject: [PATCH 067/133] Responded to comments and fixed compile bug Removed the hash of `let c: fn(_,_) -> _ = ExprKind::Cast` and fixed compile issue by collecting HirVec into an actual Vec --- clippy_lints/src/trait_bounds.rs | 4 ++-- clippy_lints/src/utils/hir_utils.rs | 4 +--- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 02514377d..cb836eac3 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,6 +1,6 @@ use crate::utils::{in_macro, span_help_and_lint, SpanlessHash}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::{declare_tool_lint, lint_array, impl_lint_pass}; +use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashMap; use rustc::hir::*; @@ -29,7 +29,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { for bound in &gen.where_clause.predicates { if let WherePredicate::BoundPredicate(ref p) = bound { let h = hash(&p.bounded_ty); - if let Some(ref v) = map.insert(h, p.bounds) { + if let Some(ref v) = map.insert(h, p.bounds.iter().collect::>()) { let mut hint_string = format!("consider combining the bounds: `{:?}: ", p.bounded_ty); for b in v.iter() { hint_string.push_str(&format!("{:?}, ", b)); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 4330b5587..703c9fac1 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -3,7 +3,7 @@ use crate::utils::differing_macro_contexts; use rustc::hir::ptr::P; use rustc::hir::*; use rustc::lint::LateContext; -use rustc::ty::{self, TypeckTables}; +use rustc::ty::TypeckTables; use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use syntax::ast::Name; @@ -439,8 +439,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_exprs(args); }, ExprKind::Cast(ref e, ref ty) => { - let c: fn(_, _) -> _ = ExprKind::Cast; - c.hash(&mut self.s); self.hash_expr(e); self.hash_ty(ty); }, From 0fe6003dffaf759b25a2036ff11afaa705cf1bb2 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Fri, 26 Jul 2019 21:01:18 +0200 Subject: [PATCH 068/133] Bump version of clippy_dummy The crates.io page of clippy still suggest to install `clippy-preview` instead of `clippy` I think it's time to change this. Thanks to the Stuttgart Meetup for discovering this! --- clippy_dummy/Cargo.toml | 2 +- clippy_dummy/build.rs | 4 ++-- clippy_dummy/crates-readme.md | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_dummy/Cargo.toml b/clippy_dummy/Cargo.toml index f99a23d93..fb426a4ad 100644 --- a/clippy_dummy/Cargo.toml +++ b/clippy_dummy/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_dummy" # rename to clippy before publishing -version = "0.0.302" +version = "0.0.303" authors = ["Manish Goregaokar "] edition = "2018" readme = "crates-readme.md" diff --git a/clippy_dummy/build.rs b/clippy_dummy/build.rs index 59d32e5db..1288250da 100644 --- a/clippy_dummy/build.rs +++ b/clippy_dummy/build.rs @@ -3,7 +3,7 @@ extern crate term; fn main() { if let Err(_) = foo() { eprintln!("error: Clippy is no longer available via crates.io\n"); - eprintln!("help: please run `rustup component add clippy-preview` instead"); + eprintln!("help: please run `rustup component add clippy` instead"); } std::process::exit(1); } @@ -31,7 +31,7 @@ fn foo() -> Result<(), ()> { write!(t, "please run `").map_err(|_| ())?; t.attr(term::Attr::Bold).map_err(|_| ())?; - write!(t, "rustup component add clippy-preview").map_err(|_| ())?; + write!(t, "rustup component add clippy").map_err(|_| ())?; t.reset().map_err(|_| ())?; t.fg(term::color::WHITE).map_err(|_| ())?; diff --git a/clippy_dummy/crates-readme.md b/clippy_dummy/crates-readme.md index 4f4f4991e..0decae8b9 100644 --- a/clippy_dummy/crates-readme.md +++ b/clippy_dummy/crates-readme.md @@ -1,7 +1,7 @@ Installing clippy via crates.io is deprecated. Please use the following: ```terminal -rustup component add clippy-preview +rustup component add clippy ``` on a Rust version 1.29 or later. You may need to run `rustup self update` if it complains about a missing clippy binary. From f1955501481f4204a7189b13acc796a6583febde Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 26 Jul 2019 22:58:31 +0200 Subject: [PATCH 069/133] rustup https://github.com/rust-lang/rust/pull/62964 --- clippy_lints/src/needless_pass_by_value.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 5098fa2a7..c5283a432 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -193,7 +193,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { if_chain! { if !is_self(arg); - if !ty.is_mutable_pointer(); + if !ty.is_mutable_ptr(); if !is_copy(cx, ty); if !whitelisted_traits.iter().any(|&t| implements_trait(cx, ty, t, &[])); if !implements_borrow_trait; From cac69ec063e9fcb26e0f3102c82b9cb2d56350fe Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 11:51:27 +0100 Subject: [PATCH 070/133] Respond to comments and improve printout Now get the trait names for the diagnostic message and removed more `let c: fn(_) -> _ = T; hashes from hir_utils --- clippy_lints/src/trait_bounds.rs | 10 ++++++++-- clippy_lints/src/utils/hir_utils.rs | 6 ------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index cb836eac3..3ef353a97 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -32,10 +32,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { if let Some(ref v) = map.insert(h, p.bounds.iter().collect::>()) { let mut hint_string = format!("consider combining the bounds: `{:?}: ", p.bounded_ty); for b in v.iter() { - hint_string.push_str(&format!("{:?}, ", b)); + if let GenericBound::Trait(ref poly_trait_ref, _) = b { + let path = &poly_trait_ref.trait_ref.path; + hint_string.push_str(&format!("{}, ", path)); + } } for b in p.bounds.iter() { - hint_string.push_str(&format!("{:?}, ", b)); + 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.truncate(hint_string.len() - 2); hint_string.push('`'); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 703c9fac1..449b8c439 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -513,18 +513,12 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } }, ExprKind::Tup(ref tup) => { - let c: fn(_) -> _ = ExprKind::Tup; - c.hash(&mut self.s); self.hash_exprs(tup); }, ExprKind::Array(ref v) => { - let c: fn(_) -> _ = ExprKind::Array; - c.hash(&mut self.s); self.hash_exprs(v); }, ExprKind::Type(ref e, ref ty) => { - let c: fn(_, _) -> _ = ExprKind::Type; - c.hash(&mut self.s); self.hash_expr(e); self.hash_ty(ty); }, From 5e9906b2c64c07e95252e91a4ce1534cfa4cf10b Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 12:06:25 +0100 Subject: [PATCH 071/133] Added doc comment fixed type printout Added a doc comment for the lint and fixed the printout of the type so it prints T not type(T) --- clippy_lints/src/trait_bounds.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 3ef353a97..f5ca3793d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,4 +1,4 @@ -use crate::utils::{in_macro, span_help_and_lint, SpanlessHash}; +use crate::utils::{in_macro, snippet, span_help_and_lint, SpanlessHash}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashMap; @@ -8,6 +8,20 @@ use rustc::hir::*; pub struct TraitBounds; declare_clippy_lint! { + /// **What it does:** This lint warns about unnecessary type repetitions in trait bounds + /// + /// **Why is this bad?** Complexity + /// + /// **Example:** + /// ```rust + /// pub fn foo(t: T) where T: Copy, T: Clone + /// ``` + /// + /// Could be written as: + /// + /// ```rust + /// pub fn foo(t: T) where T: Copy + Clone + /// ``` pub TYPE_REPETITION_IN_BOUNDS, complexity, "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`" @@ -30,7 +44,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { if let WherePredicate::BoundPredicate(ref p) = bound { let h = hash(&p.bounded_ty); if let Some(ref v) = map.insert(h, p.bounds.iter().collect::>()) { - let mut hint_string = format!("consider combining the bounds: `{:?}: ", p.bounded_ty); + let mut hint_string = format!("consider combining the bounds: `{}: ", snippet(cx, p.bounded_ty.span, "_")); for b in v.iter() { if let GenericBound::Trait(ref poly_trait_ref, _) = b { let path = &poly_trait_ref.trait_ref.path; From c962ddbd29ed5b374c55a0fba43cf3d0af9ad680 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 12:07:02 +0100 Subject: [PATCH 072/133] Updated test stderr --- tests/ui/type_repetition_in_bounds.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index 1b49c6953..6f5c67afb 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -9,7 +9,7 @@ note: lint level defined here | LL | #[deny(clippy::type_repetition_in_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: consider combining the bounds: `T: Copy + Clone` + = help: consider combining the bounds: `T: Copy, Clone` error: aborting due to previous error From d73a953db7a8120ec00b31c57d7092aff0f2c10b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Fri, 26 Jul 2019 23:33:02 +0200 Subject: [PATCH 073/133] ci: temporarily disable rustfmt checks/tetss since it's broken for nightly --- .travis.yml | 2 +- appveyor.yml | 2 +- tests/fmt.rs | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a1bd0ea2..0b012139d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ env: install: - | if [ -z ${INTEGRATION} ]; then - rustup component add rustfmt || cargo install --git https://github.com/rust-lang/rustfmt/ --force + # rustup component add rustfmt || cargo install --git https://github.com/rust-lang/rustfmt/ --force if [ "$TRAVIS_OS_NAME" == "linux" ]; then . $HOME/.nvm/nvm.sh nvm install stable diff --git a/appveyor.yml b/appveyor.yml index 9f6cc45af..4cea8d99e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ install: - del rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master %RUSTC_HASH% -f -n master - - rustup component add rustfmt --toolchain nightly + #- rustup component add rustfmt --toolchain nightly - rustup default master - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V diff --git a/tests/fmt.rs b/tests/fmt.rs index 2500132d7..4df93cf5a 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -1,4 +1,5 @@ #[test] +#[ignore] fn fmt() { if option_env!("RUSTC_TEST_SUITE").is_some() { return; From 925e8207fa8ff6cc4aea7337b6cb3eeb318123d3 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 21:58:29 +0100 Subject: [PATCH 074/133] Respond to review comments Update README and CHANGELOG using the util scripts, refine the help message and fix the float_cmp error. --- CHANGELOG.md | 1 + README.md | 2 +- clippy_lints/src/lib.rs | 5 +++-- clippy_lints/src/trait_bounds.rs | 18 +++++++++------- clippy_lints/src/utils/hir_utils.rs | 30 +++++++++++---------------- src/lintlist/mod.rs | 9 +++++++- tests/ui/float_cmp.stderr | 11 +++++++++- tests/ui/type_repetition_in_bounds.rs | 17 +++++++++------ 8 files changed, 57 insertions(+), 36 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff5aebbc8..089897811 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1138,6 +1138,7 @@ Released 2018-09-13 [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#trivially_copy_pass_by_ref [`try_err`]: https://rust-lang.github.io/rust-clippy/master/index.html#try_err [`type_complexity`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_complexity +[`type_repetition_in_bounds`]: https://rust-lang.github.io/rust-clippy/master/index.html#type_repetition_in_bounds [`unicode_not_nfc`]: https://rust-lang.github.io/rust-clippy/master/index.html#unicode_not_nfc [`unimplemented`]: https://rust-lang.github.io/rust-clippy/master/index.html#unimplemented [`unit_arg`]: https://rust-lang.github.io/rust-clippy/master/index.html#unit_arg diff --git a/README.md b/README.md index 1e649d898..38651f72e 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 308 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 309 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: diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index faffb1a67..908bbeb5e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -263,9 +263,9 @@ pub mod strings; pub mod suspicious_trait_impl; pub mod swap; pub mod temporary_assignment; +pub mod trait_bounds; pub mod transmute; pub mod transmuting_null; -pub mod trait_bounds; pub mod trivially_copy_pass_by_ref; pub mod try_err; pub mod types; @@ -860,6 +860,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { swap::ALMOST_SWAPPED, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, + trait_bounds::TYPE_REPETITION_IN_BOUNDS, transmute::CROSSPOINTER_TRANSMUTE, transmute::TRANSMUTE_BYTES_TO_STR, transmute::TRANSMUTE_INT_TO_BOOL, @@ -870,7 +871,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { transmute::USELESS_TRANSMUTE, transmute::WRONG_TRANSMUTE, transmuting_null::TRANSMUTING_NULL, - trait_bounds::TYPE_REPETITION_IN_BOUNDS, trivially_copy_pass_by_ref::TRIVIALLY_COPY_PASS_BY_REF, try_err::TRY_ERR, types::ABSURD_EXTREME_COMPARISONS, @@ -1042,6 +1042,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reference::REF_IN_DEREF, swap::MANUAL_SWAP, temporary_assignment::TEMPORARY_ASSIGNMENT, + trait_bounds::TYPE_REPETITION_IN_BOUNDS, transmute::CROSSPOINTER_TRANSMUTE, transmute::TRANSMUTE_BYTES_TO_STR, transmute::TRANSMUTE_INT_TO_BOOL, diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index f5ca3793d..8a719c0dd 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -1,8 +1,8 @@ use crate::utils::{in_macro, snippet, span_help_and_lint, SpanlessHash}; +use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, impl_lint_pass}; use rustc_data_structures::fx::FxHashMap; -use rustc::hir::*; #[derive(Copy, Clone)] pub struct TraitBounds; @@ -10,11 +10,12 @@ pub struct TraitBounds; declare_clippy_lint! { /// **What it does:** This lint warns about unnecessary type repetitions in trait bounds /// - /// **Why is this bad?** Complexity + /// **Why is this bad?** Repeating the type for every bound makes the code + /// less readable than combining the bounds /// /// **Example:** /// ```rust - /// pub fn foo(t: T) where T: Copy, T: Clone + /// pub fn foo(t: T) where T: Copy, T: Clone /// ``` /// /// Could be written as: @@ -34,7 +35,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { if in_macro(gen.span) { return; } - let hash = | ty | -> u64 { + let hash = |ty| -> u64 { let mut hasher = SpanlessHash::new(cx, cx.tables); hasher.hash_ty(ty); hasher.finish() @@ -44,17 +45,20 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TraitBounds { if let WherePredicate::BoundPredicate(ref p) = bound { let h = hash(&p.bounded_ty); if let Some(ref v) = map.insert(h, p.bounds.iter().collect::>()) { - let mut hint_string = format!("consider combining the bounds: `{}: ", snippet(cx, p.bounded_ty.span, "_")); + let mut hint_string = format!( + "consider combining the bounds: `{}:", + snippet(cx, p.bounded_ty.span, "_") + ); 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!(" {} +", path)); } } 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!(" {} +", path)); } } hint_string.truncate(hint_string.len() - 2); diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 449b8c439..db7b10c6b 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -639,23 +639,20 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { for ty in ty_list { self.hash_ty(ty); } - }, - TyKind::Path(qpath) => { - match qpath { - QPath::Resolved(ref maybe_ty, ref path) => { - if let Some(ref ty) = maybe_ty { - self.hash_ty(ty); - } - for segment in &path.segments { - segment.ident.name.hash(&mut self.s); - } - }, - QPath::TypeRelative(ref ty, ref segment) => { + TyKind::Path(qpath) => match qpath { + QPath::Resolved(ref maybe_ty, ref path) => { + if let Some(ref ty) = maybe_ty { self.hash_ty(ty); + } + for segment in &path.segments { segment.ident.name.hash(&mut self.s); - }, - } + } + }, + QPath::TypeRelative(ref ty, ref segment) => { + self.hash_ty(ty); + segment.ident.name.hash(&mut self.s); + }, }, TyKind::Def(_, arg_list) => { for arg in arg_list { @@ -670,14 +667,11 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { }, TyKind::TraitObject(_, lifetime) => { self.hash_lifetime(lifetime); - }, TyKind::Typeof(anon_const) => { self.hash_expr(&self.cx.tcx.hir().body(anon_const.body).value); }, - TyKind::CVarArgs(lifetime) => { - self.hash_lifetime(lifetime) - }, + TyKind::CVarArgs(lifetime) => self.hash_lifetime(lifetime), TyKind::Err | TyKind::Infer | TyKind::Never => {}, } } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 2d9e800b6..49bce5a6c 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 308] = [ +pub const ALL_LINTS: [Lint; 309] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -1848,6 +1848,13 @@ pub const ALL_LINTS: [Lint; 308] = [ deprecation: None, module: "types", }, + Lint { + name: "type_repetition_in_bounds", + group: "complexity", + desc: "Types are repeated unnecessary in trait bounds use `+` instead of using `T: _, T: _`", + deprecation: None, + module: "trait_bounds", + }, Lint { name: "unicode_not_nfc", group: "pedantic", diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index 5dc5fbf0f..d1ffc0d15 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,3 +1,12 @@ +error: this type has already been used as a bound predicate + --> $DIR/float_cmp.rs:12:5 + | +LL | T: Copy, + | ^^^^^^^ + | + = note: `-D clippy::type-repetition-in-bounds` implied by `-D warnings` + = help: consider combining the bounds: `T: Add, Copy` + error: strict comparison of f32 or f64 --> $DIR/float_cmp.rs:60:5 | @@ -35,5 +44,5 @@ note: std::f32::EPSILON and std::f64::EPSILON are available. LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/type_repetition_in_bounds.rs b/tests/ui/type_repetition_in_bounds.rs index 3aa0d0da5..8b538be76 100644 --- a/tests/ui/type_repetition_in_bounds.rs +++ b/tests/ui/type_repetition_in_bounds.rs @@ -1,14 +1,19 @@ #[deny(clippy::type_repetition_in_bounds)] -pub fn foo(_t: T) where T: Copy, T: Clone { +pub fn foo(_t: T) +where + T: Copy, + T: Clone, +{ unimplemented!(); } -pub fn bar(_t: T, _u: U) where T: Copy, U: Clone { +pub fn bar(_t: T, _u: U) +where + T: Copy, + U: Clone, +{ unimplemented!(); } - -fn main() { - -} +fn main() {} From bba2c7f02c3b49ce3f4d5f83f66b52dca5bd310b Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 22:53:26 +0100 Subject: [PATCH 075/133] Updated tests. Removed unnecessary type repetition in float test and regenerated stderr Regenerated type_repetition stderr --- tests/ui/float_cmp.rs | 3 +-- tests/ui/float_cmp.stderr | 23 +++++++---------------- tests/ui/type_repetition_in_bounds.stderr | 8 ++++---- 3 files changed, 12 insertions(+), 22 deletions(-) diff --git a/tests/ui/float_cmp.rs b/tests/ui/float_cmp.rs index 1ec8af3e3..207c1bcbb 100644 --- a/tests/ui/float_cmp.rs +++ b/tests/ui/float_cmp.rs @@ -8,8 +8,7 @@ const ONE: f32 = ZERO + 1.0; fn twice(x: T) -> T where - T: Add, - T: Copy, + T: Add + Copy, { x + x } diff --git a/tests/ui/float_cmp.stderr b/tests/ui/float_cmp.stderr index d1ffc0d15..116e3e90e 100644 --- a/tests/ui/float_cmp.stderr +++ b/tests/ui/float_cmp.stderr @@ -1,48 +1,39 @@ -error: this type has already been used as a bound predicate - --> $DIR/float_cmp.rs:12:5 - | -LL | T: Copy, - | ^^^^^^^ - | - = note: `-D clippy::type-repetition-in-bounds` implied by `-D warnings` - = help: consider combining the bounds: `T: Add, Copy` - error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:60:5 + --> $DIR/float_cmp.rs:59: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:60:5 + --> $DIR/float_cmp.rs:59:5 | LL | ONE as f64 != 2.0; | ^^^^^^^^^^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:65:5 + --> $DIR/float_cmp.rs:64: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:65:5 + --> $DIR/float_cmp.rs:64:5 | LL | x == 1.0; | ^^^^^^^^ error: strict comparison of f32 or f64 - --> $DIR/float_cmp.rs:68:5 + --> $DIR/float_cmp.rs:67: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:68:5 + --> $DIR/float_cmp.rs:67:5 | LL | twice(x) != twice(ONE as f64); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/type_repetition_in_bounds.stderr b/tests/ui/type_repetition_in_bounds.stderr index 6f5c67afb..a72f512b0 100644 --- a/tests/ui/type_repetition_in_bounds.stderr +++ b/tests/ui/type_repetition_in_bounds.stderr @@ -1,15 +1,15 @@ error: this type has already been used as a bound predicate - --> $DIR/type_repetition_in_bounds.rs:3:37 + --> $DIR/type_repetition_in_bounds.rs:6:5 | -LL | pub fn foo(_t: T) where T: Copy, T: Clone { - | ^^^^^^^^ +LL | T: Clone, + | ^^^^^^^^ | note: lint level defined here --> $DIR/type_repetition_in_bounds.rs:1:8 | LL | #[deny(clippy::type_repetition_in_bounds)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = help: consider combining the bounds: `T: Copy, Clone` + = help: consider combining the bounds: `T: Copy + Clone` error: aborting due to previous error From ad637193f0e5b90db1c934f3c637679514f67777 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 22:59:46 +0100 Subject: [PATCH 076/133] Hash discriminant of Lifetime::Name --- clippy_lints/src/utils/hir_utils.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index db7b10c6b..64f5f3525 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -584,6 +584,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_lifetime(&mut self, lifetime: &Lifetime) { if let LifetimeName::Param(ref name) = lifetime.name { + std::mem::discriminant(&name).hash(&mut self.s); match name { ParamName::Plain(ref ident) => { ident.name.hash(&mut self.s); @@ -591,7 +592,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ParamName::Fresh(ref size) => { size.hash(&mut self.s); }, - _ => {}, + ParamName::Error => {}, } } } From 03c543515ad3c963f801c65da8f8bb6a4e0a35da Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sat, 27 Jul 2019 23:04:36 +0100 Subject: [PATCH 077/133] Hash discriminant of lifetime.name --- clippy_lints/src/utils/hir_utils.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 64f5f3525..e3da8c494 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -583,6 +583,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } pub fn hash_lifetime(&mut self, lifetime: &Lifetime) { + std::mem::discriminant(&lifetime.name).hash(&mut self.s); if let LifetimeName::Param(ref name) = lifetime.name { std::mem::discriminant(&name).hash(&mut self.s); match name { From cc779c8050a863328ddf5c0197ba509473a54be7 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 28 Jul 2019 06:41:13 +0200 Subject: [PATCH 078/133] dev-fmt: better error handling Check if rustfmt is installed at the start and exit if it isn't. --- clippy_dev/src/fmt.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 5ccdbec14..3b5d6d2db 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -10,6 +10,7 @@ pub enum CliError { CommandFailed(String), IoError(io::Error), ProjectRootNotFound, + RustfmtNotInstalled, WalkDirError(walkdir::Error), } @@ -36,6 +37,8 @@ pub fn run(check: bool, verbose: bool) { let project_root = project_root()?; + rustfmt_test(context)?; + success &= cargo_fmt(context, project_root.as_path())?; success &= cargo_fmt(context, &project_root.join("clippy_dev"))?; success &= cargo_fmt(context, &project_root.join("rustc_tools_util"))?; @@ -69,6 +72,9 @@ pub fn run(check: bool, verbose: bool) { CliError::ProjectRootNotFound => { eprintln!("error: Can't determine root of project. Please run inside a Clippy working dir."); }, + CliError::RustfmtNotInstalled => { + eprintln!("error: rustfmt nightly is not installed."); + }, CliError::WalkDirError(err) => { eprintln!("error: {}", err); }, @@ -139,6 +145,29 @@ fn cargo_fmt(context: &FmtContext, path: &Path) -> Result { Ok(success) } +fn rustfmt_test(context: &FmtContext) -> Result<(), CliError> { + let program = "rustfmt"; + let dir = std::env::current_dir()?; + let args = &["+nightly", "--version"]; + + if context.verbose { + println!("{}", format_command(&program, &dir, args)); + } + + let output = Command::new(&program).current_dir(&dir).args(args.iter()).output()?; + + if output.status.success() { + Ok(()) + } else if std::str::from_utf8(&output.stderr) + .unwrap_or("") + .starts_with("error: 'rustfmt' is not installed") + { + Err(CliError::RustfmtNotInstalled) + } else { + Err(CliError::CommandFailed(format_command(&program, &dir, args))) + } +} + fn rustfmt(context: &FmtContext, path: &Path) -> Result { let mut args = vec!["+nightly".as_ref(), path.as_os_str()]; if context.check { From dae40767601ee9aa647b442130993bd8ad664f9f Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 28 Jul 2019 06:41:25 +0200 Subject: [PATCH 079/133] Skip fmt test if rustfmt is unavailble --- tests/fmt.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/tests/fmt.rs b/tests/fmt.rs index 4df93cf5a..65a1c50e4 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -1,3 +1,5 @@ +use std::process::Command; + #[test] #[ignore] fn fmt() { @@ -5,9 +7,20 @@ fn fmt() { return; } + // Skip this test if rustup nightly is unavailable + let rustup_output = Command::new("rustup") + .args(&["component", "list", "--toolchain", "nightly"]) + .output() + .unwrap(); + assert!(rustup_output.status.success()); + let component_output = String::from_utf8_lossy(&rustup_output.stdout); + if !component_output.contains("rustfmt") { + return; + } + let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); let dev_dir = root_dir.join("clippy_dev"); - let output = std::process::Command::new("cargo") + let output = Command::new("cargo") .current_dir(dev_dir) .args(&["+nightly", "run", "--", "fmt", "--check"]) .output() From a9714227bde1ad9e280d087acf513b0420afd871 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Sun, 28 Jul 2019 06:41:29 +0200 Subject: [PATCH 080/133] Enable rustfmt tests This reverts commit d73a953db7a8120ec00b31c57d7092aff0f2c10b. --- .travis.yml | 2 +- appveyor.yml | 2 +- tests/fmt.rs | 1 - 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0b012139d..0a1bd0ea2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -22,7 +22,7 @@ env: install: - | if [ -z ${INTEGRATION} ]; then - # rustup component add rustfmt || cargo install --git https://github.com/rust-lang/rustfmt/ --force + rustup component add rustfmt || cargo install --git https://github.com/rust-lang/rustfmt/ --force if [ "$TRAVIS_OS_NAME" == "linux" ]; then . $HOME/.nvm/nvm.sh nvm install stable diff --git a/appveyor.yml b/appveyor.yml index 4cea8d99e..9f6cc45af 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ install: - del rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master %RUSTC_HASH% -f -n master - #- rustup component add rustfmt --toolchain nightly + - rustup component add rustfmt --toolchain nightly - rustup default master - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V diff --git a/tests/fmt.rs b/tests/fmt.rs index 65a1c50e4..bc37be84b 100644 --- a/tests/fmt.rs +++ b/tests/fmt.rs @@ -1,7 +1,6 @@ use std::process::Command; #[test] -#[ignore] fn fmt() { if option_env!("RUSTC_TEST_SUITE").is_some() { return; From 78ebcaa5263e0fd4c4ec89da648d8386c034ce84 Mon Sep 17 00:00:00 2001 From: xd009642 Date: Sun, 28 Jul 2019 09:31:05 +0100 Subject: [PATCH 081/133] Fix dogfood test --- clippy_lints/src/utils/hir_utils.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index e3da8c494..6fc5939a2 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -438,7 +438,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { self.hash_expr(fun); self.hash_exprs(args); }, - ExprKind::Cast(ref e, ref ty) => { + ExprKind::Cast(ref e, ref ty) | ExprKind::Type(ref e, ref ty) => { self.hash_expr(e); self.hash_ty(ty); }, @@ -518,10 +518,6 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { ExprKind::Array(ref v) => { self.hash_exprs(v); }, - ExprKind::Type(ref e, ref ty) => { - self.hash_expr(e); - self.hash_ty(ty); - }, ExprKind::Unary(lop, ref le) => { lop.hash(&mut self.s); self.hash_expr(le); @@ -585,7 +581,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { pub fn hash_lifetime(&mut self, lifetime: &Lifetime) { std::mem::discriminant(&lifetime.name).hash(&mut self.s); if let LifetimeName::Param(ref name) = lifetime.name { - std::mem::discriminant(&name).hash(&mut self.s); + std::mem::discriminant(name).hash(&mut self.s); match name { ParamName::Plain(ref ident) => { ident.name.hash(&mut self.s); @@ -603,7 +599,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } pub fn hash_tykind(&mut self, ty: &TyKind) { - std::mem::discriminant(&ty).hash(&mut self.s); + std::mem::discriminant(ty).hash(&mut self.s); match ty { TyKind::Slice(ty) => { self.hash_ty(ty); From 82be293dfd532beb763c022f881bcac974d483a9 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 29 Jul 2019 07:51:44 +0200 Subject: [PATCH 082/133] Make appveyor build ignore rustfmt unavailability --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 9f6cc45af..23268d7e0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ install: - del rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master %RUSTC_HASH% -f -n master - - rustup component add rustfmt --toolchain nightly + - rustup component add rustfmt --toolchain nightly || echo "rustfmt night is unavailable" - rustup default master - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V From 2682bd112e14716fe128879abefff667c8a68766 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Mon, 29 Jul 2019 07:54:03 +0200 Subject: [PATCH 083/133] Correct typo --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 23268d7e0..092a5c80a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ install: - del rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master %RUSTC_HASH% -f -n master - - rustup component add rustfmt --toolchain nightly || echo "rustfmt night is unavailable" + - rustup component add rustfmt --toolchain nightly || echo "rustfmt nightly is unavailable" - rustup default master - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V From 2f5c1d031d881c29d18ee94ef575efed93e7e528 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Tue, 30 Jul 2019 06:37:49 +0200 Subject: [PATCH 084/133] Fix breakage due to rust-lang/rust#61856 --- clippy_lints/src/escape.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index cc5f05ede..f276014f4 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -1,5 +1,5 @@ use rustc::hir::intravisit as visit; -use rustc::hir::*; +use rustc::hir::{self, *}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::middle::expr_use_visitor::*; use rustc::middle::mem_categorization::{cmt_, Categorization}; @@ -101,6 +101,19 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxedLocal { } } +// TODO: Replace with Map::is_argument(..) when it's fixed +fn is_argument(map: &hir::map::Map<'_>, id: HirId) -> bool { + match map.find(id) { + Some(Node::Binding(_)) => (), + _ => return false, + } + + match map.find(map.get_parent_node(id)) { + Some(Node::Arg(_)) => true, + _ => false, + } +} + impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn consume(&mut self, _: HirId, _: Span, cmt: &cmt_<'tcx>, mode: ConsumeMode) { if let Categorization::Local(lid) = cmt.cat { @@ -113,11 +126,13 @@ impl<'a, 'tcx> Delegate<'tcx> for EscapeDelegate<'a, 'tcx> { fn matched_pat(&mut self, _: &Pat, _: &cmt_<'tcx>, _: MatchMode) {} fn consume_pat(&mut self, consume_pat: &Pat, cmt: &cmt_<'tcx>, _: ConsumeMode) { let map = &self.cx.tcx.hir(); - if map.is_argument(consume_pat.hir_id) { + if is_argument(map, consume_pat.hir_id) { // Skip closure arguments - if let Some(Node::Expr(..)) = map.find(map.get_parent_node(consume_pat.hir_id)) { + let parent_id = map.get_parent_node(consume_pat.hir_id); + if let Some(Node::Expr(..)) = map.find(map.get_parent_node(parent_id)) { return; } + if is_non_trait_box(cmt.ty) && !self.is_large_box(cmt.ty) { self.set.insert(consume_pat.hir_id); } From 41110b0039aca086216f675e148effc68b15bf1d Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Wed, 31 Jul 2019 00:24:28 +0000 Subject: [PATCH 085/133] Extend the `use_self` lint to suggest uses of `Self::Variant`. --- clippy_lints/src/use_self.rs | 62 +++++++++++++++++++++++------------- tests/ui/use_self.fixed | 8 +++++ tests/ui/use_self.rs | 8 +++++ tests/ui/use_self.stderr | 26 ++++++++++++--- 4 files changed, 78 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b60b9ccab..3f93e019c 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -51,9 +51,11 @@ declare_lint_pass!(UseSelf => [USE_SELF]); const SEGMENTS_MSG: &str = "segments should be composed of at least 1 element"; -fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path) { +fn span_use_self_lint(cx: &LateContext<'_, '_>, path: &Path, last_segment: Option<&PathSegment>) { + let last_segment = last_segment.unwrap_or_else(|| path.segments.last().expect(SEGMENTS_MSG)); + // Path segments only include actual path, no methods or fields. - let last_path_span = path.segments.last().expect(SEGMENTS_MSG).ident.span; + let last_path_span = last_segment.ident.span; // Only take path up to the end of last_path_span. let span = path.span.with_hi(last_path_span.hi()); @@ -80,22 +82,18 @@ impl<'a, 'tcx> Visitor<'tcx> for TraitImplTyVisitor<'a, 'tcx> { let trait_ty = self.trait_type_walker.next(); let impl_ty = self.impl_type_walker.next(); - if let TyKind::Path(QPath::Resolved(_, path)) = &t.node { + if_chain! { + if let TyKind::Path(QPath::Resolved(_, path)) = &t.node; + // 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 { - let is_self_ty = if let def::Res::SelfTy(..) = path.res { - true - } else { - false - }; - - if !is_self_ty { - span_use_self_lint(self.cx, path); - } - } + 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) } } } @@ -220,15 +218,35 @@ struct UseSelfVisitor<'a, 'tcx> { impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { fn visit_path(&mut self, path: &'tcx Path, _id: HirId) { - if path.segments.last().expect(SEGMENTS_MSG).ident.name != kw::SelfUpper { - if self.item_path.res == path.res { - span_use_self_lint(self.cx, path); - } else if let Res::Def(DefKind::Ctor(def::CtorOf::Struct, CtorKind::Fn), ctor_did) = path.res { - if self.item_path.res.opt_def_id() == self.cx.tcx.parent(ctor_did) { - span_use_self_lint(self.cx, path); + if path.segments.len() >= 2 { + let last_but_one = &path.segments[path.segments.len() - 2]; + if last_but_one.ident.name != kw::SelfUpper { + let enum_def_id = match path.res { + Res::Def(DefKind::Variant, variant_def_id) => + self.cx.tcx.parent(variant_def_id), + Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), ctor_def_id) => { + let variant_def_id = self.cx.tcx.parent(ctor_def_id); + variant_def_id.and_then(|def_id| self.cx.tcx.parent(def_id)) + } + _ => None + }; + + if self.item_path.res.opt_def_id() == enum_def_id { + span_use_self_lint(self.cx, path, Some(last_but_one)); } } } + + if path.segments.last().expect(SEGMENTS_MSG).ident.name != kw::SelfUpper { + if self.item_path.res == path.res { + span_use_self_lint(self.cx, path, None); + } else if let Res::Def(DefKind::Ctor(def::CtorOf::Struct, CtorKind::Fn), ctor_def_id) = path.res { + if self.item_path.res.opt_def_id() == self.cx.tcx.parent(ctor_def_id) { + span_use_self_lint(self.cx, path, None); + } + } + } + walk_path(self, path); } diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index 68af85030..ac2a1708b 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -265,6 +265,8 @@ mod nesting { enum Enum { A, + B(u64), + C { field: bool } } impl Enum { fn method() { @@ -272,6 +274,12 @@ mod nesting { use self::Enum::*; // Issue 3425 static STATIC: Enum = Enum::A; // Can't use Self as type } + + fn method2() { + let _ = Self::B(42); + let _ = Self::C { field: true }; + let _ = Self::A; + } } } diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 7a6d41552..21b5833e5 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -265,6 +265,8 @@ mod nesting { enum Enum { A, + B(u64), + C { field: bool } } impl Enum { fn method() { @@ -272,6 +274,12 @@ mod nesting { use self::Enum::*; // Issue 3425 static STATIC: Enum = Enum::A; // Can't use Self as type } + + fn method2() { + let _ = Enum::B(42); + let _ = Enum::C { field: true }; + let _ = Enum::A; + } } } diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index bf1f41fd6..12dd672e3 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -175,22 +175,40 @@ LL | Bar { foo: Foo {} } | ^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:304:13 + --> $DIR/use_self.rs:279:21 + | +LL | let _ = Enum::B(42); + | ^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:280:21 + | +LL | let _ = Enum::C { field: true }; + | ^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:281:21 + | +LL | let _ = Enum::A; + | ^^^^ help: use the applicable keyword: `Self` + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:312:13 | LL | nested::A::fun_1(); | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:305:13 + --> $DIR/use_self.rs:313:13 | LL | nested::A::A; | ^^^^^^^^^ help: use the applicable keyword: `Self` error: unnecessary structure name repetition - --> $DIR/use_self.rs:307:13 + --> $DIR/use_self.rs:315:13 | LL | nested::A {}; | ^^^^^^^^^ help: use the applicable keyword: `Self` -error: aborting due to 31 previous errors +error: aborting due to 34 previous errors From 2a13e83f2baafed62db958aa202666a4182c4fb5 Mon Sep 17 00:00:00 2001 From: Jakub Wieczorek Date: Wed, 31 Jul 2019 00:25:35 +0000 Subject: [PATCH 086/133] Update all the code to pass the updated `use_self` lint. One struct required a temporary `#[allow(dead_code)]` annotation due to a bug in the Rust compiler: https://github.com/rust-lang/rust/issues/63151. --- clippy_dev/src/fmt.rs | 4 +- clippy_lints/src/checked_conversions.rs | 6 +-- clippy_lints/src/consts.rs | 56 +++++++++++----------- clippy_lints/src/excessive_precision.rs | 12 ++--- clippy_lints/src/literal_representation.rs | 14 +++--- clippy_lints/src/methods/mod.rs | 40 ++++++++-------- clippy_lints/src/non_copy_const.rs | 5 +- clippy_lints/src/ptr_offset_with_cast.rs | 8 ++-- clippy_lints/src/types.rs | 8 ++-- clippy_lints/src/utils/conf.rs | 6 +-- 10 files changed, 80 insertions(+), 79 deletions(-) diff --git a/clippy_dev/src/fmt.rs b/clippy_dev/src/fmt.rs index 5ccdbec14..e23673f27 100644 --- a/clippy_dev/src/fmt.rs +++ b/clippy_dev/src/fmt.rs @@ -15,13 +15,13 @@ pub enum CliError { impl From for CliError { fn from(error: io::Error) -> Self { - CliError::IoError(error) + Self::IoError(error) } } impl From for CliError { fn from(error: walkdir::Error) -> Self { - CliError::WalkDirError(error) + Self::WalkDirError(error) } } diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index 3c335acb4..c23f2fbc0 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -160,12 +160,12 @@ impl ConversionType { /// Creates a conversion type if the type is allowed & conversion is valid fn try_new(from: &str, to: &str) -> Option { if UINTS.contains(&from) { - Some(ConversionType::FromUnsigned) + Some(Self::FromUnsigned) } else if SINTS.contains(&from) { if UINTS.contains(&to) { - Some(ConversionType::SignedToUnsigned) + Some(Self::SignedToUnsigned) } else if SINTS.contains(&to) { - Some(ConversionType::SignedToSigned) + Some(Self::SignedToSigned) } else { None } diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 9f6cfe04c..d18474abd 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -48,27 +48,27 @@ pub enum Constant { impl PartialEq for Constant { fn eq(&self, other: &Self) -> bool { match (self, other) { - (&Constant::Str(ref ls), &Constant::Str(ref rs)) => ls == rs, - (&Constant::Binary(ref l), &Constant::Binary(ref r)) => l == r, - (&Constant::Char(l), &Constant::Char(r)) => l == r, - (&Constant::Int(l), &Constant::Int(r)) => l == r, - (&Constant::F64(l), &Constant::F64(r)) => { + (&Self::Str(ref ls), &Self::Str(ref rs)) => ls == rs, + (&Self::Binary(ref l), &Self::Binary(ref r)) => l == r, + (&Self::Char(l), &Self::Char(r)) => l == r, + (&Self::Int(l), &Self::Int(r)) => l == r, + (&Self::F64(l), &Self::F64(r)) => { // We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have // `Fw32 == Fw64`, so don’t compare them. // `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs. l.to_bits() == r.to_bits() }, - (&Constant::F32(l), &Constant::F32(r)) => { + (&Self::F32(l), &Self::F32(r)) => { // We want `Fw32 == FwAny` and `FwAny == Fw64`, and by transitivity we must have // `Fw32 == Fw64`, so don’t compare them. // `to_bits` is required to catch non-matching 0.0, -0.0, and NaNs. f64::from(l).to_bits() == f64::from(r).to_bits() }, - (&Constant::Bool(l), &Constant::Bool(r)) => l == r, - (&Constant::Vec(ref l), &Constant::Vec(ref r)) | (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) => { + (&Self::Bool(l), &Self::Bool(r)) => l == r, + (&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => { l == r }, - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, + (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, // TODO: are there inter-type equalities? _ => false, } @@ -82,38 +82,38 @@ impl Hash for Constant { { std::mem::discriminant(self).hash(state); match *self { - Constant::Str(ref s) => { + Self::Str(ref s) => { s.hash(state); }, - Constant::Binary(ref b) => { + Self::Binary(ref b) => { b.hash(state); }, - Constant::Char(c) => { + Self::Char(c) => { c.hash(state); }, - Constant::Int(i) => { + Self::Int(i) => { i.hash(state); }, - Constant::F32(f) => { + Self::F32(f) => { f64::from(f).to_bits().hash(state); }, - Constant::F64(f) => { + Self::F64(f) => { f.to_bits().hash(state); }, - Constant::Bool(b) => { + Self::Bool(b) => { b.hash(state); }, - Constant::Vec(ref v) | Constant::Tuple(ref v) => { + Self::Vec(ref v) | Self::Tuple(ref v) => { v.hash(state); }, - Constant::Repeat(ref c, l) => { + Self::Repeat(ref c, l) => { c.hash(state); l.hash(state); }, - Constant::RawPtr(u) => { + Self::RawPtr(u) => { u.hash(state); }, - Constant::Err(ref s) => { + Self::Err(ref s) => { s.hash(state); }, } @@ -123,25 +123,25 @@ impl Hash for Constant { impl Constant { pub fn partial_cmp(tcx: TyCtxt<'_>, cmp_type: Ty<'_>, left: &Self, right: &Self) -> Option { match (left, right) { - (&Constant::Str(ref ls), &Constant::Str(ref rs)) => Some(ls.cmp(rs)), - (&Constant::Char(ref l), &Constant::Char(ref r)) => Some(l.cmp(r)), - (&Constant::Int(l), &Constant::Int(r)) => { + (&Self::Str(ref ls), &Self::Str(ref rs)) => Some(ls.cmp(rs)), + (&Self::Char(ref l), &Self::Char(ref r)) => Some(l.cmp(r)), + (&Self::Int(l), &Self::Int(r)) => { if let ty::Int(int_ty) = cmp_type.sty { Some(sext(tcx, l, int_ty).cmp(&sext(tcx, r, int_ty))) } else { Some(l.cmp(&r)) } }, - (&Constant::F64(l), &Constant::F64(r)) => l.partial_cmp(&r), - (&Constant::F32(l), &Constant::F32(r)) => l.partial_cmp(&r), - (&Constant::Bool(ref l), &Constant::Bool(ref r)) => Some(l.cmp(r)), - (&Constant::Tuple(ref l), &Constant::Tuple(ref r)) | (&Constant::Vec(ref l), &Constant::Vec(ref r)) => l + (&Self::F64(l), &Self::F64(r)) => l.partial_cmp(&r), + (&Self::F32(l), &Self::F32(r)) => l.partial_cmp(&r), + (&Self::Bool(ref l), &Self::Bool(ref r)) => Some(l.cmp(r)), + (&Self::Tuple(ref l), &Self::Tuple(ref r)) | (&Self::Vec(ref l), &Self::Vec(ref r)) => l .iter() .zip(r.iter()) .map(|(li, ri)| Self::partial_cmp(tcx, cmp_type, li, ri)) .find(|r| r.map_or(true, |o| o != Ordering::Equal)) .unwrap_or_else(|| Some(l.len().cmp(&r.len()))), - (&Constant::Repeat(ref lv, ref ls), &Constant::Repeat(ref rv, ref rs)) => { + (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => { match Self::partial_cmp(tcx, cmp_type, lv, rv) { Some(Equal) => Some(ls.cmp(rs)), x => x, diff --git a/clippy_lints/src/excessive_precision.rs b/clippy_lints/src/excessive_precision.rs index 5f6312378..e996bac39 100644 --- a/clippy_lints/src/excessive_precision.rs +++ b/clippy_lints/src/excessive_precision.rs @@ -143,20 +143,20 @@ impl FloatFormat { fn new(s: &str) -> Self { s.chars() .find_map(|x| match x { - 'e' => Some(FloatFormat::LowerExp), - 'E' => Some(FloatFormat::UpperExp), + 'e' => Some(Self::LowerExp), + 'E' => Some(Self::UpperExp), _ => None, }) - .unwrap_or(FloatFormat::Normal) + .unwrap_or(Self::Normal) } fn format(&self, f: T) -> String where T: fmt::UpperExp + fmt::LowerExp + fmt::Display, { match self { - FloatFormat::LowerExp => format!("{:e}", f), - FloatFormat::UpperExp => format!("{:E}", f), - FloatFormat::Normal => format!("{}", f), + Self::LowerExp => format!("{:e}", f), + Self::UpperExp => format!("{:E}", f), + Self::Normal => format!("{}", f), } } } diff --git a/clippy_lints/src/literal_representation.rs b/clippy_lints/src/literal_representation.rs index c2892a278..9cc957f14 100644 --- a/clippy_lints/src/literal_representation.rs +++ b/clippy_lints/src/literal_representation.rs @@ -115,8 +115,8 @@ impl Radix { /// Returns a reasonable digit group size for this radix. crate fn suggest_grouping(&self) -> usize { match *self { - Radix::Binary | Radix::Hexadecimal => 4, - Radix::Octal | Radix::Decimal => 3, + Self::Binary | Self::Hexadecimal => 4, + Self::Octal | Self::Decimal => 3, } } } @@ -285,7 +285,7 @@ enum WarningType { impl WarningType { crate fn display(&self, grouping_hint: &str, cx: &EarlyContext<'_>, span: syntax_pos::Span) { match self { - WarningType::MistypedLiteralSuffix => span_lint_and_sugg( + Self::MistypedLiteralSuffix => span_lint_and_sugg( cx, MISTYPED_LITERAL_SUFFIXES, span, @@ -294,7 +294,7 @@ impl WarningType { grouping_hint.to_string(), Applicability::MaybeIncorrect, ), - WarningType::UnreadableLiteral => span_lint_and_sugg( + Self::UnreadableLiteral => span_lint_and_sugg( cx, UNREADABLE_LITERAL, span, @@ -303,7 +303,7 @@ impl WarningType { grouping_hint.to_owned(), Applicability::MachineApplicable, ), - WarningType::LargeDigitGroups => span_lint_and_sugg( + Self::LargeDigitGroups => span_lint_and_sugg( cx, LARGE_DIGIT_GROUPS, span, @@ -312,7 +312,7 @@ impl WarningType { grouping_hint.to_owned(), Applicability::MachineApplicable, ), - WarningType::InconsistentDigitGrouping => span_lint_and_sugg( + Self::InconsistentDigitGrouping => span_lint_and_sugg( cx, INCONSISTENT_DIGIT_GROUPING, span, @@ -321,7 +321,7 @@ impl WarningType { grouping_hint.to_owned(), Applicability::MachineApplicable, ), - WarningType::DecimalRepresentation => span_lint_and_sugg( + Self::DecimalRepresentation => span_lint_and_sugg( cx, DECIMAL_LITERAL_REPRESENTATION, span, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f689a2d4e..02dfb3e32 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2505,14 +2505,14 @@ impl SelfKind { let is_actually_self = |ty| is_self_ty(ty) || SpanlessEq::new(cx).eq_ty(ty, self_ty); if is_self(arg) { match self { - SelfKind::Value => is_actually_self(ty), - SelfKind::Ref | SelfKind::RefMut => { + Self::Value => is_actually_self(ty), + Self::Ref | Self::RefMut => { if allow_value_for_ref && is_actually_self(ty) { return true; } match ty.node { hir::TyKind::Rptr(_, ref mt_ty) => { - let mutability_match = if self == SelfKind::Ref { + let mutability_match = if self == Self::Ref { mt_ty.mutbl == hir::MutImmutable } else { mt_ty.mutbl == hir::MutMutable @@ -2526,20 +2526,20 @@ impl SelfKind { } } else { match self { - SelfKind::Value => false, - SelfKind::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT), - SelfKind::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT), - SelfKind::No => true, + Self::Value => false, + Self::Ref => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASREF_TRAIT), + Self::RefMut => is_as_ref_or_mut_trait(ty, self_ty, generics, &paths::ASMUT_TRAIT), + Self::No => true, } } } fn description(self) -> &'static str { match self { - SelfKind::Value => "self by value", - SelfKind::Ref => "self by reference", - SelfKind::RefMut => "self by mutable reference", - SelfKind::No => "no self", + Self::Value => "self by value", + Self::Ref => "self by reference", + Self::RefMut => "self by mutable reference", + Self::No => "no self", } } } @@ -2609,8 +2609,8 @@ fn single_segment_ty(ty: &hir::Ty) -> Option<&hir::PathSegment> { impl Convention { fn check(&self, other: &str) -> bool { match *self { - Convention::Eq(this) => this == other, - Convention::StartsWith(this) => other.starts_with(this) && this != other, + Self::Eq(this) => this == other, + Self::StartsWith(this) => other.starts_with(this) && this != other, } } } @@ -2618,8 +2618,8 @@ impl Convention { impl fmt::Display for Convention { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { - Convention::Eq(this) => this.fmt(f), - Convention::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), + Self::Eq(this) => this.fmt(f), + Self::StartsWith(this) => this.fmt(f).and_then(|_| '*'.fmt(f)), } } } @@ -2636,11 +2636,11 @@ impl OutType { fn matches(self, cx: &LateContext<'_, '_>, ty: &hir::FunctionRetTy) -> bool { let is_unit = |ty: &hir::Ty| SpanlessEq::new(cx).eq_ty_kind(&ty.node, &hir::TyKind::Tup(vec![].into())); match (self, ty) { - (OutType::Unit, &hir::DefaultReturn(_)) => true, - (OutType::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, - (OutType::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, - (OutType::Any, &hir::Return(ref ty)) if !is_unit(ty) => true, - (OutType::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)), + (Self::Unit, &hir::DefaultReturn(_)) => true, + (Self::Unit, &hir::Return(ref ty)) if is_unit(ty) => true, + (Self::Bool, &hir::Return(ref ty)) if is_bool(ty) => true, + (Self::Any, &hir::Return(ref ty)) if !is_unit(ty) => true, + (Self::Ref, &hir::Return(ref ty)) => matches!(ty.node, hir::TyKind::Rptr(_, _)), _ => false, } } diff --git a/clippy_lints/src/non_copy_const.rs b/clippy_lints/src/non_copy_const.rs index 62e4f692e..644660100 100644 --- a/clippy_lints/src/non_copy_const.rs +++ b/clippy_lints/src/non_copy_const.rs @@ -84,6 +84,7 @@ declare_clippy_lint! { "referencing const with interior mutability" } +#[allow(dead_code)] #[derive(Copy, Clone)] enum Source { Item { item: Span }, @@ -94,12 +95,12 @@ enum Source { impl Source { fn lint(&self) -> (&'static Lint, &'static str, Span) { match self { - Source::Item { item } | Source::Assoc { item, .. } => ( + Self::Item { item } | Self::Assoc { item, .. } => ( DECLARE_INTERIOR_MUTABLE_CONST, "a const item should never be interior mutable", *item, ), - Source::Expr { expr } => ( + Self::Expr { expr } => ( BORROW_INTERIOR_MUTABLE_CONST, "a const item with interior mutability should not be borrowed", *expr, diff --git a/clippy_lints/src/ptr_offset_with_cast.rs b/clippy_lints/src/ptr_offset_with_cast.rs index 152140c85..ffd6d4ca0 100644 --- a/clippy_lints/src/ptr_offset_with_cast.rs +++ b/clippy_lints/src/ptr_offset_with_cast.rs @@ -133,8 +133,8 @@ enum Method { impl Method { fn suggestion(self) -> &'static str { match self { - Method::Offset => "add", - Method::WrappingOffset => "wrapping_add", + Self::Offset => "add", + Self::WrappingOffset => "wrapping_add", } } } @@ -142,8 +142,8 @@ impl Method { impl fmt::Display for Method { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Method::Offset => write!(f, "offset"), - Method::WrappingOffset => write!(f, "wrapping_offset"), + Self::Offset => write!(f, "offset"), + Self::WrappingOffset => write!(f, "wrapping_offset"), } } } diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3610c3d12..31d4c3658 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1725,10 +1725,10 @@ impl PartialEq for FullInt { impl PartialOrd for FullInt { fn partial_cmp(&self, other: &Self) -> Option { Some(match (self, other) { - (&FullInt::S(s), &FullInt::S(o)) => s.cmp(&o), - (&FullInt::U(s), &FullInt::U(o)) => s.cmp(&o), - (&FullInt::S(s), &FullInt::U(o)) => Self::cmp_s_u(s, o), - (&FullInt::U(s), &FullInt::S(o)) => Self::cmp_s_u(o, s).reverse(), + (&Self::S(s), &Self::S(o)) => s.cmp(&o), + (&Self::U(s), &Self::U(o)) => s.cmp(&o), + (&Self::S(s), &Self::U(o)) => Self::cmp_s_u(s, o), + (&Self::U(s), &Self::S(o)) => Self::cmp_s_u(o, s).reverse(), }) } } diff --git a/clippy_lints/src/utils/conf.rs b/clippy_lints/src/utils/conf.rs index efa2697d0..0c5db79df 100644 --- a/clippy_lints/src/utils/conf.rs +++ b/clippy_lints/src/utils/conf.rs @@ -44,15 +44,15 @@ pub enum Error { impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match *self { - Error::Io(ref err) => err.fmt(f), - Error::Toml(ref err) => err.fmt(f), + Self::Io(ref err) => err.fmt(f), + Self::Toml(ref err) => err.fmt(f), } } } impl From for Error { fn from(e: io::Error) -> Self { - Error::Io(e) + Self::Io(e) } } From 2d467dca62917b9b29b8739fb1a0509262aeca63 Mon Sep 17 00:00:00 2001 From: chansuke Date: Mon, 29 Jul 2019 23:42:33 +0900 Subject: [PATCH 087/133] Add required negation in non_zero lint --- clippy_lints/src/len_zero.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index be1c2a112..ea302ed9f 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -244,7 +244,7 @@ fn check_len( LEN_ZERO, span, &format!("length comparison to {}", if compare_to == 0 { "zero" } else { "one" }), - "using `is_empty` is clearer and more explicit", + &format!("using `{}is_empty` is clearer and more explicit", op), format!( "{}{}.is_empty()", op, From 38e7bd20f29bfb6693f32fe7347ace0b95c7e7eb Mon Sep 17 00:00:00 2001 From: Manish Goregaokar Date: Wed, 31 Jul 2019 08:38:08 -0700 Subject: [PATCH 088/133] Don't nudge people towards toilet closures when producing owl results --- tests/ui/drop_forget_ref.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index b3c75bc57..b60f373e7 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -55,3 +55,38 @@ fn test_similarly_named_function() { forget(&SomeStruct); //OK; call to unrelated function which happens to have the same name std::mem::forget(&SomeStruct); } + +#[derive(Copy, Clone)] +pub struct Error; +fn produce_half_owl_error() -> Result<(), Error> { + Ok(()) +} + +fn produce_half_owl_ok() -> Result { + Ok(true) +} + +#[allow(dead_code)] +fn test_owl_result() -> Result<(), ()> { + produce_half_owl_error().map_err(|_| ())?; + produce_half_owl_ok().map(|_| ())?; + // the following should not be linted, + // we should not force users to use toilet closures + // to produce owl results when drop is more convenient + produce_half_owl_error().map_err(drop)?; + produce_half_owl_ok().map_err(drop)?; + Ok(()) +} + + +#[allow(dead_code)] +fn test_owl_result_2() -> Result { + produce_half_owl_error().map_err(|_| ())?; + produce_half_owl_ok().map(|_| ())?; + // the following should not be linted, + // we should not force users to use toilet closures + // to produce owl results when drop is more convenient + produce_half_owl_error().map_err(drop)?; + produce_half_owl_ok().map(drop)?; + Ok(1) +} From 04ca58a691c60771fee566867d9712458180ad4a Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Wed, 31 Jul 2019 21:05:31 +0200 Subject: [PATCH 089/133] Mark `fn_to_numeric_cast` lints as MaybeIncorrect At least for now so that `cargo fix --clippy` is not causing problems with this lint. cc #3630, #3896 --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 31d4c3658..1516428d3 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1251,7 +1251,7 @@ fn lint_fn_to_numeric_cast( } match cast_from.sty { ty::FnDef(..) | ty::FnPtr(_) => { - let mut applicability = Applicability::MachineApplicable; + let mut applicability = Applicability::MaybeIncorrect; let from_snippet = snippet_with_applicability(cx, cast_expr.span, "x", &mut applicability); let to_nbits = int_ty_to_nbits(cast_to, cx.tcx); From 533abfa613aae4ac8b8575dba426bf03199e014d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Thu, 1 Aug 2019 06:54:57 +0200 Subject: [PATCH 090/133] UI Test Cleanup: No wrong_self_convention in methods.rs These cases are already covered in `tests/ui/wrong_self_convention.rs`. cc #2038 --- tests/ui/methods.rs | 3 +- tests/ui/methods.stderr | 62 ++++++++++++++--------------------------- 2 files changed, 23 insertions(+), 42 deletions(-) diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index 1b50c94ac..32e73988d 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -12,7 +12,8 @@ clippy::default_trait_access, clippy::use_self, clippy::new_ret_no_self, - clippy::useless_format + clippy::useless_format, + clippy::wrong_self_convention )] #[macro_use] diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index 8d28c3282..ab9762178 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:35:5 + --> $DIR/methods.rs:36:5 | LL | / pub fn add(self, other: T) -> T { LL | | self @@ -8,28 +8,8 @@ LL | | } | = note: `-D clippy::should-implement-trait` implied by `-D warnings` -error: methods called `into_*` usually take self by value; consider choosing a less ambiguous name - --> $DIR/methods.rs:70:17 - | -LL | fn into_u16(&self) -> u16 { - | ^^^^^ - | - = note: `-D clippy::wrong-self-convention` implied by `-D warnings` - -error: methods called `to_*` usually take self by reference; consider choosing a less ambiguous name - --> $DIR/methods.rs:74:21 - | -LL | fn to_something(self) -> u32 { - | ^^^^ - -error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:78:12 - | -LL | fn new(self) -> Self { - | ^^^^ - error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:157:13 + --> $DIR/methods.rs:158:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -41,7 +21,7 @@ LL | | .unwrap_or(0); = note: replace `map(|x| x + 1).unwrap_or(0)` with `map_or(0, |x| x + 1)` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:161:13 + --> $DIR/methods.rs:162:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -51,7 +31,7 @@ LL | | ).unwrap_or(0); | |____________________________^ error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:165:13 + --> $DIR/methods.rs:166:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -61,7 +41,7 @@ LL | | }); | |__________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:170:13 + --> $DIR/methods.rs:171:13 | LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -69,7 +49,7 @@ LL | let _ = opt.map(|x| Some(x + 1)).unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:172:13 + --> $DIR/methods.rs:173:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -79,7 +59,7 @@ LL | | ).unwrap_or(None); | |_____________________^ error: called `map(f).unwrap_or(None)` on an Option value. This can be done more directly by calling `and_then(f)` instead - --> $DIR/methods.rs:176:13 + --> $DIR/methods.rs:177:13 | LL | let _ = opt | _____________^ @@ -90,7 +70,7 @@ LL | | .unwrap_or(None); = note: replace `map(|x| Some(x + 1)).unwrap_or(None)` with `and_then(|x| Some(x + 1))` error: called `map(f).unwrap_or(a)` on an Option value. This can be done more directly by calling `map_or(a, f)` instead - --> $DIR/methods.rs:187:13 + --> $DIR/methods.rs:188:13 | LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -98,7 +78,7 @@ LL | let _ = Some("prefix").map(|p| format!("{}.", p)).unwrap_or(id); = note: replace `map(|p| format!("{}.", p)).unwrap_or(id)` with `map_or(id, |p| format!("{}.", p))` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:191:13 + --> $DIR/methods.rs:192:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -110,7 +90,7 @@ LL | | .unwrap_or_else(|| 0); = note: replace `map(|x| x + 1).unwrap_or_else(|| 0)` with `map_or_else(|| 0, |x| x + 1)` error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:195:13 + --> $DIR/methods.rs:196:13 | LL | let _ = opt.map(|x| { | _____________^ @@ -120,7 +100,7 @@ LL | | ).unwrap_or_else(|| 0); | |____________________________________^ error: called `map(f).unwrap_or_else(g)` on an Option value. This can be done more directly by calling `map_or_else(g, f)` instead - --> $DIR/methods.rs:199:13 + --> $DIR/methods.rs:200:13 | LL | let _ = opt.map(|x| x + 1) | _____________^ @@ -130,7 +110,7 @@ LL | | ); | |_________________^ error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:229:13 + --> $DIR/methods.rs:230:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -139,7 +119,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:232:13 + --> $DIR/methods.rs:233:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -149,7 +129,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:248:13 + --> $DIR/methods.rs:249:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -158,7 +138,7 @@ LL | let _ = v.iter().find(|&x| *x < 0).is_some(); = note: replace `find(|&x| *x < 0).is_some()` with `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:251:13 + --> $DIR/methods.rs:252:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -168,7 +148,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with position. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:257:13 + --> $DIR/methods.rs:258:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -176,7 +156,7 @@ LL | let _ = v.iter().position(|&x| x < 0).is_some(); = note: replace `position(|&x| x < 0).is_some()` with `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:260:13 + --> $DIR/methods.rs:261:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -186,7 +166,7 @@ LL | | ).is_some(); | |______________________________^ error: called `is_some()` after searching an `Iterator` with rposition. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:266:13 + --> $DIR/methods.rs:267:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -194,7 +174,7 @@ LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); = note: replace `rposition(|&x| x < 0).is_some()` with `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:269:13 + --> $DIR/methods.rs:270:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -204,12 +184,12 @@ LL | | ).is_some(); | |______________________________^ error: used unwrap() on an Option value. If you don't want to handle the None case gracefully, consider using expect() to provide a better panic message - --> $DIR/methods.rs:284:13 + --> $DIR/methods.rs:285:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 23 previous errors +error: aborting due to 20 previous errors From be646ac0dff10f154855b9dc706294c2a4ee9059 Mon Sep 17 00:00:00 2001 From: Michael Wright Date: Thu, 1 Aug 2019 07:09:57 +0200 Subject: [PATCH 091/133] Update formatting --- clippy_lints/src/consts.rs | 4 +--- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/open_options.rs | 8 ++++---- clippy_lints/src/redundant_static_lifetimes.rs | 3 ++- clippy_lints/src/use_self.rs | 7 +++---- rustc_tools_util/src/lib.rs | 1 - tests/ui/checked_unwrap/simple_conditionals.rs | 6 ++++-- tests/ui/drop_forget_ref.rs | 1 - tests/ui/use_self.fixed | 2 +- tests/ui/use_self.rs | 2 +- 10 files changed, 17 insertions(+), 19 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index d18474abd..9d1cc110e 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -65,9 +65,7 @@ impl PartialEq for Constant { f64::from(l).to_bits() == f64::from(r).to_bits() }, (&Self::Bool(l), &Self::Bool(r)) => l == r, - (&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => { - l == r - }, + (&Self::Vec(ref l), &Self::Vec(ref r)) | (&Self::Tuple(ref l), &Self::Tuple(ref r)) => l == r, (&Self::Repeat(ref lv, ref ls), &Self::Repeat(ref rv, ref rs)) => ls == rs && lv == rv, // TODO: are there inter-type equalities? _ => false, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index c2e42a0a9..c9df436da 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -305,7 +305,7 @@ impl EarlyLintPass for MiscEarlyLints { name makes code comprehension and documentation more difficult", arg_name[1..].to_owned() ), - );; + ); } } else { registered_names.insert(arg_name, arg.pat.span); diff --git a/clippy_lints/src/open_options.rs b/clippy_lints/src/open_options.rs index e115769ab..5a3af2c37 100644 --- a/clippy_lints/src/open_options.rs +++ b/clippy_lints/src/open_options.rs @@ -127,7 +127,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument } else { create = true } - create_arg = create_arg || (arg == Argument::True);; + create_arg = create_arg || (arg == Argument::True); }, (OpenOption::Append, arg) => { if append { @@ -140,7 +140,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument } else { append = true } - append_arg = append_arg || (arg == Argument::True);; + append_arg = append_arg || (arg == Argument::True); }, (OpenOption::Truncate, arg) => { if truncate { @@ -166,7 +166,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument } else { read = true } - read_arg = read_arg || (arg == Argument::True);; + read_arg = read_arg || (arg == Argument::True); }, (OpenOption::Write, arg) => { if write { @@ -179,7 +179,7 @@ fn check_open_options(cx: &LateContext<'_, '_>, options: &[(OpenOption, Argument } else { write = true } - write_arg = write_arg || (arg == Argument::True);; + write_arg = write_arg || (arg == Argument::True); }, } } diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index bdd48fe86..4d9fbbca8 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -81,7 +81,8 @@ impl EarlyLintPass for RedundantStaticLifetimes { if !in_macro_or_desugar(item.span) { if let ItemKind::Const(ref var_type, _) = item.node { self.visit_type(var_type, cx, "Constants have by default a `'static` lifetime"); - // Don't check associated consts because `'static` cannot be elided on those (issue #2438) + // Don't check associated consts because `'static` cannot be elided on those (issue + // #2438) } if let ItemKind::Static(ref var_type, _, _) = item.node { diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index 3f93e019c..4e2e97ddf 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -222,13 +222,12 @@ impl<'a, 'tcx> Visitor<'tcx> for UseSelfVisitor<'a, 'tcx> { let last_but_one = &path.segments[path.segments.len() - 2]; if last_but_one.ident.name != kw::SelfUpper { let enum_def_id = match path.res { - Res::Def(DefKind::Variant, variant_def_id) => - self.cx.tcx.parent(variant_def_id), + Res::Def(DefKind::Variant, variant_def_id) => self.cx.tcx.parent(variant_def_id), Res::Def(DefKind::Ctor(def::CtorOf::Variant, _), ctor_def_id) => { let variant_def_id = self.cx.tcx.parent(ctor_def_id); variant_def_id.and_then(|def_id| self.cx.tcx.parent(def_id)) - } - _ => None + }, + _ => None, }; if self.item_path.res.opt_def_id() == enum_def_id { diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index ec3b69219..92b710614 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -154,5 +154,4 @@ mod test { "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 2, patch: 0 }" ); } - } diff --git a/tests/ui/checked_unwrap/simple_conditionals.rs b/tests/ui/checked_unwrap/simple_conditionals.rs index c20c4a7a7..c080ae826 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.rs +++ b/tests/ui/checked_unwrap/simple_conditionals.rs @@ -31,10 +31,12 @@ fn main() { if x.is_ok() { x = Err(()); x.unwrap(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enough to see this (it only checks if conditions). + // it will always panic but the lint is not smart enough to see this (it only + // checks if conditions). } else { x = Ok(()); x.unwrap_err(); // not unnecessary because of mutation of x - // it will always panic but the lint is not smart enough to see this (it only checks if conditions). + // it will always panic but the lint is not smart enough to see this (it + // only checks if conditions). } } diff --git a/tests/ui/drop_forget_ref.rs b/tests/ui/drop_forget_ref.rs index b60f373e7..aad996c03 100644 --- a/tests/ui/drop_forget_ref.rs +++ b/tests/ui/drop_forget_ref.rs @@ -78,7 +78,6 @@ fn test_owl_result() -> Result<(), ()> { Ok(()) } - #[allow(dead_code)] fn test_owl_result_2() -> Result { produce_half_owl_error().map_err(|_| ())?; diff --git a/tests/ui/use_self.fixed b/tests/ui/use_self.fixed index ac2a1708b..86ed7ca26 100644 --- a/tests/ui/use_self.fixed +++ b/tests/ui/use_self.fixed @@ -266,7 +266,7 @@ mod nesting { enum Enum { A, B(u64), - C { field: bool } + C { field: bool }, } impl Enum { fn method() { diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index 21b5833e5..cabb9a7f8 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -266,7 +266,7 @@ mod nesting { enum Enum { A, B(u64), - C { field: bool } + C { field: bool }, } impl Enum { fn method() { From b8a50cae4c6ce7eaac4c0844336522477d3416bf Mon Sep 17 00:00:00 2001 From: Zachery Gyurkovitz Date: Wed, 31 Jul 2019 22:24:57 -0700 Subject: [PATCH 092/133] Fix `for on` typo --- clippy_lints/src/types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 31d4c3658..e45688309 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -690,7 +690,7 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for on casts between numerical types that may + /// **What it does:** Checks for casts between numerical types that may /// truncate large values. This is expected behavior, so the cast is `Allow` by /// default. /// @@ -735,7 +735,7 @@ declare_clippy_lint! { } declare_clippy_lint! { - /// **What it does:** Checks for on casts between numerical types that may + /// **What it does:** Checks for casts between numerical types that may /// be replaced by safe conversion functions. /// /// **Why is this bad?** Rust's `as` keyword will perform many kinds of From d7224a6341e9dfed504f85e34d5fff35681ddb2b Mon Sep 17 00:00:00 2001 From: Y0hy0h Date: Thu, 1 Aug 2019 10:51:39 +0200 Subject: [PATCH 093/133] Improve documentation on implicit_hasher lint Provide an example of how to fix the lint. --- clippy_lints/src/types.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 1516428d3..adc37fdcc 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1923,12 +1923,21 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// # use std::collections::HashMap; - /// # use std::hash::Hash; + /// # use std::hash::{Hash, BuildHasher}; /// # trait Serialize {}; /// impl Serialize for HashMap { } /// /// pub fn foo(map: &mut HashMap) { } /// ``` + /// could be rewritten as + /// ```rust + /// # use std::collections::HashMap; + /// # use std::hash::Hash; + /// # trait Serialize {}; + /// impl Serialize for HashMap { } + /// + /// pub fn foo(map: &mut HashMap) { } + /// ``` pub IMPLICIT_HASHER, style, "missing generalization over different hashers" From e6a836e2e801a3c0675b3dd24e0de1c810470813 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 30 Jul 2019 09:50:56 +0200 Subject: [PATCH 094/133] Move UNNECESSARY_UNWRAP to complexity and PANICKING_UNWRAP to correctness --- clippy_lints/src/lib.rs | 6 ++++-- clippy_lints/src/unwrap.rs | 4 ++-- src/lintlist/mod.rs | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 908bbeb5e..1e9e17f59 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -894,6 +894,8 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME, unused_io_amount::UNUSED_IO_AMOUNT, unused_label::UNUSED_LABEL, + unwrap::PANICKING_UNWRAP, + unwrap::UNNECESSARY_UNWRAP, vec::USELESS_VEC, write::PRINTLN_EMPTY_STRING, write::PRINT_LITERAL, @@ -1060,6 +1062,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::UNNECESSARY_CAST, types::VEC_BOX, unused_label::UNUSED_LABEL, + unwrap::UNNECESSARY_UNWRAP, zero_div_zero::ZERO_DIVIDED_BY_ZERO, ]); @@ -1121,6 +1124,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { types::UNIT_CMP, unicode::ZERO_WIDTH_SPACE, unused_io_amount::UNUSED_IO_AMOUNT, + unwrap::PANICKING_UNWRAP, ]); reg.register_lint_group("clippy::perf", Some("clippy_perf"), vec![ @@ -1157,8 +1161,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { needless_borrow::NEEDLESS_BORROW, path_buf_push_overwrite::PATH_BUF_PUSH_OVERWRITE, redundant_clone::REDUNDANT_CLONE, - unwrap::PANICKING_UNWRAP, - unwrap::UNNECESSARY_UNWRAP, ]); } diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 568087b36..830e1fc4d 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -31,7 +31,7 @@ declare_clippy_lint! { /// } /// ``` pub UNNECESSARY_UNWRAP, - nursery, + complexity, "checks for calls of unwrap[_err]() that cannot fail" } @@ -52,7 +52,7 @@ declare_clippy_lint! { /// /// This code will always panic. The if condition should probably be inverted. pub PANICKING_UNWRAP, - nursery, + correctness, "checks for calls of unwrap[_err]() that will always fail" } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 49bce5a6c..aa4576640 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -1381,7 +1381,7 @@ pub const ALL_LINTS: [Lint; 309] = [ }, Lint { name: "panicking_unwrap", - group: "nursery", + group: "correctness", desc: "checks for calls of unwrap[_err]() that will always fail", deprecation: None, module: "unwrap", @@ -1927,7 +1927,7 @@ pub const ALL_LINTS: [Lint; 309] = [ }, Lint { name: "unnecessary_unwrap", - group: "nursery", + group: "complexity", desc: "checks for calls of unwrap[_err]() that cannot fail", deprecation: None, module: "unwrap", From 7a73b8fdfaa6bec11d9326d0a2077f6cf6d238a7 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Tue, 30 Jul 2019 09:51:45 +0200 Subject: [PATCH 095/133] Remove Known problems for UNNECESSARY_UNWRAP This shouldn't happen with NLL --- clippy_lints/src/unwrap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index 830e1fc4d..c2fb62c30 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -14,7 +14,7 @@ declare_clippy_lint! { /// /// **Why is this bad?** Using `if let` or `match` is more idiomatic. /// - /// **Known problems:** Limitations of the borrow checker might make unwrap() necessary sometimes? + /// **Known problems:** None /// /// **Example:** /// ```rust From feca48d8a292c66186fb391c231327b85e116cd9 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Thu, 1 Aug 2019 12:53:20 +0200 Subject: [PATCH 096/133] Fix doc tests --- clippy_lints/src/unwrap.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/clippy_lints/src/unwrap.rs b/clippy_lints/src/unwrap.rs index c2fb62c30..d39c341d0 100644 --- a/clippy_lints/src/unwrap.rs +++ b/clippy_lints/src/unwrap.rs @@ -18,6 +18,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let option = Some(0); + /// # fn do_something_with(_x: usize) {} /// if option.is_some() { /// do_something_with(option.unwrap()) /// } @@ -26,6 +28,8 @@ declare_clippy_lint! { /// Could be written: /// /// ```rust + /// # let option = Some(0); + /// # fn do_something_with(_x: usize) {} /// if let Some(value) = option { /// do_something_with(value) /// } @@ -45,6 +49,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let option = Some(0); + /// # fn do_something_with(_x: usize) {} /// if option.is_none() { /// do_something_with(option.unwrap()) /// } From ccc3257c91f3649126da00644c205759a941623b Mon Sep 17 00:00:00 2001 From: chansuke Date: Thu, 1 Aug 2019 22:20:08 +0900 Subject: [PATCH 097/133] Update `stderr` file --- tests/ui/len_zero.stderr | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/len_zero.stderr b/tests/ui/len_zero.stderr index 9a472b31e..6c71f1bee 100644 --- a/tests/ui/len_zero.stderr +++ b/tests/ui/len_zero.stderr @@ -22,13 +22,13 @@ error: length comparison to zero --> $DIR/len_zero.rs:83:8 | LL | if has_is_empty.len() != 0 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:86:8 | LL | if has_is_empty.len() > 0 { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:89:8 @@ -40,7 +40,7 @@ error: length comparison to one --> $DIR/len_zero.rs:92:8 | LL | if has_is_empty.len() >= 1 { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:103:8 @@ -52,19 +52,19 @@ error: length comparison to zero --> $DIR/len_zero.rs:106:8 | LL | if 0 != has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to zero --> $DIR/len_zero.rs:109:8 | LL | if 0 < has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:112:8 | LL | if 1 <= has_is_empty.len() { - | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!has_is_empty.is_empty()` error: length comparison to one --> $DIR/len_zero.rs:115:8 @@ -82,7 +82,7 @@ error: length comparison to zero --> $DIR/len_zero.rs:142:8 | LL | if b.len() != 0 {} - | ^^^^^^^^^^^^ help: using `is_empty` is clearer and more explicit: `!b.is_empty()` + | ^^^^^^^^^^^^ help: using `!is_empty` is clearer and more explicit: `!b.is_empty()` error: aborting due to 14 previous errors From 5decadd93eb806d34034344363828dce6fc3bd7a Mon Sep 17 00:00:00 2001 From: Y0hy0h Date: Thu, 1 Aug 2019 17:54:22 +0200 Subject: [PATCH 098/133] Fix missing import --- clippy_lints/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index adc37fdcc..6a7e449a2 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1932,7 +1932,7 @@ declare_clippy_lint! { /// could be rewritten as /// ```rust /// # use std::collections::HashMap; - /// # use std::hash::Hash; + /// # use std::hash::{Hash, BuildHasher}; /// # trait Serialize {}; /// impl Serialize for HashMap { } /// From abfa8a952c74a409ee0d3cc80d85d90cc9de70ae Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Fri, 2 Aug 2019 08:13:54 +0200 Subject: [PATCH 099/133] Doctests: Fix all complexity lint docs cc #4319 --- clippy_lints/src/assign_ops.rs | 3 +- clippy_lints/src/double_comparison.rs | 8 +++- clippy_lints/src/double_parens.rs | 7 ++-- clippy_lints/src/duration_subsec.rs | 1 + clippy_lints/src/eval_order_dependence.rs | 4 +- clippy_lints/src/explicit_write.rs | 4 +- clippy_lints/src/format.rs | 5 ++- clippy_lints/src/functions.rs | 3 +- clippy_lints/src/identity_op.rs | 3 +- clippy_lints/src/int_plus_one.rs | 10 +++-- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/loops.rs | 14 ++++--- clippy_lints/src/map_unit_fn.rs | 41 +++++++++++++------ clippy_lints/src/methods/mod.rs | 13 ++++-- clippy_lints/src/misc.rs | 2 +- clippy_lints/src/misc_early.rs | 2 +- clippy_lints/src/needless_bool.rs | 4 +- clippy_lints/src/needless_borrowed_ref.rs | 5 +-- clippy_lints/src/needless_update.rs | 10 ++++- clippy_lints/src/no_effect.rs | 2 +- .../src/overflow_check_conditional.rs | 4 +- clippy_lints/src/partialeq_ne_impl.rs | 2 +- clippy_lints/src/ranges.rs | 7 ++-- clippy_lints/src/reference.rs | 6 +-- clippy_lints/src/swap.rs | 5 +++ clippy_lints/src/trait_bounds.rs | 4 +- clippy_lints/src/transmute.rs | 35 +++++++++++----- clippy_lints/src/types.rs | 9 ++-- clippy_lints/src/utils/author.rs | 5 ++- clippy_lints/src/utils/inspector.rs | 4 +- clippy_lints/src/utils/internal_lints.rs | 10 ++--- clippy_lints/src/zero_div_zero.rs | 2 +- 33 files changed, 155 insertions(+), 83 deletions(-) diff --git a/clippy_lints/src/assign_ops.rs b/clippy_lints/src/assign_ops.rs index 28a5f8246..ec4c8f5fa 100644 --- a/clippy_lints/src/assign_ops.rs +++ b/clippy_lints/src/assign_ops.rs @@ -45,7 +45,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let mut a = 5; - /// ... + /// let b = 2; + /// // ... /// a += a + b; /// ``` pub MISREFACTORED_ASSIGN_OP, diff --git a/clippy_lints/src/double_comparison.rs b/clippy_lints/src/double_comparison.rs index 0c7c81f40..d48bfea73 100644 --- a/clippy_lints/src/double_comparison.rs +++ b/clippy_lints/src/double_comparison.rs @@ -18,13 +18,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x == y || x < y + /// # let x = 1; + /// # let y = 2; + /// if x == y || x < y {} /// ``` /// /// Could be written as: /// /// ```rust - /// x <= y + /// # let x = 1; + /// # let y = 2; + /// if x <= y {} /// ``` pub DOUBLE_COMPARISONS, complexity, diff --git a/clippy_lints/src/double_parens.rs b/clippy_lints/src/double_parens.rs index f39ea6a3c..e55490325 100644 --- a/clippy_lints/src/double_parens.rs +++ b/clippy_lints/src/double_parens.rs @@ -13,9 +13,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// ((0)) - /// foo((0)) - /// ((1, 2)) + /// # fn foo(bar: usize) {} + /// ((0)); + /// foo((0)); + /// ((1, 2)); /// ``` pub DOUBLE_PARENS, complexity, diff --git a/clippy_lints/src/duration_subsec.rs b/clippy_lints/src/duration_subsec.rs index 60470ede5..1346aea3e 100644 --- a/clippy_lints/src/duration_subsec.rs +++ b/clippy_lints/src/duration_subsec.rs @@ -20,6 +20,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::time::Duration; /// let dur = Duration::new(5, 0); /// let _micros = dur.subsec_nanos() / 1_000; /// let _millis = dur.subsec_nanos() / 1_000_000; diff --git a/clippy_lints/src/eval_order_dependence.rs b/clippy_lints/src/eval_order_dependence.rs index 2db3a2bc0..b915d5067 100644 --- a/clippy_lints/src/eval_order_dependence.rs +++ b/clippy_lints/src/eval_order_dependence.rs @@ -42,7 +42,9 @@ declare_clippy_lint! { /// shorthand. /// /// **Example:** - /// ```rust + /// ```rust,no_run + /// # fn b() -> bool { true } + /// # fn c() -> bool { true } /// let a = b() || panic!() || c(); /// // `c()` is dead, `panic!()` is only called if `b()` returns `false` /// let x = (a, b, c, panic!()); diff --git a/clippy_lints/src/explicit_write.rs b/clippy_lints/src/explicit_write.rs index dc76bb0b2..a2edb4855 100644 --- a/clippy_lints/src/explicit_write.rs +++ b/clippy_lints/src/explicit_write.rs @@ -16,8 +16,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::io::Write; + /// # let bar = "furchtbar"; /// // this would be clearer as `eprintln!("foo: {:?}", bar);` - /// writeln!(&mut io::stderr(), "foo: {:?}", bar).unwrap(); + /// writeln!(&mut std::io::stderr(), "foo: {:?}", bar).unwrap(); /// ``` pub EXPLICIT_WRITE, complexity, diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index aed1142d9..751d8fd00 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -26,8 +26,9 @@ declare_clippy_lint! { /// /// **Examples:** /// ```rust - /// format!("foo") - /// format!("{}", foo) + /// # let foo = "foo"; + /// format!("foo"); + /// format!("{}", foo); /// ``` pub USELESS_FORMAT, complexity, diff --git a/clippy_lints/src/functions.rs b/clippy_lints/src/functions.rs index 1a163e682..9772a603b 100644 --- a/clippy_lints/src/functions.rs +++ b/clippy_lints/src/functions.rs @@ -23,8 +23,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # struct Color; /// fn foo(x: u32, y: u32, name: &str, c: Color, w: f32, h: f32, a: f32, b: f32) { - /// .. + /// // .. /// } /// ``` pub TOO_MANY_ARGUMENTS, diff --git a/clippy_lints/src/identity_op.rs b/clippy_lints/src/identity_op.rs index b3ab46781..1cd58a370 100644 --- a/clippy_lints/src/identity_op.rs +++ b/clippy_lints/src/identity_op.rs @@ -17,7 +17,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x / 1 + 0 * 1 - 0 | 0 + /// # let x = 1; + /// x / 1 + 0 * 1 - 0 | 0; /// ``` pub IDENTITY_OP, complexity, diff --git a/clippy_lints/src/int_plus_one.rs b/clippy_lints/src/int_plus_one.rs index b59179618..22ebf562d 100644 --- a/clippy_lints/src/int_plus_one.rs +++ b/clippy_lints/src/int_plus_one.rs @@ -17,13 +17,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x >= y + 1 + /// # let x = 1; + /// # let y = 1; + /// if x >= y + 1 {} /// ``` /// - /// Could be written: + /// Could be written as: /// /// ```rust - /// x > y + /// # let x = 1; + /// # let y = 1; + /// if x > y {} /// ``` pub INT_PLUS_ONE, complexity, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1e9e17f59..d05e815c2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -100,7 +100,7 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, complexity, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Warn, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => { diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 47cced9d9..73d4a3257 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -47,7 +47,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// fn unused_lifetime<'a>(x: u8) { - /// .. + /// // .. /// } /// ``` pub EXTRA_UNUSED_LIFETIMES, diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 02074c79b..3c66c7432 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -217,18 +217,19 @@ declare_clippy_lint! { /// **Known problems:** Sometimes the wrong binding is displayed (#383). /// /// **Example:** - /// ```rust + /// ```rust,no_run + /// # let y = Some(1); /// loop { /// let x = match y { /// Some(x) => x, /// None => break, - /// } + /// }; /// // .. do something with x /// } /// // is easier written as /// while let Some(x) = y { /// // .. do something with x - /// } + /// }; /// ``` pub WHILE_LET_LOOP, complexity, @@ -309,8 +310,11 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```ignore - /// for i in 0..v.len() { foo(v[i]); + /// ```rust + /// # let v = vec![1]; + /// # fn foo(bar: usize) {} + /// # fn bar(bar: usize, baz: usize) {} + /// for i in 0..v.len() { foo(v[i]); } /// for i in 0..v.len() { bar(i, v[i]); } /// ``` pub EXPLICIT_COUNTER_LOOP, diff --git a/clippy_lints/src/map_unit_fn.rs b/clippy_lints/src/map_unit_fn.rs index 2e97f44b3..22093bfbe 100644 --- a/clippy_lints/src/map_unit_fn.rs +++ b/clippy_lints/src/map_unit_fn.rs @@ -20,20 +20,29 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust - /// let x: Option<&str> = do_stuff(); + /// # fn do_stuff() -> Option { Some(String::new()) } + /// # fn log_err_msg(foo: String) -> Option { Some(foo) } + /// # fn format_msg(foo: String) -> String { String::new() } + /// let x: Option = do_stuff(); /// x.map(log_err_msg); - /// x.map(|msg| log_err_msg(format_msg(msg))) + /// # let x: Option = do_stuff(); + /// x.map(|msg| log_err_msg(format_msg(msg))); /// ``` /// /// The correct use would be: /// /// ```rust - /// let x: Option<&str> = do_stuff(); + /// # fn do_stuff() -> Option { Some(String::new()) } + /// # fn log_err_msg(foo: String) -> Option { Some(foo) } + /// # fn format_msg(foo: String) -> String { String::new() } + /// let x: Option = do_stuff(); /// if let Some(msg) = x { - /// log_err_msg(msg) + /// log_err_msg(msg); /// } + /// + /// # let x: Option = do_stuff(); /// if let Some(msg) = x { - /// log_err_msg(format_msg(msg)) + /// log_err_msg(format_msg(msg)); /// } /// ``` pub OPTION_MAP_UNIT_FN, @@ -53,21 +62,29 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust - /// let x: Result<&str, &str> = do_stuff(); + /// # fn do_stuff() -> Result { Ok(String::new()) } + /// # fn log_err_msg(foo: String) -> Result { Ok(foo) } + /// # fn format_msg(foo: String) -> String { String::new() } + /// let x: Result = do_stuff(); /// x.map(log_err_msg); - /// x.map(|msg| log_err_msg(format_msg(msg))) + /// # let x: Result = do_stuff(); + /// x.map(|msg| log_err_msg(format_msg(msg))); /// ``` /// /// The correct use would be: /// /// ```rust - /// let x: Result<&str, &str> = do_stuff(); + /// # fn do_stuff() -> Result { Ok(String::new()) } + /// # fn log_err_msg(foo: String) -> Result { Ok(foo) } + /// # fn format_msg(foo: String) -> String { String::new() } + /// let x: Result = do_stuff(); /// if let Ok(msg) = x { - /// log_err_msg(msg) - /// } + /// log_err_msg(msg); + /// }; + /// # let x: Result = do_stuff(); /// if let Ok(msg) = x { - /// log_err_msg(format_msg(msg)) - /// } + /// log_err_msg(format_msg(msg)); + /// }; /// ``` pub RESULT_MAP_UNIT_FN, complexity, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 02dfb3e32..473f3892f 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -247,7 +247,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// iter.filter(|x| x == 0).next() + /// # let vec = vec![1]; + /// vec.iter().filter(|x| **x == 0).next(); /// ``` pub FILTER_NEXT, complexity, @@ -345,7 +346,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// iter.find(|x| x == 0).is_some() + /// # let vec = vec![1]; + /// vec.iter().find(|x| **x == 0).is_some(); /// ``` pub SEARCH_IS_SOME, complexity, @@ -363,7 +365,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// name.chars().next() == Some('_') + /// let name = "foo"; + /// name.chars().next() == Some('_'); /// ``` pub CHARS_NEXT_CMP, complexity, @@ -434,7 +437,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// 42u64.clone() + /// 42u64.clone(); /// ``` pub CLONE_ON_COPY, complexity, @@ -708,11 +711,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # fn do_stuff(x: &[i32]) {} /// let x: &[i32] = &[1, 2, 3, 4, 5]; /// do_stuff(x.as_ref()); /// ``` /// The correct use would be: /// ```rust + /// # fn do_stuff(x: &[i32]) {} /// let x: &[i32] = &[1, 2, 3, 4, 5]; /// do_stuff(x); /// ``` diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index d89f886a3..6d24aa008 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -184,7 +184,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// f() && g(); // We should write `if f() { g(); }`. /// ``` pub SHORT_CIRCUIT_STATEMENT, diff --git a/clippy_lints/src/misc_early.rs b/clippy_lints/src/misc_early.rs index c9df436da..7d6f29c52 100644 --- a/clippy_lints/src/misc_early.rs +++ b/clippy_lints/src/misc_early.rs @@ -53,7 +53,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// (|| 42)() /// ``` pub REDUNDANT_CLOSURE_CALL, diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 9857e1756..167f00fee 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -24,7 +24,7 @@ declare_clippy_lint! { /// shorter code. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// if x { /// false /// } else { @@ -46,7 +46,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// if x == true {} // could be `if x { }` /// ``` pub BOOL_COMPARISON, diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index b6104f6cc..b6598ac55 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -18,7 +18,7 @@ declare_clippy_lint! { /// /// **Known problems:** It seems that the `&ref` pattern is sometimes useful. /// For instance in the following snippet: - /// ```rust + /// ```rust,ignore /// enum Animal { /// Cat(u64), /// Dog(u64), @@ -26,8 +26,7 @@ declare_clippy_lint! { /// /// fn foo(a: &Animal, b: &Animal) { /// match (a, b) { - /// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime - /// mismatch error + /// (&Animal::Cat(v), k) | (k, &Animal::Cat(v)) => (), // lifetime mismatch error /// (&Animal::Dog(ref c), &Animal::Dog(_)) => () /// } /// } diff --git a/clippy_lints/src/needless_update.rs b/clippy_lints/src/needless_update.rs index 316395acf..fdaa14dfb 100644 --- a/clippy_lints/src/needless_update.rs +++ b/clippy_lints/src/needless_update.rs @@ -15,11 +15,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # struct Point { + /// # x: i32, + /// # y: i32, + /// # z: i32, + /// # } + /// # let zero_point = Point { x: 0, y: 0, z: 0 }; /// Point { /// x: 1, - /// y: 0, + /// y: 1, /// ..zero_point - /// } + /// }; /// ``` pub NEEDLESS_UPDATE, complexity, diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 8c5ddaf41..2fe866a1d 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -34,7 +34,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// compute_array()[0]; /// ``` pub UNNECESSARY_OPERATION, diff --git a/clippy_lints/src/overflow_check_conditional.rs b/clippy_lints/src/overflow_check_conditional.rs index c598e915a..f4c301958 100644 --- a/clippy_lints/src/overflow_check_conditional.rs +++ b/clippy_lints/src/overflow_check_conditional.rs @@ -14,7 +14,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// a + b < a + /// # let a = 1; + /// # let b = 2; + /// a + b < a; /// ``` pub OVERFLOW_CHECK_CONDITIONAL, complexity, diff --git a/clippy_lints/src/partialeq_ne_impl.rs b/clippy_lints/src/partialeq_ne_impl.rs index 1091ed0d6..805efa7cf 100644 --- a/clippy_lints/src/partialeq_ne_impl.rs +++ b/clippy_lints/src/partialeq_ne_impl.rs @@ -19,7 +19,7 @@ declare_clippy_lint! { /// struct Foo; /// /// impl PartialEq for Foo { - /// fn eq(&self, other: &Foo) -> bool { ... } + /// fn eq(&self, other: &Foo) -> bool { true } /// fn ne(&self, other: &Foo) -> bool { !(self == other) } /// } /// ``` diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index af2342634..a0391e336 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -40,7 +40,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x.iter().zip(0..x.len()) + /// # let x = vec![1]; + /// x.iter().zip(0..x.len()); /// ``` pub RANGE_ZIP_WITH_LEN, complexity, @@ -60,7 +61,7 @@ declare_clippy_lint! { /// I.e., `let _ = (f()+1)..(f()+1)` results in `let _ = ((f()+1)..=f())`. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// for x..(y+1) { .. } /// ``` pub RANGE_PLUS_ONE, @@ -78,7 +79,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// for x..=(y-1) { .. } /// ``` pub RANGE_MINUS_ONE, diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index 2ee00a2f1..35e214faa 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// the suggested fix for `x = **&&y` is `x = *&y`, which is still incorrect. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// let a = f(*&mut b); /// let c = *&d; /// ``` @@ -64,8 +64,8 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// struct Point(u32, u32); - /// let point = Foo(30, 20); - /// let x = (&point).x; + /// let point = Point(30, 20); + /// let x = (&point).0; /// ``` pub REF_IN_DEREF, complexity, diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index fc5b2150d..11ab5b876 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -20,12 +20,17 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// let mut a = 42; + /// let mut b = 1337; + /// /// let t = b; /// b = a; /// a = t; /// ``` /// Use std::mem::swap(): /// ```rust + /// let mut a = 1; + /// let mut b = 2; /// std::mem::swap(&mut a, &mut b); /// ``` pub MANUAL_SWAP, diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 8a719c0dd..bf4c5d65d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -15,13 +15,13 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// pub fn foo(t: T) where T: Copy, T: Clone + /// pub fn foo(t: T) where T: Copy, T: Clone {} /// ``` /// /// Could be written as: /// /// ```rust - /// pub fn foo(t: T) where T: Copy + Clone + /// pub fn foo(t: T) where T: Copy + Clone {} /// ``` pub TYPE_REPETITION_IN_BOUNDS, complexity, diff --git a/clippy_lints/src/transmute.rs b/clippy_lints/src/transmute.rs index e2534dae0..a514b9c51 100644 --- a/clippy_lints/src/transmute.rs +++ b/clippy_lints/src/transmute.rs @@ -36,8 +36,8 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust - /// core::intrinsics::transmute(t) // where the result type is the same as `t`'s + /// ```rust,ignore + /// core::intrinsics::transmute(t); // where the result type is the same as `t`'s /// ``` pub USELESS_TRANSMUTE, complexity, @@ -53,7 +53,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// core::intrinsics::transmute(t) // where the result type is the same as /// // `*t` or `&t`'s /// ``` @@ -70,8 +70,10 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust - /// let _: &T = std::mem::transmute(p); // where p: *const T + /// ```rust,ignore + /// unsafe { + /// let _: &T = std::mem::transmute(p); // where p: *const T + /// } /// /// // can be written: /// let _: &T = &*p; @@ -99,7 +101,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let _: char = std::mem::transmute(x); // where x: u32 + /// let x = 1_u32; + /// unsafe { + /// let _: char = std::mem::transmute(x); // where x: u32 + /// } /// /// // should be: /// let _ = std::char::from_u32(x).unwrap(); @@ -127,7 +132,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let _: &str = std::mem::transmute(b); // where b: &[u8] + /// let b: &[u8] = &[1_u8, 2_u8]; + /// unsafe { + /// let _: &str = std::mem::transmute(b); // where b: &[u8] + /// } /// /// // should be: /// let _ = std::str::from_utf8(b).unwrap(); @@ -146,7 +154,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let _: bool = std::mem::transmute(x); // where x: u8 + /// let x = 1_u8; + /// unsafe { + /// let _: bool = std::mem::transmute(x); // where x: u8 + /// } /// /// // should be: /// let _: bool = x != 0; @@ -166,10 +177,12 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let _: f32 = std::mem::transmute(x); // where x: u32 + /// unsafe { + /// let _: f32 = std::mem::transmute(1_u32); // where x: u32 + /// } /// /// // should be: - /// let _: f32 = f32::from_bits(x); + /// let _: f32 = f32::from_bits(1_u32); /// ``` pub TRANSMUTE_INT_TO_FLOAT, complexity, @@ -195,7 +208,7 @@ declare_clippy_lint! { /// let _: &f32 = std::mem::transmute(&1u32); /// } /// // These can be respectively written: - /// let _ = ptr as *const f32 + /// let _ = ptr as *const f32; /// let _ = unsafe{ &*(&1u32 as *const u32 as *const f32) }; /// ``` pub TRANSMUTE_PTR_TO_PTR, diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 549ba56ee..838ec7670 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -557,7 +557,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// foo({ /// let a = bar(); /// baz(a); @@ -775,7 +775,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let _ = 2i32 as i32 + /// let _ = 2i32 as i32; /// ``` pub UNNECESSARY_CAST, complexity, @@ -1295,6 +1295,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::rc::Rc; /// struct Foo { /// inner: Rc>>>, /// } @@ -1458,13 +1459,13 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// 'x' as u8 /// ``` /// /// A better version, using the byte literal: /// - /// ```rust + /// ```rust,ignore /// b'x' /// ``` pub CHAR_LIT_AS_U8, diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index f41933809..811bdce18 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// **What it does:** Generates clippy code that detects the offending pattern /// /// **Example:** - /// ```rust + /// ```rust,ignore /// // ./tests/ui/my_lint.rs /// fn foo() { /// // detect the following pattern @@ -24,13 +24,14 @@ declare_clippy_lint! { /// // but ignore everything from here on /// #![clippy::author = "ignore"] /// } + /// () /// } /// ``` /// /// Running `TESTNAME=ui/my_lint cargo uitest` will produce /// a `./tests/ui/new_lint.stdout` file with the generated code: /// - /// ```rust + /// ```rust,ignore /// // ./tests/ui/new_lint.stdout /// if_chain! { /// if let ExprKind::If(ref cond, ref then, None) = item.node, diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index ea169481a..48dc98c05 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -13,14 +13,14 @@ declare_clippy_lint! { /// attribute /// /// **Example:** - /// ```rust + /// ```rust,ignore /// #[clippy::dump] /// extern crate foo; /// ``` /// /// prints /// - /// ``` + /// ```text /// item `foo` /// visibility inherited from outer item /// extern crate dylib source: "/path/to/foo.so" diff --git a/clippy_lints/src/utils/internal_lints.rs b/clippy_lints/src/utils/internal_lints.rs index 6393bf2ad..0dcac1121 100644 --- a/clippy_lints/src/utils/internal_lints.rs +++ b/clippy_lints/src/utils/internal_lints.rs @@ -38,7 +38,7 @@ declare_clippy_lint! { /// `declare_lint_pass!`, `impl_lint_pass!`, and `lint_array!` macros. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// declare_lint! { pub LINT_1, ... } /// declare_lint! { pub LINT_2, ... } /// declare_lint! { pub FORGOTTEN_LINT, ... } @@ -62,12 +62,12 @@ declare_clippy_lint! { /// /// **Example:** /// Bad: - /// ```rust + /// ```rust,ignore /// cx.span_lint(LINT_NAME, "message"); /// ``` /// /// Good: - /// ```rust + /// ```rust,ignore /// utils::span_lint(cx, LINT_NAME, "message"); /// ``` pub COMPILER_LINT_FUNCTIONS, @@ -85,12 +85,12 @@ declare_clippy_lint! { /// /// **Example:** /// Bad: - /// ```rust + /// ```rust,ignore /// expr.span.ctxt().outer().expn_info() /// ``` /// /// Good: - /// ```rust + /// ```rust,ignore /// expr.span.ctxt().outer_expn_info() /// ``` pub OUTER_EXPN_EXPN_INFO, diff --git a/clippy_lints/src/zero_div_zero.rs b/clippy_lints/src/zero_div_zero.rs index 094cb627d..1c4c54f26 100644 --- a/clippy_lints/src/zero_div_zero.rs +++ b/clippy_lints/src/zero_div_zero.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// 0.0f32 / 0.0 + /// 0.0f32 / 0.0; /// ``` pub ZERO_DIVIDED_BY_ZERO, complexity, From c0cdfd296e1ef2ef8a9076856d0b1b80f08c654d Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 08:01:27 +0200 Subject: [PATCH 100/133] Doctests: Enable running doc tests for perf lints This should be possible to merge independently of #4325 cc #4319 --- clippy_lints/src/bytecount.rs | 3 ++- clippy_lints/src/entry.rs | 25 +++++++++++++------ clippy_lints/src/escape.rs | 9 +++---- clippy_lints/src/lib.rs | 4 +-- clippy_lints/src/loops.rs | 9 ++++--- clippy_lints/src/methods/mod.rs | 24 +++++++++++++----- clippy_lints/src/misc.rs | 4 ++- clippy_lints/src/mutex_atomic.rs | 2 ++ .../src/slow_vector_initialization.rs | 2 ++ .../src/trivially_copy_pass_by_ref.rs | 15 +++++------ 10 files changed, 65 insertions(+), 32 deletions(-) diff --git a/clippy_lints/src/bytecount.rs b/clippy_lints/src/bytecount.rs index 984858382..ab9cf9512 100644 --- a/clippy_lints/src/bytecount.rs +++ b/clippy_lints/src/bytecount.rs @@ -24,7 +24,8 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust - /// &my_data.filter(|&x| x == 0u8).count() // use bytecount::count instead + /// # let vec = vec![1_u8]; + /// &vec.iter().filter(|x| **x == 0u8).count(); // use bytecount::count instead /// ``` pub NAIVE_BYTECOUNT, perf, diff --git a/clippy_lints/src/entry.rs b/clippy_lints/src/entry.rs index 83f78b2d7..e6b09f89b 100644 --- a/clippy_lints/src/entry.rs +++ b/clippy_lints/src/entry.rs @@ -16,21 +16,32 @@ declare_clippy_lint! { /// /// **Known problems:** Some false negatives, eg.: /// ```rust - /// let k = &key; - /// if !m.contains_key(k) { - /// m.insert(k.clone(), v); + /// # use std::collections::HashMap; + /// # let mut map = HashMap::new(); + /// # let v = 1; + /// # let k = 1; + /// if !map.contains_key(&k) { + /// map.insert(k.clone(), v); /// } /// ``` /// /// **Example:** /// ```rust - /// if !m.contains_key(&k) { - /// m.insert(k, v) + /// # use std::collections::HashMap; + /// # let mut map = HashMap::new(); + /// # let k = 1; + /// # let v = 1; + /// if !map.contains_key(&k) { + /// map.insert(k, v); /// } /// ``` - /// can be rewritten as: + /// can both be rewritten as: /// ```rust - /// m.entry(k).or_insert(v); + /// # use std::collections::HashMap; + /// # let mut map = HashMap::new(); + /// # let k = 1; + /// # let v = 1; + /// map.entry(k).or_insert(v); /// ``` pub MAP_ENTRY, perf, diff --git a/clippy_lints/src/escape.rs b/clippy_lints/src/escape.rs index f276014f4..c37efbd6e 100644 --- a/clippy_lints/src/escape.rs +++ b/clippy_lints/src/escape.rs @@ -28,11 +28,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// fn main() { - /// let x = Box::new(1); - /// foo(*x); - /// println!("{}", *x); - /// } + /// # fn foo(bar: usize) {} + /// let x = Box::new(1); + /// foo(*x); + /// println!("{}", *x); /// ``` pub BOXED_LOCAL, perf, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 1e9e17f59..8a29e187e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -105,7 +105,7 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, perf, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Warn, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => { @@ -120,7 +120,7 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Allow, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 02074c79b..940da9b3f 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -41,7 +41,9 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```ignore + /// ```rust + /// # let src = vec![1]; + /// # let mut dst = vec![0; 65]; /// for i in 0..src.len() { /// dst[i + 64] = src[i]; /// } @@ -264,8 +266,9 @@ declare_clippy_lint! { /// None /// /// **Example:** - /// ```ignore - /// let len = iterator.collect::>().len(); + /// ```rust + /// # let iterator = vec![1].into_iter(); + /// let len = iterator.clone().collect::>().len(); /// // should be /// let len = iterator.count(); /// ``` diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 02dfb3e32..8ae08f584 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -383,15 +383,18 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// foo.unwrap_or(String::new()) + /// # let foo = Some(String::new()); + /// foo.unwrap_or(String::new()); /// ``` /// this can instead be written: /// ```rust - /// foo.unwrap_or_else(String::new) + /// # let foo = Some(String::new()); + /// foo.unwrap_or_else(String::new); /// ``` /// or /// ```rust - /// foo.unwrap_or_default() + /// # let foo = Some(String::new()); + /// foo.unwrap_or_default(); /// ``` pub OR_FUN_CALL, perf, @@ -409,15 +412,24 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// foo.expect(&format!("Err {}: {}", err_code, err_msg)) + /// # let foo = Some(String::new()); + /// # let err_code = "418"; + /// # let err_msg = "I'm a teapot"; + /// foo.expect(&format!("Err {}: {}", err_code, err_msg)); /// ``` /// or /// ```rust - /// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str()) + /// # let foo = Some(String::new()); + /// # let err_code = "418"; + /// # let err_msg = "I'm a teapot"; + /// foo.expect(format!("Err {}: {}", err_code, err_msg).as_str()); /// ``` /// this can instead be written: /// ```rust - /// foo.unwrap_or_else(|_| panic!("Err {}: {}", err_code, err_msg)) + /// # let foo = Some(String::new()); + /// # let err_code = "418"; + /// # let err_msg = "I'm a teapot"; + /// foo.unwrap_or_else(|| panic!("Err {}: {}", err_code, err_msg)); /// ``` pub EXPECT_FUN_CALL, perf, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index d89f886a3..ae339021a 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -101,7 +101,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x.to_owned() == y + /// # let x = "foo"; + /// # let y = String::from("foo"); + /// if x.to_owned() == y {} /// ``` pub CMP_OWNED, perf, diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 3b9641b35..bf76e0ff3 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -22,6 +22,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::sync::Mutex; + /// # let y = 1; /// let x = Mutex::new(&y); /// ``` pub MUTEX_ATOMIC, diff --git a/clippy_lints/src/slow_vector_initialization.rs b/clippy_lints/src/slow_vector_initialization.rs index dde9412c5..7e543bfe6 100644 --- a/clippy_lints/src/slow_vector_initialization.rs +++ b/clippy_lints/src/slow_vector_initialization.rs @@ -19,6 +19,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use core::iter::repeat; + /// # let len = 4; /// let mut vec1 = Vec::with_capacity(len); /// vec1.resize(len, 0); /// diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs index 4e07a07cc..be79fc2fb 100644 --- a/clippy_lints/src/trivially_copy_pass_by_ref.rs +++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs @@ -39,14 +39,15 @@ declare_clippy_lint! { /// each other. /// /// **Example:** + /// /// ```rust - /// fn foo(v: &u32) { - /// assert_eq!(v, 42); - /// } - /// // should be - /// fn foo(v: u32) { - /// assert_eq!(v, 42); - /// } + /// // Bad + /// fn foo(v: &u32) {} + /// ``` + /// + /// ```rust + /// // Better + /// fn foo(v: u32) {} /// ``` pub TRIVIALLY_COPY_PASS_BY_REF, perf, From eb68dc9a1a1264b561e891b74c8939d3d67ed9c0 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 08:12:53 +0200 Subject: [PATCH 101/133] Also enable doc tests for internal lints Because there were fixed in the parent commit. --- clippy_lints/src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index d05e815c2..39e55a955 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -130,12 +130,12 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Allow, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, internal_warn, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Warn, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Warn, $description, report_in_external_macro: true } }; } From d61df4f60976f98d9ab41746c5b56fe8177bfcf4 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 08:44:32 +0200 Subject: [PATCH 102/133] Rustup to latest rustc master Broken due to: * https://github.com/rust-lang/rust/pull/63180 (`Existential` -> `OpaqueTy`) * https://github.com/rust-lang/rust/pull/63121 (New fields for `FormatSpec`) --- clippy_lints/src/lifetimes.rs | 2 +- clippy_lints/src/missing_doc.rs | 4 ++-- clippy_lints/src/missing_inline.rs | 4 ++-- clippy_lints/src/utils/inspector.rs | 4 ++-- clippy_lints/src/write.rs | 2 ++ 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index 47cced9d9..07fbc78f3 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -348,7 +348,7 @@ impl<'a, 'tcx> Visitor<'tcx> for RefVisitor<'a, 'tcx> { }, TyKind::Def(item, _) => { let map = self.cx.tcx.hir(); - if let ItemKind::Existential(ref exist_ty) = map.expect_item(item.id).node { + if let ItemKind::OpaqueTy(ref exist_ty) = map.expect_item(item.id).node { for bound in &exist_ty.bounds { if let GenericBound::Outlives(_) = *bound { self.record(&None); diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 195e78795..00f1cf9a5 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -148,7 +148,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::TraitAlias(..) => "a trait alias", hir::ItemKind::Ty(..) => "a type alias", hir::ItemKind::Union(..) => "a union", - hir::ItemKind::Existential(..) => "an existential type", + hir::ItemKind::OpaqueTy(..) => "an existential type", hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod(..) | hir::ItemKind::GlobalAsm(..) @@ -185,7 +185,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ImplItemKind::Const(..) => "an associated constant", hir::ImplItemKind::Method(..) => "a method", hir::ImplItemKind::Type(_) => "an associated type", - hir::ImplItemKind::Existential(_) => "an existential type", + hir::ImplItemKind::OpaqueTy(_) => "an existential type", }; self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc); } diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 3efbfbb70..c467f2fc3 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { | hir::ItemKind::GlobalAsm(..) | hir::ItemKind::Ty(..) | hir::ItemKind::Union(..) - | hir::ItemKind::Existential(..) + | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::ExternCrate(..) | hir::ItemKind::ForeignMod(..) | hir::ItemKind::Impl(..) @@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { let desc = match impl_item.node { hir::ImplItemKind::Method(..) => "a method", - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::Existential(_) => return, + hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::OpaqueTy(_) => return, }; let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index ea169481a..7f7466a1a 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -64,7 +64,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { }, hir::ImplItemKind::Method(..) => println!("method"), hir::ImplItemKind::Type(_) => println!("associated type"), - hir::ImplItemKind::Existential(_) => println!("existential type"), + hir::ImplItemKind::OpaqueTy(_) => println!("existential type"), } } // fn check_trait_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx @@ -363,7 +363,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { hir::ItemKind::Ty(..) => { println!("type alias for {:?}", cx.tcx.type_of(did)); }, - hir::ItemKind::Existential(..) => { + hir::ItemKind::OpaqueTy(..) => { println!("existential type with real type {:?}", cx.tcx.type_of(did)); }, hir::ItemKind::Enum(..) => { diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 869e532ee..9b30708b2 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -364,7 +364,9 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O align: AlignUnknown, flags: 0, precision: CountImplied, + precision_span: None, width: CountImplied, + width_span: None, ty: "", }; if !parser.eat(&token::Comma) { From ff59f4ad217af98421228dc6017ade6dab133648 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 12:30:51 +0200 Subject: [PATCH 103/133] Ignore missing rustfmt --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 092a5c80a..eabb5ac5b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,7 +22,7 @@ install: - del rust-toolchain - cargo install rustup-toolchain-install-master --debug || echo "rustup-toolchain-install-master already installed" - rustup-toolchain-install-master %RUSTC_HASH% -f -n master - - rustup component add rustfmt --toolchain nightly || echo "rustfmt nightly is unavailable" + - rustup component add rustfmt --toolchain nightly & exit 0 # Format test handles missing rustfmt - rustup default master - set PATH=%PATH%;C:\Users\appveyor\.rustup\toolchains\master\bin - rustc -V From 1dc9a5012e1ace8024a6b6920e0af3a376a644fe Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 18:42:05 +0200 Subject: [PATCH 104/133] Doctests: Enable running doc tests for pedantic lints --- clippy_lints/src/checked_conversions.rs | 2 ++ clippy_lints/src/copy_iterator.rs | 2 +- clippy_lints/src/derive.rs | 4 ++-- clippy_lints/src/doc.rs | 2 +- clippy_lints/src/if_not_else.rs | 6 ++++++ clippy_lints/src/infinite_iter.rs | 3 ++- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/loops.rs | 18 +++++++++++------- clippy_lints/src/matches.rs | 10 ++++++++-- clippy_lints/src/methods/mod.rs | 19 +++++++++++++------ clippy_lints/src/mut_mut.rs | 1 + clippy_lints/src/needless_continue.rs | 10 ++++++++++ clippy_lints/src/needless_pass_by_value.rs | 3 +++ clippy_lints/src/replace_consts.rs | 2 ++ clippy_lints/src/shadow.rs | 2 ++ clippy_lints/src/types.rs | 14 ++++++++------ 16 files changed, 73 insertions(+), 27 deletions(-) diff --git a/clippy_lints/src/checked_conversions.rs b/clippy_lints/src/checked_conversions.rs index c23f2fbc0..10ba0b9bf 100644 --- a/clippy_lints/src/checked_conversions.rs +++ b/clippy_lints/src/checked_conversions.rs @@ -27,6 +27,8 @@ declare_clippy_lint! { /// Could be written: /// /// ```rust + /// # use std::convert::TryFrom; + /// # let foo = 1; /// # let _ = /// i32::try_from(foo).is_ok() /// # ; diff --git a/clippy_lints/src/copy_iterator.rs b/clippy_lints/src/copy_iterator.rs index cacf4563f..3c2a328b9 100644 --- a/clippy_lints/src/copy_iterator.rs +++ b/clippy_lints/src/copy_iterator.rs @@ -13,7 +13,7 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** - /// ```rust + /// ```rust,ignore /// #[derive(Copy, Clone)] /// struct Countdown(u8); /// diff --git a/clippy_lints/src/derive.rs b/clippy_lints/src/derive.rs index 809dd0ee3..d50a47f8f 100644 --- a/clippy_lints/src/derive.rs +++ b/clippy_lints/src/derive.rs @@ -49,12 +49,12 @@ declare_clippy_lint! { /// **Known problems:** Bounds of generic types are sometimes wrong: https://github.com/rust-lang/rust/issues/26925 /// /// **Example:** - /// ```rust + /// ```rust,ignore /// #[derive(Copy)] /// struct Foo; /// /// impl Clone for Foo { - /// .. + /// // .. /// } /// ``` pub EXPL_IMPL_CLONE_ON_COPY, diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 2b1f6afb3..4950212a4 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -27,7 +27,7 @@ declare_clippy_lint! { /// /// Do something with the foo_bar parameter. See also /// /// that::other::module::foo. /// // ^ `foo_bar` and `that::other::module::foo` should be ticked. - /// fn doit(foo_bar) { .. } + /// fn doit(foo_bar: usize) {} /// ``` pub DOC_MARKDOWN, pedantic, diff --git a/clippy_lints/src/if_not_else.rs b/clippy_lints/src/if_not_else.rs index 385ba9f16..af9647dc0 100644 --- a/clippy_lints/src/if_not_else.rs +++ b/clippy_lints/src/if_not_else.rs @@ -17,6 +17,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let v: Vec = vec![]; + /// # fn a() {} + /// # fn b() {} /// if !v.is_empty() { /// a() /// } else { @@ -27,6 +30,9 @@ declare_clippy_lint! { /// Could be written: /// /// ```rust + /// # let v: Vec = vec![]; + /// # fn a() {} + /// # fn b() {} /// if v.is_empty() { /// b() /// } else { diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 92768d14f..48767aa27 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -34,7 +34,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// [0..].iter().zip(infinite_iter.take_while(|x| x > 5)) + /// let infinite_iter = 0..; + /// [0..].iter().zip(infinite_iter.take_while(|x| *x > 5)); /// ``` pub MAYBE_INFINITE_ITER, pedantic, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 86a32a69e..31b18ec9b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -110,7 +110,7 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, pedantic, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Allow, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => { diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index e1a949c04..7a5ac47b6 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -91,16 +91,18 @@ declare_clippy_lint! { /// types. /// /// **Example:** - /// ```ignore + /// ```rust /// // with `y` a `Vec` or slice: + /// # let y = vec![1]; /// for x in y.iter() { - /// .. + /// // .. /// } /// ``` /// can be rewritten to /// ```rust + /// # let y = vec![1]; /// for x in &y { - /// .. + /// // .. /// } /// ``` pub EXPLICIT_ITER_LOOP, @@ -117,16 +119,18 @@ declare_clippy_lint! { /// **Known problems:** None /// /// **Example:** - /// ```ignore + /// ```rust + /// # let y = vec![1]; /// // with `y` a `Vec` or slice: /// for x in y.into_iter() { - /// .. + /// // .. /// } /// ``` /// can be rewritten to - /// ```ignore + /// ```rust + /// # let y = vec![1]; /// for x in y { - /// .. + /// // .. /// } /// ``` pub EXPLICIT_INTO_ITER_LOOP, diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 566082c9b..6558a2548 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -53,19 +53,25 @@ declare_clippy_lint! { /// Using `match`: /// /// ```rust + /// # fn bar(foo: &usize) {} + /// # let other_ref: usize = 1; + /// # let x: Option<&usize> = Some(&1); /// match x { /// Some(ref foo) => bar(foo), - /// _ => bar(other_ref), + /// _ => bar(&other_ref), /// } /// ``` /// /// Using `if let` with `else`: /// /// ```rust + /// # fn bar(foo: &usize) {} + /// # let other_ref: usize = 1; + /// # let x: Option<&usize> = Some(&1); /// if let Some(ref foo) = x { /// bar(foo); /// } else { - /// bar(other_ref); + /// bar(&other_ref); /// } /// ``` pub SINGLE_MATCH_ELSE, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2a52ad58d..bfdd3e085 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -179,7 +179,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x.map(|a| a + 1).unwrap_or(0) + /// # let x = Some(1); + /// x.map(|a| a + 1).unwrap_or(0); /// ``` pub OPTION_MAP_UNWRAP_OR, pedantic, @@ -196,7 +197,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x.map(|a| a + 1).unwrap_or_else(some_function) + /// # let x = Some(1); + /// # fn some_function() -> usize { 1 } + /// x.map(|a| a + 1).unwrap_or_else(some_function); /// ``` pub OPTION_MAP_UNWRAP_OR_ELSE, pedantic, @@ -213,7 +216,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x.map(|a| a + 1).unwrap_or_else(some_function) + /// # let x: Result = Ok(1); + /// # fn some_function(foo: ()) -> usize { 1 } + /// x.map(|a| a + 1).unwrap_or_else(some_function); /// ``` pub RESULT_MAP_UNWRAP_OR_ELSE, pedantic, @@ -265,7 +270,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// iter.map(|x| x.iter()).flatten() + /// let vec = vec![vec![1]]; + /// vec.iter().map(|x| x.iter()).flatten(); /// ``` pub MAP_FLATTEN, pedantic, @@ -284,7 +290,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// iter.filter(|x| x == 0).map(|x| x * 2) + /// let vec = vec![1]; + /// vec.iter().filter(|x| **x == 0).map(|x| *x * 2); /// ``` pub FILTER_MAP, pedantic, @@ -324,7 +331,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// (0..3).find(|x| x == 2).map(|x| x * 2); + /// (0..3).find(|x| *x == 2).map(|x| x * 2); /// ``` /// Can be written as /// ```rust diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 858ad50e1..decc684b6 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -16,6 +16,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let mut y = 1; /// let x = &mut &mut y; /// ``` pub MUT_MUT, diff --git a/clippy_lints/src/needless_continue.rs b/clippy_lints/src/needless_continue.rs index 97175f869..a5c0652b2 100644 --- a/clippy_lints/src/needless_continue.rs +++ b/clippy_lints/src/needless_continue.rs @@ -57,6 +57,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # fn condition() -> bool { false } + /// # fn update_condition() {} + /// # let x = false; /// while condition() { /// update_condition(); /// if x { @@ -71,6 +74,9 @@ declare_clippy_lint! { /// Could be rewritten as /// /// ```rust + /// # fn condition() -> bool { false } + /// # fn update_condition() {} + /// # let x = false; /// while condition() { /// update_condition(); /// if x { @@ -83,22 +89,26 @@ declare_clippy_lint! { /// As another example, the following code /// /// ```rust + /// # fn waiting() -> bool { false } /// loop { /// if waiting() { /// continue; /// } else { /// // Do something useful /// } + /// # break; /// } /// ``` /// Could be rewritten as /// /// ```rust + /// # fn waiting() -> bool { false } /// loop { /// if waiting() { /// continue; /// } /// // Do something useful + /// # break; /// } /// ``` pub NEEDLESS_CONTINUE, diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index c5283a432..eaca9c42a 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -40,6 +40,9 @@ declare_clippy_lint! { /// fn foo(v: Vec) { /// assert_eq!(v.len(), 42); /// } + /// ``` + /// + /// ```rust /// // should be /// fn foo(v: &[i32]) { /// assert_eq!(v.len(), 42); diff --git a/clippy_lints/src/replace_consts.rs b/clippy_lints/src/replace_consts.rs index cb7be85ab..0dbc7f055 100644 --- a/clippy_lints/src/replace_consts.rs +++ b/clippy_lints/src/replace_consts.rs @@ -16,12 +16,14 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use core::sync::atomic::{ATOMIC_ISIZE_INIT, AtomicIsize}; /// static FOO: AtomicIsize = ATOMIC_ISIZE_INIT; /// ``` /// /// Could be written: /// /// ```rust + /// # use core::sync::atomic::AtomicIsize; /// static FOO: AtomicIsize = AtomicIsize::new(0); /// ``` pub REPLACE_CONSTS, diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index c75e33e84..45d6a7f71 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -67,6 +67,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let y = 1; + /// # let z = 2; /// let x = y; /// let x = z; // shadows the earlier binding /// ``` diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3c8ca3fea..4c87f4e92 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -133,7 +133,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let x = LinkedList::new(); + /// # use std::collections::LinkedList; + /// let x: LinkedList = LinkedList::new(); /// ``` pub LINKEDLIST, pedantic, @@ -660,8 +661,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let x = u64::MAX; - /// x as f64 + /// let x = std::u64::MAX; + /// x as f64; /// ``` pub CAST_PRECISION_LOSS, pedantic, @@ -682,7 +683,7 @@ declare_clippy_lint! { /// **Example:** /// ```rust /// let y: i8 = -1; - /// y as u128 // will return 18446744073709551615 + /// y as u128; // will return 18446744073709551615 /// ``` pub CAST_SIGN_LOSS, pedantic, @@ -727,7 +728,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// u32::MAX as i32 // will yield a value of `-1` + /// std::u32::MAX as i32; // will yield a value of `-1` /// ``` pub CAST_POSSIBLE_WRAP, pedantic, @@ -1689,7 +1690,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// let x : u8 = ...; (x as u32) > 300 + /// let x: u8 = 1; + /// (x as u32) > 300; /// ``` pub INVALID_UPCAST_COMPARISONS, pedantic, From 2f48effc926a84a823db9264f36890cc2da8ba49 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 21:01:23 +0200 Subject: [PATCH 105/133] Doctests: Enable running doc tests for nursery lints --- clippy_lints/src/attrs.rs | 14 +++++++------- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/missing_const_for_fn.rs | 10 ++++++++++ clippy_lints/src/mutex_atomic.rs | 1 + clippy_lints/src/redundant_clone.rs | 12 ++++++++++-- 5 files changed, 29 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/attrs.rs b/clippy_lints/src/attrs.rs index cdb53dbc3..64c8a715d 100644 --- a/clippy_lints/src/attrs.rs +++ b/clippy_lints/src/attrs.rs @@ -113,19 +113,19 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// // Bad - /// #[inline(always)] - /// - /// fn not_quite_good_code(..) { ... } - /// /// // Good (as inner attribute) /// #![inline(always)] /// - /// fn this_is_fine(..) { ... } + /// fn this_is_fine() { } + /// + /// // Bad + /// #[inline(always)] + /// + /// fn not_quite_good_code() { } /// /// // Good (as outer attribute) /// #[inline(always)] - /// fn this_is_fine_too(..) { ... } + /// fn this_is_fine_too() { } /// ``` pub EMPTY_LINE_AFTER_OUTER_ATTR, nursery, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 86a32a69e..7e21268b1 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -125,7 +125,7 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, nursery, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Allow, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, internal, $description:tt } => { diff --git a/clippy_lints/src/missing_const_for_fn.rs b/clippy_lints/src/missing_const_for_fn.rs index 3eb582747..89398f82c 100644 --- a/clippy_lints/src/missing_const_for_fn.rs +++ b/clippy_lints/src/missing_const_for_fn.rs @@ -40,17 +40,27 @@ declare_clippy_lint! { /// **Example:** /// /// ```rust + /// # struct Foo { + /// # random_number: usize, + /// # } + /// # impl Foo { /// fn new() -> Self { /// Self { random_number: 42 } /// } + /// # } /// ``` /// /// Could be a const fn: /// /// ```rust + /// # struct Foo { + /// # random_number: usize, + /// # } + /// # impl Foo { /// const fn new() -> Self { /// Self { random_number: 42 } /// } + /// # } /// ``` pub MISSING_CONST_FOR_FN, nursery, diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index bf76e0ff3..522c4ab52 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -44,6 +44,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::sync::Mutex; /// let x = Mutex::new(0usize); /// ``` pub MUTEX_INTEGER, diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index e85538615..76f3f8fd8 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -40,6 +40,7 @@ declare_clippy_lint! { /// * False-positive if there is a borrow preventing the value from moving out. /// /// ```rust + /// # fn foo(x: String) {} /// let x = String::new(); /// /// let y = &x; @@ -49,15 +50,22 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::path::Path; + /// # #[derive(Clone)] + /// # struct Foo; + /// # impl Foo { + /// # fn new() -> Self { Foo {} } + /// # } + /// # fn call(x: Foo) {} /// { /// let x = Foo::new(); /// call(x.clone()); /// call(x.clone()); // this can just pass `x` /// } /// - /// ["lorem", "ipsum"].join(" ").to_string() + /// ["lorem", "ipsum"].join(" ").to_string(); /// - /// Path::new("/a/b").join("c").to_path_buf() + /// Path::new("/a/b").join("c").to_path_buf(); /// ``` pub REDUNDANT_CLONE, nursery, From b608e02e1cedb99ee8a069e3647dde5316b41968 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sat, 3 Aug 2019 21:24:50 +0200 Subject: [PATCH 106/133] Doctests: Enable running doc tests for restriction lints --- clippy_lints/src/arithmetic.rs | 6 ++-- clippy_lints/src/else_if_without_else.rs | 6 ++++ clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/lib.rs | 2 +- clippy_lints/src/matches.rs | 2 ++ clippy_lints/src/mem_forget.rs | 2 ++ clippy_lints/src/methods/mod.rs | 36 ++++++++++++++++++++---- clippy_lints/src/misc.rs | 5 ++-- clippy_lints/src/missing_inline.rs | 6 ++-- clippy_lints/src/shadow.rs | 3 ++ clippy_lints/src/strings.rs | 2 +- clippy_lints/src/write.rs | 1 + 12 files changed, 57 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/arithmetic.rs b/clippy_lints/src/arithmetic.rs index d94cd668b..9e0d11456 100644 --- a/clippy_lints/src/arithmetic.rs +++ b/clippy_lints/src/arithmetic.rs @@ -16,7 +16,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// a + 1 + /// # let a = 0; + /// a + 1; /// ``` pub INTEGER_ARITHMETIC, restriction, @@ -33,7 +34,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// a + 1.0 + /// # let a = 0.0; + /// a + 1.0; /// ``` pub FLOAT_ARITHMETIC, restriction, diff --git a/clippy_lints/src/else_if_without_else.rs b/clippy_lints/src/else_if_without_else.rs index 25a1cde6e..6daf204a5 100644 --- a/clippy_lints/src/else_if_without_else.rs +++ b/clippy_lints/src/else_if_without_else.rs @@ -16,6 +16,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # fn a() {} + /// # fn b() {} + /// # let x: i32 = 1; /// if x.is_positive() { /// a(); /// } else if x.is_negative() { @@ -26,6 +29,9 @@ declare_clippy_lint! { /// Could be written: /// /// ```rust + /// # fn a() {} + /// # fn b() {} + /// # let x: i32 = 1; /// if x.is_positive() { /// a(); /// } else if x.is_negative() { diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index d90efd2ea..06e5458c1 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -47,7 +47,7 @@ declare_clippy_lint! { /// **Known problems:** Hopefully none. /// /// **Example:** - /// ```rust + /// ```rust,no_run /// // Vector /// let x = vec![0; 5]; /// diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 86a32a69e..ac983b5a2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -115,7 +115,7 @@ macro_rules! declare_clippy_lint { }; { $(#[$attr:meta])* pub $name:tt, restriction, $description:tt } => { declare_tool_lint! { - pub clippy::$name, Allow, $description, report_in_external_macro: true + $(#[$attr])* pub clippy::$name, Allow, $description, report_in_external_macro: true } }; { $(#[$attr:meta])* pub $name:tt, cargo, $description:tt } => { diff --git a/clippy_lints/src/matches.rs b/clippy_lints/src/matches.rs index 566082c9b..b0a4d2691 100644 --- a/clippy_lints/src/matches.rs +++ b/clippy_lints/src/matches.rs @@ -205,6 +205,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # enum Foo { A(usize), B(usize) } + /// # let x = Foo::B(1); /// match x { /// A => {}, /// _ => {}, diff --git a/clippy_lints/src/mem_forget.rs b/clippy_lints/src/mem_forget.rs index 55673c430..54b0a6193 100644 --- a/clippy_lints/src/mem_forget.rs +++ b/clippy_lints/src/mem_forget.rs @@ -14,6 +14,8 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # use std::mem; + /// # use std::rc::Rc; /// mem::forget(Rc::new(55)) /// ``` pub MEM_FORGET, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 2a52ad58d..476bf3b56 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -40,8 +40,19 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** + /// + /// Using unwrap on an `Option`: + /// /// ```rust - /// x.unwrap() + /// let opt = Some(1); + /// opt.unwrap(); + /// ``` + /// + /// Better: + /// + /// ```rust + /// let opt = Some(1); + /// opt.expect("more helpful message"); /// ``` pub OPTION_UNWRAP_USED, restriction, @@ -62,8 +73,18 @@ declare_clippy_lint! { /// **Known problems:** None. /// /// **Example:** + /// Using unwrap on an `Option`: + /// /// ```rust - /// x.unwrap() + /// let res: Result = Ok(1); + /// res.unwrap(); + /// ``` + /// + /// Better: + /// + /// ```rust + /// let res: Result = Ok(1); + /// res.expect("more helpful message"); /// ``` pub RESULT_UNWRAP_USED, restriction, @@ -141,9 +162,10 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// impl X { - /// pub fn as_str(self) -> &str { - /// .. + /// # struct X; + /// impl<'a> X { + /// pub fn as_str(self) -> &'a str { + /// "foo" /// } /// } /// ``` @@ -467,7 +489,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// x.clone() + /// # use std::rc::Rc; + /// let x = Rc::new(1); + /// x.clone(); /// ``` pub CLONE_ON_REF_PTR, restriction, diff --git a/clippy_lints/src/misc.rs b/clippy_lints/src/misc.rs index dec3cd0fb..f8a249829 100644 --- a/clippy_lints/src/misc.rs +++ b/clippy_lints/src/misc.rs @@ -226,8 +226,9 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust - /// const ONE = 1.00f64; - /// x == ONE // where both are floats + /// let x: f64 = 1.0; + /// const ONE: f64 = 1.00; + /// x == ONE; // where both are floats /// ``` pub FLOAT_CMP_CONST, restriction, diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index c467f2fc3..115bde344 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -33,7 +33,7 @@ declare_clippy_lint! { /// /// struct Baz; /// impl Baz { - /// fn priv() {} // ok + /// fn private() {} // ok /// } /// /// impl Bar for Baz { @@ -42,8 +42,8 @@ declare_clippy_lint! { /// /// pub struct PubBaz; /// impl PubBaz { - /// fn priv() {} // ok - /// pub not_ptriv() {} // missing #[inline] + /// fn private() {} // ok + /// pub fn not_ptrivate() {} // missing #[inline] /// } /// /// impl Bar for PubBaz { diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs index c75e33e84..b5413b388 100644 --- a/clippy_lints/src/shadow.rs +++ b/clippy_lints/src/shadow.rs @@ -20,6 +20,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let x = 1; /// let x = &x; /// ``` pub SHADOW_SAME, @@ -41,10 +42,12 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// let x = 2; /// let x = x + 1; /// ``` /// use different variable name: /// ```rust + /// let x = 2; /// let y = x + 1; /// ``` pub SHADOW_REUSE, diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index 57f63a600..0de63b5ff 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -48,7 +48,7 @@ declare_clippy_lint! { /// /// ```rust /// let x = "Hello".to_owned(); - /// x + ", World" + /// x + ", World"; /// ``` pub STRING_ADD, restriction, diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index 9b30708b2..9e26b3e5b 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -77,6 +77,7 @@ declare_clippy_lint! { /// /// **Example:** /// ```rust + /// # let foo = "bar"; /// println!("{:?}", foo); /// ``` pub USE_DEBUG, From 2d84d0361d04b5220214bdad9dbf3714d3d8affe Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 4 Aug 2019 08:24:23 +0200 Subject: [PATCH 107/133] Split up cast.rs tests, run-rustfix for unnecessary_cast This splits up the cast.rs tests and enables rustfix tests for the part of the `unnecessary_cast` lint that emits `MachineApplicable` suggestions. cc #3630 --- tests/ui/cast.rs | 28 ----------------- tests/ui/cast.stderr | 40 +----------------------- tests/ui/unnecessary_cast.rs | 23 ++++++++++++++ tests/ui/unnecessary_cast.stderr | 22 +++++++++++++ tests/ui/unnecessary_cast_fixable.fixed | 17 ++++++++++ tests/ui/unnecessary_cast_fixable.rs | 17 ++++++++++ tests/ui/unnecessary_cast_fixable.stderr | 22 +++++++++++++ 7 files changed, 102 insertions(+), 67 deletions(-) create mode 100644 tests/ui/unnecessary_cast.rs create mode 100644 tests/ui/unnecessary_cast.stderr create mode 100644 tests/ui/unnecessary_cast_fixable.fixed create mode 100644 tests/ui/unnecessary_cast_fixable.rs create mode 100644 tests/ui/unnecessary_cast_fixable.stderr diff --git a/tests/ui/cast.rs b/tests/ui/cast.rs index 16da099bd..797050719 100644 --- a/tests/ui/cast.rs +++ b/tests/ui/cast.rs @@ -42,32 +42,4 @@ fn main() { i32::max_value() as u32; i64::max_value() as u64; i128::max_value() as u128; - // Extra checks for *size - // Test cast_unnecessary - 1i32 as i32; - 1f32 as f32; - false as bool; - &1i32 as &i32; - // macro version - macro_rules! foo { - ($a:ident, $b:ident) => { - pub fn $a() -> $b { - 1 as $b - } - }; - } - foo!(a, i32); - foo!(b, f32); - foo!(c, f64); - - // casting integer literal to float is unnecessary - 100 as f32; - 100 as f64; - 100_i32 as f64; - // Should not trigger - #[rustfmt::skip] - let v = vec!(1); - &v as &[i32]; - 1.0 as f64; - 1 as u64; } diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 42232808c..0ebd3a1f1 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -138,43 +138,5 @@ error: casting isize to usize may lose the sign of the value LL | -1isize as usize; | ^^^^^^^^^^^^^^^^ -error: casting to the same type is unnecessary (`i32` -> `i32`) - --> $DIR/cast.rs:47:5 - | -LL | 1i32 as i32; - | ^^^^^^^^^^^ - | - = note: `-D clippy::unnecessary-cast` implied by `-D warnings` - -error: casting to the same type is unnecessary (`f32` -> `f32`) - --> $DIR/cast.rs:48:5 - | -LL | 1f32 as f32; - | ^^^^^^^^^^^ - -error: casting to the same type is unnecessary (`bool` -> `bool`) - --> $DIR/cast.rs:49:5 - | -LL | false as bool; - | ^^^^^^^^^^^^^ - -error: casting integer literal to f32 is unnecessary - --> $DIR/cast.rs:64:5 - | -LL | 100 as f32; - | ^^^^^^^^^^ help: try: `100_f32` - -error: casting integer literal to f64 is unnecessary - --> $DIR/cast.rs:65:5 - | -LL | 100 as f64; - | ^^^^^^^^^^ help: try: `100_f64` - -error: casting integer literal to f64 is unnecessary - --> $DIR/cast.rs:66:5 - | -LL | 100_i32 as f64; - | ^^^^^^^^^^^^^^ help: try: `100_f64` - -error: aborting due to 28 previous errors +error: aborting due to 22 previous errors diff --git a/tests/ui/unnecessary_cast.rs b/tests/ui/unnecessary_cast.rs new file mode 100644 index 000000000..df9b227ee --- /dev/null +++ b/tests/ui/unnecessary_cast.rs @@ -0,0 +1,23 @@ +#![warn(clippy::unnecessary_cast)] +#![allow(clippy::no_effect)] + +fn main() { + // Test cast_unnecessary + 1i32 as i32; + 1f32 as f32; + false as bool; + &1i32 as &i32; + + // macro version + macro_rules! foo { + ($a:ident, $b:ident) => { + #[allow(unused)] + pub fn $a() -> $b { + 1 as $b + } + }; + } + foo!(a, i32); + foo!(b, f32); + foo!(c, f64); +} diff --git a/tests/ui/unnecessary_cast.stderr b/tests/ui/unnecessary_cast.stderr new file mode 100644 index 000000000..8981d13e8 --- /dev/null +++ b/tests/ui/unnecessary_cast.stderr @@ -0,0 +1,22 @@ +error: casting to the same type is unnecessary (`i32` -> `i32`) + --> $DIR/unnecessary_cast.rs:6:5 + | +LL | 1i32 as i32; + | ^^^^^^^^^^^ + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + +error: casting to the same type is unnecessary (`f32` -> `f32`) + --> $DIR/unnecessary_cast.rs:7:5 + | +LL | 1f32 as f32; + | ^^^^^^^^^^^ + +error: casting to the same type is unnecessary (`bool` -> `bool`) + --> $DIR/unnecessary_cast.rs:8:5 + | +LL | false as bool; + | ^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/unnecessary_cast_fixable.fixed b/tests/ui/unnecessary_cast_fixable.fixed new file mode 100644 index 000000000..8c659df83 --- /dev/null +++ b/tests/ui/unnecessary_cast_fixable.fixed @@ -0,0 +1,17 @@ +// run-rustfix + +#![warn(clippy::unnecessary_cast)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] + +fn main() { + // casting integer literal to float is unnecessary + 100_f32; + 100_f64; + 100_f64; + // Should not trigger + #[rustfmt::skip] + let v = vec!(1); + &v as &[i32]; + 1.0 as f64; + 1 as u64; +} diff --git a/tests/ui/unnecessary_cast_fixable.rs b/tests/ui/unnecessary_cast_fixable.rs new file mode 100644 index 000000000..7bab5540c --- /dev/null +++ b/tests/ui/unnecessary_cast_fixable.rs @@ -0,0 +1,17 @@ +// run-rustfix + +#![warn(clippy::unnecessary_cast)] +#![allow(clippy::no_effect, clippy::unnecessary_operation)] + +fn main() { + // casting integer literal to float is unnecessary + 100 as f32; + 100 as f64; + 100_i32 as f64; + // Should not trigger + #[rustfmt::skip] + let v = vec!(1); + &v as &[i32]; + 1.0 as f64; + 1 as u64; +} diff --git a/tests/ui/unnecessary_cast_fixable.stderr b/tests/ui/unnecessary_cast_fixable.stderr new file mode 100644 index 000000000..74616bb90 --- /dev/null +++ b/tests/ui/unnecessary_cast_fixable.stderr @@ -0,0 +1,22 @@ +error: casting integer literal to f32 is unnecessary + --> $DIR/unnecessary_cast_fixable.rs:8:5 + | +LL | 100 as f32; + | ^^^^^^^^^^ help: try: `100_f32` + | + = note: `-D clippy::unnecessary-cast` implied by `-D warnings` + +error: casting integer literal to f64 is unnecessary + --> $DIR/unnecessary_cast_fixable.rs:9:5 + | +LL | 100 as f64; + | ^^^^^^^^^^ help: try: `100_f64` + +error: casting integer literal to f64 is unnecessary + --> $DIR/unnecessary_cast_fixable.rs:10:5 + | +LL | 100_i32 as f64; + | ^^^^^^^^^^^^^^ help: try: `100_f64` + +error: aborting due to 3 previous errors + From a332febb04b3a05c72530712bba9bb5b0aab75c8 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 4 Aug 2019 10:21:52 +0200 Subject: [PATCH 108/133] Add run-rustfix for decimal_literal_representation lint cc #3630 --- tests/ui/decimal_literal_representation.fixed | 25 +++++++++++++++++++ tests/ui/decimal_literal_representation.rs | 3 +++ .../ui/decimal_literal_representation.stderr | 10 ++++---- 3 files changed, 33 insertions(+), 5 deletions(-) create mode 100644 tests/ui/decimal_literal_representation.fixed diff --git a/tests/ui/decimal_literal_representation.fixed b/tests/ui/decimal_literal_representation.fixed new file mode 100644 index 000000000..959481540 --- /dev/null +++ b/tests/ui/decimal_literal_representation.fixed @@ -0,0 +1,25 @@ +// run-rustfix + +#[warn(clippy::decimal_literal_representation)] +#[allow(unused_variables)] +#[rustfmt::skip] +fn main() { + let good = ( // Hex: + 127, // 0x7F + 256, // 0x100 + 511, // 0x1FF + 2048, // 0x800 + 4090, // 0xFFA + 16_371, // 0x3FF3 + 61_683, // 0xF0F3 + 2_131_750_925, // 0x7F0F_F00D + ); + let bad = ( // Hex: + 0x8005, // 0x8005 + 0xFF00, // 0xFF00 + 0x7F0F_F00F, // 0x7F0F_F00F + 0x7FFF_FFFF, // 0x7FFF_FFFF + #[allow(overflowing_literals)] + 0xF0F0_F0F0, // 0xF0F0_F0F0 + ); +} diff --git a/tests/ui/decimal_literal_representation.rs b/tests/ui/decimal_literal_representation.rs index d841f1675..3f73ebc6e 100644 --- a/tests/ui/decimal_literal_representation.rs +++ b/tests/ui/decimal_literal_representation.rs @@ -1,3 +1,5 @@ +// run-rustfix + #[warn(clippy::decimal_literal_representation)] #[allow(unused_variables)] #[rustfmt::skip] @@ -17,6 +19,7 @@ fn main() { 65_280, // 0xFF00 2_131_750_927, // 0x7F0F_F00F 2_147_483_647, // 0x7FFF_FFFF + #[allow(overflowing_literals)] 4_042_322_160, // 0xF0F0_F0F0 ); } diff --git a/tests/ui/decimal_literal_representation.stderr b/tests/ui/decimal_literal_representation.stderr index 3a535def1..862b193ce 100644 --- a/tests/ui/decimal_literal_representation.stderr +++ b/tests/ui/decimal_literal_representation.stderr @@ -1,5 +1,5 @@ error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:16:9 + --> $DIR/decimal_literal_representation.rs:18:9 | LL | 32_773, // 0x8005 | ^^^^^^ help: consider: `0x8005` @@ -7,25 +7,25 @@ LL | 32_773, // 0x8005 = note: `-D clippy::decimal-literal-representation` implied by `-D warnings` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:17:9 + --> $DIR/decimal_literal_representation.rs:19:9 | LL | 65_280, // 0xFF00 | ^^^^^^ help: consider: `0xFF00` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:18:9 + --> $DIR/decimal_literal_representation.rs:20:9 | LL | 2_131_750_927, // 0x7F0F_F00F | ^^^^^^^^^^^^^ help: consider: `0x7F0F_F00F` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:19:9 + --> $DIR/decimal_literal_representation.rs:21:9 | LL | 2_147_483_647, // 0x7FFF_FFFF | ^^^^^^^^^^^^^ help: consider: `0x7FFF_FFFF` error: integer literal has a better hexadecimal representation - --> $DIR/decimal_literal_representation.rs:20:9 + --> $DIR/decimal_literal_representation.rs:23:9 | LL | 4_042_322_160, // 0xF0F0_F0F0 | ^^^^^^^^^^^^^ help: consider: `0xF0F0_F0F0` From 71a943820bee0daa2d9f89c0c9b7f8758bcfd429 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 5 Aug 2019 07:30:01 +0200 Subject: [PATCH 109/133] Rustup to https://github.com/rust-lang/rust/pull/63213 --- clippy_lints/src/missing_doc.rs | 4 ++-- clippy_lints/src/missing_inline.rs | 4 ++-- clippy_lints/src/types.rs | 2 +- clippy_lints/src/utils/inspector.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 00f1cf9a5..7f49a287c 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -146,7 +146,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { hir::ItemKind::Struct(..) => "a struct", hir::ItemKind::Trait(..) => "a trait", hir::ItemKind::TraitAlias(..) => "a trait alias", - hir::ItemKind::Ty(..) => "a type alias", + hir::ItemKind::TyAlias(..) => "a type alias", hir::ItemKind::Union(..) => "a union", hir::ItemKind::OpaqueTy(..) => "an existential type", hir::ItemKind::ExternCrate(..) @@ -184,7 +184,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc { let desc = match impl_item.node { hir::ImplItemKind::Const(..) => "an associated constant", hir::ImplItemKind::Method(..) => "a method", - hir::ImplItemKind::Type(_) => "an associated type", + hir::ImplItemKind::TyAlias(_) => "an associated type", hir::ImplItemKind::OpaqueTy(_) => "an existential type", }; self.check_missing_docs_attrs(cx, &impl_item.attrs, impl_item.span, desc); diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index c467f2fc3..e738fd554 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -119,7 +119,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { | hir::ItemKind::Struct(..) | hir::ItemKind::TraitAlias(..) | hir::ItemKind::GlobalAsm(..) - | hir::ItemKind::Ty(..) + | hir::ItemKind::TyAlias(..) | hir::ItemKind::Union(..) | hir::ItemKind::OpaqueTy(..) | hir::ItemKind::ExternCrate(..) @@ -142,7 +142,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingInline { let desc = match impl_item.node { hir::ImplItemKind::Method(..) => "a method", - hir::ImplItemKind::Const(..) | hir::ImplItemKind::Type(_) | hir::ImplItemKind::OpaqueTy(_) => return, + hir::ImplItemKind::Const(..) | hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => return, }; let def_id = cx.tcx.hir().local_def_id(impl_item.hir_id); diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3c8ca3fea..654674de0 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -1354,7 +1354,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeComplexity { fn check_impl_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx ImplItem) { match item.node { - ImplItemKind::Const(ref ty, _) | ImplItemKind::Type(ref ty) => self.check_type(cx, ty), + ImplItemKind::Const(ref ty, _) | ImplItemKind::TyAlias(ref ty) => self.check_type(cx, ty), // methods are covered by check_fn _ => (), } diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index c061e4f91..809590c88 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -63,7 +63,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for DeepCodeInspector { print_expr(cx, &cx.tcx.hir().body(body_id).value, 1); }, hir::ImplItemKind::Method(..) => println!("method"), - hir::ImplItemKind::Type(_) => println!("associated type"), + hir::ImplItemKind::TyAlias(_) => println!("associated type"), hir::ImplItemKind::OpaqueTy(_) => println!("existential type"), } } @@ -360,7 +360,7 @@ fn print_item(cx: &LateContext<'_, '_>, item: &hir::Item) { hir::ItemKind::Mod(..) => println!("module"), hir::ItemKind::ForeignMod(ref fm) => println!("foreign module with abi: {}", fm.abi), hir::ItemKind::GlobalAsm(ref asm) => println!("global asm: {:?}", asm), - hir::ItemKind::Ty(..) => { + hir::ItemKind::TyAlias(..) => { println!("type alias for {:?}", cx.tcx.type_of(did)); }, hir::ItemKind::OpaqueTy(..) => { From c5ad0b075a1bf37c0dad43fbe763d1fa56b12c3f Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 5 Aug 2019 09:29:39 +0200 Subject: [PATCH 110/133] Make let_unit lint suggestion auto applicable --- clippy_lints/src/types.rs | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/types.rs b/clippy_lints/src/types.rs index 3c8ca3fea..ec2091062 100644 --- a/clippy_lints/src/types.rs +++ b/clippy_lints/src/types.rs @@ -25,7 +25,7 @@ use crate::utils::paths; use crate::utils::{ clip, comparisons, differing_macro_contexts, higher, in_constant, in_macro_or_desugar, int_bits, last_path_segment, match_def_path, match_path, multispan_sugg, same_tys, sext, snippet, snippet_opt, snippet_with_applicability, - span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, + snippet_with_macro_callsite, span_help_and_lint, span_lint, span_lint_and_sugg, span_lint_and_then, unsext, }; declare_clippy_lint! { @@ -467,15 +467,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for LetUnitValue { if higher::is_from_for_desugar(local) { return; } - span_lint( - cx, - LET_UNIT_VALUE, - stmt.span, - &format!( - "this let-binding has unit value. Consider omitting `let {} =`", - snippet(cx, local.pat.span, "..") - ), - ); + span_lint_and_then(cx, LET_UNIT_VALUE, stmt.span, "this let-binding has unit value", |db| { + if let Some(expr) = &local.init { + let snip = snippet_with_macro_callsite(cx, expr.span, "()"); + db.span_suggestion( + stmt.span, + "omit the `let` binding", + format!("{};", snip), + Applicability::MachineApplicable, // snippet + ); + } + }); } } } From 385f4474da199a0f21c93be454043b9bb25f2cd7 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 5 Aug 2019 09:30:24 +0200 Subject: [PATCH 111/133] Add tests for auto fixable let_unit suggestion --- tests/ui/let_unit.fixed | 63 ++++++++++++++++++++++++++++++++++++++++ tests/ui/let_unit.rs | 17 +++++++++++ tests/ui/let_unit.stderr | 35 +++++++++++++++++----- 3 files changed, 108 insertions(+), 7 deletions(-) create mode 100644 tests/ui/let_unit.fixed diff --git a/tests/ui/let_unit.fixed b/tests/ui/let_unit.fixed new file mode 100644 index 000000000..f398edc23 --- /dev/null +++ b/tests/ui/let_unit.fixed @@ -0,0 +1,63 @@ +// run-rustfix + +#![warn(clippy::let_unit_value)] +#![allow(clippy::no_effect)] +#![allow(unused_variables)] + +macro_rules! let_and_return { + ($n:expr) => {{ + let ret = $n; + }}; +} + +fn main() { + println!("x"); + let _y = 1; // this is fine + let _z = ((), 1); // this as well + if true { + (); + } + + consume_units_with_for_loop(); // should be fine as well + + multiline_sugg(); + + let_and_return!(()) // should be fine +} + +// Related to issue #1964 +fn consume_units_with_for_loop() { + // `for_let_unit` lint should not be triggered by consuming them using for loop. + let v = vec![(), (), ()]; + let mut count = 0; + for _ in v { + count += 1; + } + assert_eq!(count, 3); + + // Same for consuming from some other Iterator. + let (tx, rx) = ::std::sync::mpsc::channel(); + tx.send(()).unwrap(); + drop(tx); + + count = 0; + for _ in rx.iter() { + count += 1; + } + assert_eq!(count, 1); +} + +fn multiline_sugg() { + let v: Vec = vec![2]; + + v + .into_iter() + .map(|i| i * 2) + .filter(|i| i % 2 == 0) + .map(|_| ()) + .next() + .unwrap(); +} + +#[derive(Copy, Clone)] +pub struct ContainsUnit(()); // should be fine diff --git a/tests/ui/let_unit.rs b/tests/ui/let_unit.rs index dc17c98f6..af5b1fb2a 100644 --- a/tests/ui/let_unit.rs +++ b/tests/ui/let_unit.rs @@ -1,4 +1,7 @@ +// run-rustfix + #![warn(clippy::let_unit_value)] +#![allow(clippy::no_effect)] #![allow(unused_variables)] macro_rules! let_and_return { @@ -17,6 +20,8 @@ fn main() { consume_units_with_for_loop(); // should be fine as well + multiline_sugg(); + let_and_return!(()) // should be fine } @@ -42,5 +47,17 @@ fn consume_units_with_for_loop() { assert_eq!(count, 1); } +fn multiline_sugg() { + let v: Vec = vec![2]; + + let _ = v + .into_iter() + .map(|i| i * 2) + .filter(|i| i % 2 == 0) + .map(|_| ()) + .next() + .unwrap(); +} + #[derive(Copy, Clone)] pub struct ContainsUnit(()); // should be fine diff --git a/tests/ui/let_unit.stderr b/tests/ui/let_unit.stderr index e1773a402..7130fcd87 100644 --- a/tests/ui/let_unit.stderr +++ b/tests/ui/let_unit.stderr @@ -1,16 +1,37 @@ -error: this let-binding has unit value. Consider omitting `let _x =` - --> $DIR/let_unit.rs:11:5 +error: this let-binding has unit value + --> $DIR/let_unit.rs:14:5 | LL | let _x = println!("x"); - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ help: omit the `let` binding: `println!("x");` | = note: `-D clippy::let-unit-value` implied by `-D warnings` -error: this let-binding has unit value. Consider omitting `let _a =` - --> $DIR/let_unit.rs:15:9 +error: this let-binding has unit value + --> $DIR/let_unit.rs:18:9 | LL | let _a = (); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^ help: omit the `let` binding: `();` -error: aborting due to 2 previous errors +error: this let-binding has unit value + --> $DIR/let_unit.rs:53:5 + | +LL | / let _ = v +LL | | .into_iter() +LL | | .map(|i| i * 2) +LL | | .filter(|i| i % 2 == 0) +LL | | .map(|_| ()) +LL | | .next() +LL | | .unwrap(); + | |__________________^ +help: omit the `let` binding + | +LL | v +LL | .into_iter() +LL | .map(|i| i * 2) +LL | .filter(|i| i % 2 == 0) +LL | .map(|_| ()) +LL | .next() + ... + +error: aborting due to 3 previous errors From 4eab691db63c11ffeaea79c4ad4f3ff8b17564ef Mon Sep 17 00:00:00 2001 From: Vincent Dal Maso Date: Thu, 13 Jun 2019 10:58:35 +0200 Subject: [PATCH 112/133] Add recursion check on main function Changes: - Add MainRecursion lint to clippy - Check for no-std setup fixes #333 --- clippy_lints/src/lib.rs | 2 + clippy_lints/src/main_recursion.rs | 55 +++++++++++++++++++ .../no_std_main_recursion.rs | 31 +++++++++++ .../no_std_main_recursion.stderr | 0 .../crate_level_checks/std_main_recursion.rs | 5 ++ .../std_main_recursion.stderr | 11 ++++ 6 files changed, 104 insertions(+) create mode 100644 clippy_lints/src/main_recursion.rs create mode 100644 tests/ui/crate_level_checks/no_std_main_recursion.rs create mode 100644 tests/ui/crate_level_checks/no_std_main_recursion.stderr create mode 100644 tests/ui/crate_level_checks/std_main_recursion.rs create mode 100644 tests/ui/crate_level_checks/std_main_recursion.stderr diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 8e2340175..325195caa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -208,6 +208,7 @@ pub mod let_if_seq; pub mod lifetimes; pub mod literal_representation; pub mod loops; +pub mod main_recursion; pub mod map_clone; pub mod map_unit_fn; pub mod matches; @@ -473,6 +474,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box types::LetUnitValue); reg.register_late_lint_pass(box types::UnitCmp); reg.register_late_lint_pass(box loops::Loops); + reg.register_early_lint_pass(box main_recursion::MainRecursion::new()); reg.register_late_lint_pass(box lifetimes::Lifetimes); reg.register_late_lint_pass(box entry::HashMapPass); reg.register_late_lint_pass(box ranges::Ranges); diff --git a/clippy_lints/src/main_recursion.rs b/clippy_lints/src/main_recursion.rs new file mode 100644 index 000000000..9ef4de21f --- /dev/null +++ b/clippy_lints/src/main_recursion.rs @@ -0,0 +1,55 @@ + +use syntax::ast::{Crate, Expr, ExprKind}; +use syntax::symbol::sym; +use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext}; +use rustc::{declare_tool_lint, impl_lint_pass}; + +use if_chain::if_chain; +use crate::utils::span_help_and_lint; + +declare_clippy_lint! { + pub MAIN_RECURSION, + pedantic, + "function named `foo`, which is not a descriptive name" +} + +pub struct MainRecursion { + has_no_std_attr: bool +} + +impl_lint_pass!(MainRecursion => [MAIN_RECURSION]); + +impl MainRecursion { + pub fn new() -> MainRecursion { + MainRecursion { + has_no_std_attr: false + } + } +} + +impl EarlyLintPass for MainRecursion { + fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) { + self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std); + } + + fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + if self.has_no_std_attr { + return; + } + + if_chain! { + if let ExprKind::Call(func, _) = &expr.node; + if let ExprKind::Path(_, path) = &func.node; + if *path == sym::main; + then { + span_help_and_lint( + cx, + MAIN_RECURSION, + expr.span, + "You are recursing into main()", + "Consider using another function for this recursion" + ) + } + } + } +} diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs new file mode 100644 index 000000000..857af96a0 --- /dev/null +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -0,0 +1,31 @@ +#![feature(lang_items, link_args, start, libc)] +#![link_args="-nostartfiles"] +#![no_std] + +use core::panic::PanicInfo; +use core::sync::atomic::{AtomicUsize, Ordering}; + +static N: AtomicUsize = AtomicUsize::new(0); + +#[warn(clippy::main_recursion)] +#[allow(unconditional_recursion)] +#[start] +fn main(argc: isize, argv: *const *const u8) -> isize { + let x = N.load(Ordering::Relaxed); + N.store(x + 1, Ordering::Relaxed); + + if x < 3 { + main(argc, argv); + } + + 0 +} + +#[allow(clippy::empty_loop)] +#[panic_handler] +fn panic(_info: &PanicInfo) -> ! { + loop {} +} + +#[lang = "eh_personality"] +extern fn eh_personality() {} diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.stderr b/tests/ui/crate_level_checks/no_std_main_recursion.stderr new file mode 100644 index 000000000..e69de29bb diff --git a/tests/ui/crate_level_checks/std_main_recursion.rs b/tests/ui/crate_level_checks/std_main_recursion.rs new file mode 100644 index 000000000..e7689ffb7 --- /dev/null +++ b/tests/ui/crate_level_checks/std_main_recursion.rs @@ -0,0 +1,5 @@ +#[warn(clippy::main_recursion)] +#[allow(unconditional_recursion)] +fn main() { + main(); +} diff --git a/tests/ui/crate_level_checks/std_main_recursion.stderr b/tests/ui/crate_level_checks/std_main_recursion.stderr new file mode 100644 index 000000000..7979010ea --- /dev/null +++ b/tests/ui/crate_level_checks/std_main_recursion.stderr @@ -0,0 +1,11 @@ +error: You are recursing into main() + --> $DIR/std_main_recursion.rs:4:5 + | +LL | main(); + | ^^^^^^ + | + = note: `-D clippy::main-recursion` implied by `-D warnings` + = help: Consider using another function for this recursion + +error: aborting due to previous error + From 77b21b644f2072768d24dee331494b082ea133d1 Mon Sep 17 00:00:00 2001 From: Vincent Dal Maso Date: Mon, 17 Jun 2019 17:36:42 +0200 Subject: [PATCH 113/133] Move expression check to LateLintPass Changes: - Move from EarlyLintPass - Fix entrypoint check with function path def_id. --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 4 +- clippy_lints/src/main_recursion.rs | 55 +++++++++++-------- src/lintlist/mod.rs | 7 +++ .../entrypoint_recursion.rs | 12 ++++ .../entrypoint_recursion.stderr | 11 ++++ .../no_std_main_recursion.rs | 5 +- .../no_std_main_recursion.stderr | 0 .../crate_level_checks/std_main_recursion.rs | 1 + .../std_main_recursion.stderr | 8 +-- 10 files changed, 72 insertions(+), 32 deletions(-) create mode 100644 tests/ui/crate_level_checks/entrypoint_recursion.rs create mode 100644 tests/ui/crate_level_checks/entrypoint_recursion.stderr delete mode 100644 tests/ui/crate_level_checks/no_std_main_recursion.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 089897811..e4a1a602c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1000,6 +1000,7 @@ Released 2018-09-13 [`let_unit_value`]: https://rust-lang.github.io/rust-clippy/master/index.html#let_unit_value [`linkedlist`]: https://rust-lang.github.io/rust-clippy/master/index.html#linkedlist [`logic_bug`]: https://rust-lang.github.io/rust-clippy/master/index.html#logic_bug +[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion [`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy [`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap [`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 325195caa..258be38e4 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -474,7 +474,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box types::LetUnitValue); reg.register_late_lint_pass(box types::UnitCmp); reg.register_late_lint_pass(box loops::Loops); - reg.register_early_lint_pass(box main_recursion::MainRecursion::new()); + reg.register_late_lint_pass(box main_recursion::MainRecursion::default()); reg.register_late_lint_pass(box lifetimes::Lifetimes); reg.register_late_lint_pass(box entry::HashMapPass); reg.register_late_lint_pass(box ranges::Ranges); @@ -762,6 +762,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::WHILE_IMMUTABLE_CONDITION, loops::WHILE_LET_LOOP, loops::WHILE_LET_ON_ITERATOR, + main_recursion::MAIN_RECURSION, map_clone::MAP_CLONE, map_unit_fn::OPTION_MAP_UNIT_FN, map_unit_fn::RESULT_MAP_UNIT_FN, @@ -935,6 +936,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { loops::FOR_KV_MAP, loops::NEEDLESS_RANGE_LOOP, loops::WHILE_LET_ON_ITERATOR, + main_recursion::MAIN_RECURSION, map_clone::MAP_CLONE, matches::MATCH_BOOL, matches::MATCH_OVERLAPPING_ARM, diff --git a/clippy_lints/src/main_recursion.rs b/clippy_lints/src/main_recursion.rs index 9ef4de21f..88f1e685c 100644 --- a/clippy_lints/src/main_recursion.rs +++ b/clippy_lints/src/main_recursion.rs @@ -1,53 +1,60 @@ - -use syntax::ast::{Crate, Expr, ExprKind}; -use syntax::symbol::sym; -use rustc::lint::{LintArray, LintPass, EarlyLintPass, EarlyContext}; +use rustc::hir::{Crate, Expr, ExprKind, QPath}; +use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, impl_lint_pass}; +use syntax::symbol::sym; +use crate::utils::{is_entrypoint_fn, snippet, span_help_and_lint}; use if_chain::if_chain; -use crate::utils::span_help_and_lint; declare_clippy_lint! { + /// **What it does:** Checks for recursion using the entrypoint. + /// + /// **Why is this bad?** Apart from special setups (which we could detect following attributes like #![no_std]), + /// recursing into main() seems like an unintuitive antipattern we should be able to detect. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```no_run + /// fn main() { + /// main(); + /// } + /// ``` pub MAIN_RECURSION, - pedantic, - "function named `foo`, which is not a descriptive name" + style, + "recursion using the entrypoint" } +#[derive(Default)] pub struct MainRecursion { - has_no_std_attr: bool + has_no_std_attr: bool, } impl_lint_pass!(MainRecursion => [MAIN_RECURSION]); -impl MainRecursion { - pub fn new() -> MainRecursion { - MainRecursion { - has_no_std_attr: false - } - } -} - -impl EarlyLintPass for MainRecursion { - fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) { +impl LateLintPass<'_, '_> for MainRecursion { + fn check_crate(&mut self, _: &LateContext<'_, '_>, krate: &Crate) { self.has_no_std_attr = krate.attrs.iter().any(|attr| attr.path == sym::no_std); } - fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) { + fn check_expr_post(&mut self, cx: &LateContext<'_, '_>, expr: &Expr) { if self.has_no_std_attr { return; } if_chain! { if let ExprKind::Call(func, _) = &expr.node; - if let ExprKind::Path(_, path) = &func.node; - if *path == sym::main; + if let ExprKind::Path(path) = &func.node; + if let QPath::Resolved(_, path) = &path; + if let Some(def_id) = path.res.opt_def_id(); + if is_entrypoint_fn(cx, def_id); then { span_help_and_lint( cx, MAIN_RECURSION, - expr.span, - "You are recursing into main()", - "Consider using another function for this recursion" + func.span, + &format!("recursing into entrypoint `{}`", snippet(cx, func.span, "main")), + "consider using another function for this recursion" ) } } diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index aa4576640..802ba60b9 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -917,6 +917,13 @@ pub const ALL_LINTS: [Lint; 309] = [ deprecation: None, module: "booleans", }, + Lint { + name: "main_recursion", + group: "style", + desc: "recursion using the entrypoint", + deprecation: None, + module: "main_recursion", + }, Lint { name: "manual_memcpy", group: "perf", diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.rs b/tests/ui/crate_level_checks/entrypoint_recursion.rs new file mode 100644 index 000000000..995787c53 --- /dev/null +++ b/tests/ui/crate_level_checks/entrypoint_recursion.rs @@ -0,0 +1,12 @@ +// ignore-macos +// ignore-windows + +#![feature(main)] + +#[warn(clippy::main_recursion)] +#[allow(unconditional_recursion)] +#[main] +fn a() { + println!("Hello, World!"); + a(); +} diff --git a/tests/ui/crate_level_checks/entrypoint_recursion.stderr b/tests/ui/crate_level_checks/entrypoint_recursion.stderr new file mode 100644 index 000000000..f52fc949f --- /dev/null +++ b/tests/ui/crate_level_checks/entrypoint_recursion.stderr @@ -0,0 +1,11 @@ +error: recursing into entrypoint `a` + --> $DIR/entrypoint_recursion.rs:11:5 + | +LL | a(); + | ^ + | + = note: `-D clippy::main-recursion` implied by `-D warnings` + = help: consider using another function for this recursion + +error: aborting due to previous error + diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs index 857af96a0..4d19f38e2 100644 --- a/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -1,5 +1,5 @@ #![feature(lang_items, link_args, start, libc)] -#![link_args="-nostartfiles"] +#![link_args = "-nostartfiles"] #![no_std] use core::panic::PanicInfo; @@ -8,7 +8,6 @@ use core::sync::atomic::{AtomicUsize, Ordering}; static N: AtomicUsize = AtomicUsize::new(0); #[warn(clippy::main_recursion)] -#[allow(unconditional_recursion)] #[start] fn main(argc: isize, argv: *const *const u8) -> isize { let x = N.load(Ordering::Relaxed); @@ -28,4 +27,4 @@ fn panic(_info: &PanicInfo) -> ! { } #[lang = "eh_personality"] -extern fn eh_personality() {} +extern "C" fn eh_personality() {} diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.stderr b/tests/ui/crate_level_checks/no_std_main_recursion.stderr deleted file mode 100644 index e69de29bb..000000000 diff --git a/tests/ui/crate_level_checks/std_main_recursion.rs b/tests/ui/crate_level_checks/std_main_recursion.rs index e7689ffb7..89ff66099 100644 --- a/tests/ui/crate_level_checks/std_main_recursion.rs +++ b/tests/ui/crate_level_checks/std_main_recursion.rs @@ -1,5 +1,6 @@ #[warn(clippy::main_recursion)] #[allow(unconditional_recursion)] fn main() { + println!("Hello, World!"); main(); } diff --git a/tests/ui/crate_level_checks/std_main_recursion.stderr b/tests/ui/crate_level_checks/std_main_recursion.stderr index 7979010ea..0a260f9d2 100644 --- a/tests/ui/crate_level_checks/std_main_recursion.stderr +++ b/tests/ui/crate_level_checks/std_main_recursion.stderr @@ -1,11 +1,11 @@ -error: You are recursing into main() - --> $DIR/std_main_recursion.rs:4:5 +error: recursing into entrypoint `main` + --> $DIR/std_main_recursion.rs:5:5 | LL | main(); - | ^^^^^^ + | ^^^^ | = note: `-D clippy::main-recursion` implied by `-D warnings` - = help: Consider using another function for this recursion + = help: consider using another function for this recursion error: aborting due to previous error From a922f800aff150b1b2b8093ff54df40736b82332 Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 5 Aug 2019 13:24:31 +0200 Subject: [PATCH 114/133] Run update_lints and fmt --- README.md | 2 +- src/lintlist/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 38651f72e..ff64fc937 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 309 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 310 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: diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 802ba60b9..93712e8eb 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 309] = [ +pub const ALL_LINTS: [Lint; 310] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", From dabf599c90485c79420ed9cbb2ec342afb5b265a Mon Sep 17 00:00:00 2001 From: flip1995 Date: Mon, 5 Aug 2019 17:53:55 +0200 Subject: [PATCH 115/133] Ignore no_std-test on windows and macos --- tests/ui/crate_level_checks/no_std_main_recursion.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/ui/crate_level_checks/no_std_main_recursion.rs b/tests/ui/crate_level_checks/no_std_main_recursion.rs index 4d19f38e2..25b1417be 100644 --- a/tests/ui/crate_level_checks/no_std_main_recursion.rs +++ b/tests/ui/crate_level_checks/no_std_main_recursion.rs @@ -1,3 +1,6 @@ +// ignore-macos +// ignore-windows + #![feature(lang_items, link_args, start, libc)] #![link_args = "-nostartfiles"] #![no_std] From 4cfb0966a19ade111bcd57abf53fb1a8f543a127 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Sun, 4 Aug 2019 22:08:28 +0200 Subject: [PATCH 116/133] Fix needless_bool suggestion with if-else-if-else Closes #4334 --- clippy_lints/src/needless_bool.rs | 14 +++++++------ tests/ui/needless_bool.rs | 1 + tests/ui/needless_bool.stderr | 34 +++++++++++++++---------------- 3 files changed, 26 insertions(+), 23 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 167f00fee..199420071 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -118,13 +118,15 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool let parent_id = cx.tcx.hir().get_parent_node(expr.hir_id); let parent_node = cx.tcx.hir().get(parent_id); - if let rustc::hir::Node::Expr(e) = parent_node { - if higher::if_block(&e).is_some() { - return true; - } + match parent_node { + rustc::hir::Node::Expr(e) => { + higher::if_block(&e).is_some() + }, + rustc::hir::Node::Arm(e) => { + higher::if_block(&e.body).is_some() + }, + _ => false } - - false } declare_lint_pass!(BoolComparison => [BOOL_COMPARISON]); diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool.rs index 757055257..15582f087 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool.rs @@ -1,4 +1,5 @@ #![warn(clippy::needless_bool)] +#![allow(unused, dead_code, clippy::no_effect)] use std::cell::Cell; diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool.stderr index 30284675f..3c89e51d4 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool.stderr @@ -1,5 +1,5 @@ error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:31:5 + --> $DIR/needless_bool.rs:32:5 | LL | / if x { LL | | true @@ -11,7 +11,7 @@ LL | | }; = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:36:5 + --> $DIR/needless_bool.rs:37:5 | LL | / if x { LL | | false @@ -21,7 +21,7 @@ LL | | }; | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:41:5 + --> $DIR/needless_bool.rs:42:5 | LL | / if x { LL | | true @@ -31,7 +31,7 @@ LL | | }; | |_____^ help: you can reduce it to: `x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:46:5 + --> $DIR/needless_bool.rs:47:5 | LL | / if x { LL | | false @@ -41,7 +41,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:51:5 + --> $DIR/needless_bool.rs:52:5 | LL | / if x && y { LL | | false @@ -51,7 +51,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:74:5 + --> $DIR/needless_bool.rs:75:5 | LL | / if x { LL | | return true; @@ -61,7 +61,7 @@ LL | | }; | |_____^ error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:83:5 + --> $DIR/needless_bool.rs:84:5 | LL | / if x { LL | | return false; @@ -71,7 +71,7 @@ LL | | }; | |_____^ error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:92:5 + --> $DIR/needless_bool.rs:93:5 | LL | / if x { LL | | return true; @@ -81,7 +81,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:101:5 + --> $DIR/needless_bool.rs:102:5 | LL | / if x && y { LL | | return true; @@ -91,7 +91,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x && y` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:110:5 + --> $DIR/needless_bool.rs:111:5 | LL | / if x { LL | | return false; @@ -101,7 +101,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:119:5 + --> $DIR/needless_bool.rs:120:5 | LL | / if x && y { LL | | return false; @@ -111,7 +111,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:127:8 + --> $DIR/needless_bool.rs:128:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -119,25 +119,25 @@ LL | if x == true {}; = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:131:8 + --> $DIR/needless_bool.rs:132:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:141:8 + --> $DIR/needless_bool.rs:142:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:142:8 + --> $DIR/needless_bool.rs:143:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:151:12 + --> $DIR/needless_bool.rs:152:12 | LL | } else if returns_bool() { | ____________^ @@ -145,7 +145,7 @@ LL | | false LL | | } else { LL | | true LL | | }; - | |_____^ help: you can reduce it to: `!returns_bool()` + | |_____^ help: you can reduce it to: `{ !returns_bool() }` error: aborting due to 16 previous errors From cdfb72a5e1497ffc0d2b826e81ef95b2c0b845d9 Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 5 Aug 2019 20:53:13 +0200 Subject: [PATCH 117/133] fmt --- clippy_lints/src/needless_bool.rs | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/clippy_lints/src/needless_bool.rs b/clippy_lints/src/needless_bool.rs index 199420071..285ec0d08 100644 --- a/clippy_lints/src/needless_bool.rs +++ b/clippy_lints/src/needless_bool.rs @@ -119,13 +119,9 @@ fn parent_node_is_if_expr<'a, 'b>(expr: &Expr, cx: &LateContext<'a, 'b>) -> bool let parent_node = cx.tcx.hir().get(parent_id); match parent_node { - rustc::hir::Node::Expr(e) => { - higher::if_block(&e).is_some() - }, - rustc::hir::Node::Arm(e) => { - higher::if_block(&e.body).is_some() - }, - _ => false + rustc::hir::Node::Expr(e) => higher::if_block(&e).is_some(), + rustc::hir::Node::Arm(e) => higher::if_block(&e.body).is_some(), + _ => false, } } From 39c8f84f3b4b7006d3263817d99735ed45422ccd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Mon, 5 Aug 2019 22:05:05 +0200 Subject: [PATCH 118/133] Add run-rustfix for needless_bool lint This splits up the needless_bool tests into `fixable.rs` and `simple.rs`. `simple.rs` contains the code that triggers the lint diagnostic without a suggestion. --- tests/ui/needless_bool/fixable.fixed | 98 +++++++++++++++++++ .../fixable.rs} | 63 ++++-------- .../fixable.stderr} | 88 +++++------------ tests/ui/needless_bool/simple.rs | 46 +++++++++ tests/ui/needless_bool/simple.stderr | 44 +++++++++ 5 files changed, 230 insertions(+), 109 deletions(-) create mode 100644 tests/ui/needless_bool/fixable.fixed rename tests/ui/{needless_bool.rs => needless_bool/fixable.rs} (75%) rename tests/ui/{needless_bool.stderr => needless_bool/fixable.stderr} (66%) create mode 100644 tests/ui/needless_bool/simple.rs create mode 100644 tests/ui/needless_bool/simple.stderr diff --git a/tests/ui/needless_bool/fixable.fixed b/tests/ui/needless_bool/fixable.fixed new file mode 100644 index 000000000..567dbc541 --- /dev/null +++ b/tests/ui/needless_bool/fixable.fixed @@ -0,0 +1,98 @@ +// run-rustfix + +#![warn(clippy::needless_bool)] +#![allow( + unused, + dead_code, + clippy::no_effect, + clippy::if_same_then_else, + clippy::needless_return +)] + +use std::cell::Cell; + +macro_rules! bool_comparison_trigger { + ($($i:ident: $def:expr, $stb:expr );+ $(;)*) => ( + + #[derive(Clone)] + pub struct Trigger { + $($i: (Cell, bool, bool)),+ + } + + #[allow(dead_code)] + impl Trigger { + pub fn trigger(&self, key: &str) -> bool { + $( + if let stringify!($i) = key { + return self.$i.1 && self.$i.2 == $def; + } + )+ + false + } + } + ) +} + +fn main() { + let x = true; + let y = false; + x; + !x; + !(x && y); + if x { + x + } else { + false + }; // would also be questionable, but we don't catch this yet + bool_ret3(x); + bool_ret4(x); + bool_ret5(x, x); + bool_ret6(x, x); + needless_bool(x); + needless_bool2(x); + needless_bool3(x); +} + +fn bool_ret3(x: bool) -> bool { + return x; +} + +fn bool_ret4(x: bool) -> bool { + return !x; +} + +fn bool_ret5(x: bool, y: bool) -> bool { + return x && y; +} + +fn bool_ret6(x: bool, y: bool) -> bool { + return !(x && y); +} + +fn needless_bool(x: bool) { + if x {}; +} + +fn needless_bool2(x: bool) { + if !x {}; +} + +fn needless_bool3(x: bool) { + bool_comparison_trigger! { + test_one: false, false; + test_three: false, false; + test_two: true, true; + } + + if x {}; + if !x {}; +} + +fn needless_bool_in_the_suggestion_wraps_the_predicate_of_if_else_statement_in_brackets() { + let b = false; + let returns_bool = || false; + + let x = if b { + true + } else { !returns_bool() }; +} diff --git a/tests/ui/needless_bool.rs b/tests/ui/needless_bool/fixable.rs similarity index 75% rename from tests/ui/needless_bool.rs rename to tests/ui/needless_bool/fixable.rs index 15582f087..10126ad4d 100644 --- a/tests/ui/needless_bool.rs +++ b/tests/ui/needless_bool/fixable.rs @@ -1,5 +1,13 @@ +// run-rustfix + #![warn(clippy::needless_bool)] -#![allow(unused, dead_code, clippy::no_effect)] +#![allow( + unused, + dead_code, + clippy::no_effect, + clippy::if_same_then_else, + clippy::needless_return +)] use std::cell::Cell; @@ -25,20 +33,9 @@ macro_rules! bool_comparison_trigger { ) } -#[allow(clippy::if_same_then_else)] fn main() { let x = true; let y = false; - if x { - true - } else { - true - }; - if x { - false - } else { - false - }; if x { true } else { @@ -59,36 +56,15 @@ fn main() { } else { false }; // would also be questionable, but we don't catch this yet - bool_ret(x); - bool_ret2(x); bool_ret3(x); - bool_ret5(x, x); bool_ret4(x); + bool_ret5(x, x); bool_ret6(x, x); needless_bool(x); needless_bool2(x); needless_bool3(x); } -#[allow(clippy::if_same_then_else, clippy::needless_return)] -fn bool_ret(x: bool) -> bool { - if x { - return true; - } else { - return true; - }; -} - -#[allow(clippy::if_same_then_else, clippy::needless_return)] -fn bool_ret2(x: bool) -> bool { - if x { - return false; - } else { - return false; - }; -} - -#[allow(clippy::needless_return)] fn bool_ret3(x: bool) -> bool { if x { return true; @@ -97,16 +73,6 @@ fn bool_ret3(x: bool) -> bool { }; } -#[allow(clippy::needless_return)] -fn bool_ret5(x: bool, y: bool) -> bool { - if x && y { - return true; - } else { - return false; - }; -} - -#[allow(clippy::needless_return)] fn bool_ret4(x: bool) -> bool { if x { return false; @@ -115,7 +81,14 @@ fn bool_ret4(x: bool) -> bool { }; } -#[allow(clippy::needless_return)] +fn bool_ret5(x: bool, y: bool) -> bool { + if x && y { + return true; + } else { + return false; + }; +} + fn bool_ret6(x: bool, y: bool) -> bool { if x && y { return false; diff --git a/tests/ui/needless_bool.stderr b/tests/ui/needless_bool/fixable.stderr similarity index 66% rename from tests/ui/needless_bool.stderr rename to tests/ui/needless_bool/fixable.stderr index 3c89e51d4..25abfb2a4 100644 --- a/tests/ui/needless_bool.stderr +++ b/tests/ui/needless_bool/fixable.stderr @@ -1,27 +1,5 @@ -error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:32:5 - | -LL | / if x { -LL | | true -LL | | } else { -LL | | true -LL | | }; - | |_____^ - | - = note: `-D clippy::needless-bool` implied by `-D warnings` - -error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:37:5 - | -LL | / if x { -LL | | false -LL | | } else { -LL | | false -LL | | }; - | |_____^ - error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:42:5 + --> $DIR/fixable.rs:39:5 | LL | / if x { LL | | true @@ -29,9 +7,11 @@ LL | | } else { LL | | false LL | | }; | |_____^ help: you can reduce it to: `x` + | + = note: `-D clippy::needless-bool` implied by `-D warnings` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:47:5 + --> $DIR/fixable.rs:44:5 | LL | / if x { LL | | false @@ -41,7 +21,7 @@ LL | | }; | |_____^ help: you can reduce it to: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:52:5 + --> $DIR/fixable.rs:49:5 | LL | / if x && y { LL | | false @@ -50,28 +30,8 @@ LL | | true LL | | }; | |_____^ help: you can reduce it to: `!(x && y)` -error: this if-then-else expression will always return true - --> $DIR/needless_bool.rs:75:5 - | -LL | / if x { -LL | | return true; -LL | | } else { -LL | | return true; -LL | | }; - | |_____^ - -error: this if-then-else expression will always return false - --> $DIR/needless_bool.rs:84:5 - | -LL | / if x { -LL | | return false; -LL | | } else { -LL | | return false; -LL | | }; - | |_____^ - error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:93:5 + --> $DIR/fixable.rs:69:5 | LL | / if x { LL | | return true; @@ -81,17 +41,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:102:5 - | -LL | / if x && y { -LL | | return true; -LL | | } else { -LL | | return false; -LL | | }; - | |_____^ help: you can reduce it to: `return x && y` - -error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:111:5 + --> $DIR/fixable.rs:77:5 | LL | / if x { LL | | return false; @@ -101,7 +51,17 @@ LL | | }; | |_____^ help: you can reduce it to: `return !x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:120:5 + --> $DIR/fixable.rs:85:5 + | +LL | / if x && y { +LL | | return true; +LL | | } else { +LL | | return false; +LL | | }; + | |_____^ help: you can reduce it to: `return x && y` + +error: this if-then-else expression returns a bool literal + --> $DIR/fixable.rs:93:5 | LL | / if x && y { LL | | return false; @@ -111,7 +71,7 @@ LL | | }; | |_____^ help: you can reduce it to: `return !(x && y)` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:128:8 + --> $DIR/fixable.rs:101:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` @@ -119,25 +79,25 @@ LL | if x == true {}; = note: `-D clippy::bool-comparison` implied by `-D warnings` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:132:8 + --> $DIR/fixable.rs:105:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: equality checks against true are unnecessary - --> $DIR/needless_bool.rs:142:8 + --> $DIR/fixable.rs:115:8 | LL | if x == true {}; | ^^^^^^^^^ help: try simplifying it as shown: `x` error: equality checks against false can be replaced by a negation - --> $DIR/needless_bool.rs:143:8 + --> $DIR/fixable.rs:116:8 | LL | if x == false {}; | ^^^^^^^^^^ help: try simplifying it as shown: `!x` error: this if-then-else expression returns a bool literal - --> $DIR/needless_bool.rs:152:12 + --> $DIR/fixable.rs:125:12 | LL | } else if returns_bool() { | ____________^ @@ -147,5 +107,5 @@ LL | | true LL | | }; | |_____^ help: you can reduce it to: `{ !returns_bool() }` -error: aborting due to 16 previous errors +error: aborting due to 12 previous errors diff --git a/tests/ui/needless_bool/simple.rs b/tests/ui/needless_bool/simple.rs new file mode 100644 index 000000000..e9f1428fc --- /dev/null +++ b/tests/ui/needless_bool/simple.rs @@ -0,0 +1,46 @@ +#![warn(clippy::needless_bool)] +#![allow( + unused, + dead_code, + clippy::no_effect, + clippy::if_same_then_else, + clippy::needless_return +)] + +fn main() { + let x = true; + let y = false; + if x { + true + } else { + true + }; + if x { + false + } else { + false + }; + if x { + x + } else { + false + }; // would also be questionable, but we don't catch this yet + bool_ret(x); + bool_ret2(x); +} + +fn bool_ret(x: bool) -> bool { + if x { + return true; + } else { + return true; + }; +} + +fn bool_ret2(x: bool) -> bool { + if x { + return false; + } else { + return false; + }; +} diff --git a/tests/ui/needless_bool/simple.stderr b/tests/ui/needless_bool/simple.stderr new file mode 100644 index 000000000..c57a8a042 --- /dev/null +++ b/tests/ui/needless_bool/simple.stderr @@ -0,0 +1,44 @@ +error: this if-then-else expression will always return true + --> $DIR/simple.rs:13:5 + | +LL | / if x { +LL | | true +LL | | } else { +LL | | true +LL | | }; + | |_____^ + | + = note: `-D clippy::needless-bool` implied by `-D warnings` + +error: this if-then-else expression will always return false + --> $DIR/simple.rs:18:5 + | +LL | / if x { +LL | | false +LL | | } else { +LL | | false +LL | | }; + | |_____^ + +error: this if-then-else expression will always return true + --> $DIR/simple.rs:33:5 + | +LL | / if x { +LL | | return true; +LL | | } else { +LL | | return true; +LL | | }; + | |_____^ + +error: this if-then-else expression will always return false + --> $DIR/simple.rs:41:5 + | +LL | / if x { +LL | | return false; +LL | | } else { +LL | | return false; +LL | | }; + | |_____^ + +error: aborting due to 4 previous errors + From e4f8cd967235cd4d12e484901cb1174c58161a33 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Tue, 6 Aug 2019 19:20:41 +0700 Subject: [PATCH 119/133] Rustup https://github.com/rust-lang/rust/pull/59369 --- clippy_lints/src/consts.rs | 2 +- clippy_lints/src/indexing_slicing.rs | 2 +- clippy_lints/src/loops.rs | 6 +++--- clippy_lints/src/methods/mod.rs | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index 9d1cc110e..fe57c300a 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -230,7 +230,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { ExprKind::Tup(ref tup) => self.multi(tup).map(Constant::Tuple), ExprKind::Repeat(ref value, _) => { let n = match self.tables.expr_ty(e).sty { - ty::Array(_, n) => n.assert_usize(self.lcx.tcx).expect("array length"), + ty::Array(_, n) => n.eval_usize(self.lcx.tcx, self.lcx.param_env), _ => span_bug!(e.span, "typeck error"), }; self.expr(value).map(|v| Constant::Repeat(Box::new(v), n)) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 06e5458c1..02dafbe2e 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -94,7 +94,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IndexingSlicing { if let Some(range) = higher::range(cx, index) { // Ranged indexes, i.e., &x[n..m], &x[n..], &x[..n] and &x[..] if let ty::Array(_, s) = ty.sty { - let size: u128 = s.assert_usize(cx.tcx).unwrap().into(); + let size: u128 = s.eval_usize(cx.tcx, cx.param_env).into(); let const_range = to_const_range(cx, range, size); diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 7a5ac47b6..1f9120a53 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -1253,7 +1253,7 @@ fn is_end_eq_array_len<'tcx>( if let ExprKind::Lit(ref lit) = end.node; if let ast::LitKind::Int(end_int, _) = lit.node; if let ty::Array(_, arr_len_const) = indexed_ty.sty; - if let Some(arr_len) = arr_len_const.assert_usize(cx.tcx); + if let Some(arr_len) = arr_len_const.try_eval_usize(cx.tcx, cx.param_env); then { return match limits { ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), @@ -1375,7 +1375,7 @@ fn check_for_loop_arg(cx: &LateContext<'_, '_>, pat: &Pat, arg: &Expr, expr: &Ex match cx.tables.expr_ty(&args[0]).sty { // If the length is greater than 32 no traits are implemented for array and // therefore we cannot use `&`. - ty::Array(_, size) if size.assert_usize(cx.tcx).expect("array size") > 32 => (), + ty::Array(_, size) if size.eval_usize(cx.tcx, cx.param_env) > 32 => {}, _ => lint_iter_method(cx, args, arg, method_name), }; } else { @@ -1988,7 +1988,7 @@ fn is_ref_iterable_type(cx: &LateContext<'_, '_>, e: &Expr) -> bool { fn is_iterable_array<'tcx>(ty: Ty<'tcx>, cx: &LateContext<'_, 'tcx>) -> bool { // IntoIterator is currently only implemented for array sizes <= 32 in rustc match ty.sty { - ty::Array(_, n) => (0..=32).contains(&n.assert_usize(cx.tcx).expect("array length")), + ty::Array(_, n) => (0..=32).contains(&n.eval_usize(cx.tcx, cx.param_env)), _ => false, } } diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 5bb5ebc83..f40171aee 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -1825,7 +1825,7 @@ fn derefs_to_slice<'a, 'tcx>( ty::Slice(_) => true, ty::Adt(def, _) if def.is_box() => may_slice(cx, ty.boxed_ty()), ty::Adt(..) => match_type(cx, ty, &paths::VEC), - ty::Array(_, size) => size.assert_usize(cx.tcx).expect("array length") < 32, + ty::Array(_, size) => size.eval_usize(cx.tcx, cx.param_env) < 32, ty::Ref(_, inner, _) => may_slice(cx, inner), _ => false, } From 0a988c663080f5c59ccd5a1d1f4e7903495871fd Mon Sep 17 00:00:00 2001 From: Philipp Hansch Date: Tue, 6 Aug 2019 20:45:36 +0200 Subject: [PATCH 120/133] Don't emit enum_variant_names if remainder starts with a numeric As [per the reference](https://doc.rust-lang.org/reference/identifiers.html), identifiers must start with a letter. So we don't suggest a better variant naming in these cases. Fixes #739 --- clippy_lints/src/enum_variants.rs | 4 ++++ tests/ui/enum_variants.rs | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index 782d80a7b..1cc3bda3b 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -160,6 +160,7 @@ fn check_variant( let name = var2str(var); if partial_match(item_name, &name) == item_name_chars && name.chars().nth(item_name_chars).map_or(false, |c| !c.is_lowercase()) + && name.chars().nth(item_name_chars + 1).map_or(false, |c| !c.is_numeric()) { span_lint(cx, lint, var.span, "Variant name starts with the enum's name"); } @@ -178,6 +179,9 @@ fn check_variant( let pre_camel = camel_case::until(pre); pre = &pre[..pre_camel]; while let Some((next, last)) = name[pre.len()..].chars().zip(pre.chars().rev()).next() { + if next.is_numeric() { + return; + } if next.is_lowercase() { let last = pre.len() - last.len_utf8(); let last_camel = camel_case::until(&pre[..last]); diff --git a/tests/ui/enum_variants.rs b/tests/ui/enum_variants.rs index f3bbd3d96..01774a2a9 100644 --- a/tests/ui/enum_variants.rs +++ b/tests/ui/enum_variants.rs @@ -1,5 +1,5 @@ #![feature(non_ascii_idents)] -#![warn(clippy::all, clippy::pub_enum_variant_names)] +#![warn(clippy::enum_variant_names, clippy::pub_enum_variant_names)] #![allow(non_camel_case_types)] enum FakeCallType { @@ -120,4 +120,17 @@ enum N { Float, } +// should not lint +enum Peek { + Peek1, + Peek2, + Peek3, +} + +// should not lint +pub enum NetworkLayer { + Layer2, + Layer3, +} + fn main() {} From 4b2825cd3f3b5e991883eb567916e4596d3237cd Mon Sep 17 00:00:00 2001 From: Alex Touchet Date: Tue, 6 Aug 2019 13:09:26 -0700 Subject: [PATCH 121/133] Update Readme --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index ff64fc937..705966efa 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,7 @@ Table of contents: * [Usage instructions](#usage) * [Configuration](#configuration) +* [Contributing](#contributing) * [License](#license) ## Usage @@ -52,7 +53,7 @@ subcommand. #### Step 1: Install rustup -You can install [rustup](http://rustup.rs/) on supported platforms. This will help +You can install [rustup](https://rustup.rs/) on supported platforms. This will help us install Clippy and its dependencies. If you already have rustup installed, update to ensure you have the latest @@ -88,8 +89,7 @@ in your code, you can use: cargo run --bin cargo-clippy --manifest-path=path_to_clippys_Cargo.toml ``` -*[Note](https://github.com/rust-lang/rust-clippy/wiki#a-word-of-warning):* -Be sure that Clippy was compiled with the same version of rustc that cargo invokes here! +*Note:* Be sure that Clippy was compiled with the same version of rustc that cargo invokes here! ### Travis CI @@ -113,7 +113,7 @@ script: ``` If you are on nightly, It might happen that Clippy is not available for a certain nightly release. -In this case you can try to conditionally install Clippy from the git repo. +In this case you can try to conditionally install Clippy from the Git repo. ```yaml language: rust @@ -121,12 +121,12 @@ rust: - nightly before_script: - rustup component add clippy --toolchain=nightly || cargo install --git https://github.com/rust-lang/rust-clippy/ --force clippy - # etc + # etc. ``` Note that adding `-D warnings` will cause your build to fail if **any** warnings are found in your code. That includes warnings found by rustc (e.g. `dead_code`, etc.). If you want to avoid this and only cause -an error for clippy warnings, use `#![deny(clippy::all)]` in your code or `-D clippy::all` on the command +an error for Clippy warnings, use `#![deny(clippy::all)]` in your code or `-D clippy::all` on the command line. (You can swap `clippy::all` with the specific lint category you are targeting.) ## Configuration @@ -154,9 +154,9 @@ You can add options to your code to `allow`/`warn`/`deny` Clippy lints: `#![deny(clippy::pedantic)]`). Note that `clippy::pedantic` contains some very aggressive lints prone to false positives. -* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc) +* only some lints (`#![deny(clippy::single_match, clippy::box_vec)]`, etc.) -* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc +* `allow`/`warn`/`deny` can be limited to a single function or module using `#[allow(...)]`, etc. Note: `deny` produces errors instead of warnings. @@ -171,7 +171,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT Copyright 2014-2019 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license -, at your +[https://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)> or the MIT license +, at your option. All files in the project carrying such notice may not be copied, modified, or distributed except according to those terms. From 8dde4e5806869a0113042e9d1fb12a45ff55db7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 7 Aug 2019 16:24:14 +0200 Subject: [PATCH 122/133] README: mention that cargo fix has experimental support for applying some clippy lint suggestions via "cargo fix -Z unstable-options --clippy" --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index 705966efa..a4a194e5a 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,15 @@ Now you can run Clippy by invoking the following command: cargo clippy ``` +#### Automatically applying clippy suggestions + +Some Clippy lint suggestions can be automatically applied by `cargo fix`. +Note that this is still experimental and only supported on the nightly channel: + +```terminal +cargo fix -Z unstable-options --clippy +``` + ### Running Clippy from the command line without installing it To have cargo compile your crate with Clippy without Clippy installation From 39cdea6df47265c69f9b3aefa24eb37b14697c29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Wed, 7 Aug 2019 21:07:35 +0200 Subject: [PATCH 123/133] Update README.md (fix typo) Co-Authored-By: Philipp Hansch --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4a194e5a..15648b210 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Now you can run Clippy by invoking the following command: cargo clippy ``` -#### Automatically applying clippy suggestions +#### Automatically applying Clippy suggestions Some Clippy lint suggestions can be automatically applied by `cargo fix`. Note that this is still experimental and only supported on the nightly channel: From 0487b58f9afc249e850dc1bf2c8ae6d660237244 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 8 Aug 2019 19:33:34 +0700 Subject: [PATCH 124/133] Fix macro expansion in try_err lint --- clippy_lints/src/try_err.rs | 22 ++++++++++++++++++---- tests/ui/try_err.fixed | 19 +++++++++++++++++++ tests/ui/try_err.rs | 19 +++++++++++++++++++ tests/ui/try_err.stderr | 8 +++++++- 4 files changed, 63 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs index 7466221fb..3734b6098 100644 --- a/clippy_lints/src/try_err.rs +++ b/clippy_lints/src/try_err.rs @@ -1,10 +1,11 @@ -use crate::utils::{match_qpath, paths, snippet, span_lint_and_sugg}; +use crate::utils::{in_macro_or_desugar, match_qpath, paths, snippet, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::Ty; use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; +use syntax::source_map::Span; declare_clippy_lint! { /// **What it does:** Checks for usages of `Err(x)?`. @@ -67,10 +68,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr { then { let err_type = cx.tables.expr_ty(err_arg); - let suggestion = if err_type == return_type { - format!("return Err({})", snippet(cx, err_arg.span, "_")) + let span = if in_macro_or_desugar(err_arg.span) { + span_to_outer_expn(err_arg.span) } else { - format!("return Err({}.into())", snippet(cx, err_arg.span, "_")) + err_arg.span + }; + let suggestion = if err_type == return_type { + format!("return Err({})", snippet(cx, span, "_")) + } else { + format!("return Err({}.into())", snippet(cx, span, "_")) }; span_lint_and_sugg( @@ -87,6 +93,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr { } } +fn span_to_outer_expn(span: Span) -> Span { + let mut span = span; + while let Some(expr) = span.ctxt().outer_expn_info() { + span = expr.call_site; + } + span +} + // In order to determine whether to suggest `.into()` or not, we need to find the error type the // function returns. To do that, we look for the From::from call (see tree above), and capture // its output type. diff --git a/tests/ui/try_err.fixed b/tests/ui/try_err.fixed index 117300e84..a2087316e 100644 --- a/tests/ui/try_err.fixed +++ b/tests/ui/try_err.fixed @@ -78,3 +78,22 @@ fn main() { closure_matches_test().unwrap(); closure_into_test().unwrap(); } + +macro_rules! bar { + () => { + String::from("aasdfasdfasdfa") + }; +} + +macro_rules! foo { + () => { + bar!() + }; +} + +pub fn macro_inside(fail: bool) -> Result { + if fail { + return Err(foo!()); + } + Ok(0) +} diff --git a/tests/ui/try_err.rs b/tests/ui/try_err.rs index 828cf639a..5ef1b615d 100644 --- a/tests/ui/try_err.rs +++ b/tests/ui/try_err.rs @@ -78,3 +78,22 @@ fn main() { closure_matches_test().unwrap(); closure_into_test().unwrap(); } + +macro_rules! bar { + () => { + String::from("aasdfasdfasdfa") + }; +} + +macro_rules! foo { + () => { + bar!() + }; +} + +pub fn macro_inside(fail: bool) -> Result { + if fail { + Err(foo!())?; + } + Ok(0) +} diff --git a/tests/ui/try_err.stderr b/tests/ui/try_err.stderr index dbe05ce51..b915d6b60 100644 --- a/tests/ui/try_err.stderr +++ b/tests/ui/try_err.stderr @@ -28,5 +28,11 @@ error: returning an `Err(_)` with the `?` operator LL | Err(err)?; | ^^^^^^^^^ help: try this: `return Err(err.into())` -error: aborting due to 4 previous errors +error: returning an `Err(_)` with the `?` operator + --> $DIR/try_err.rs:96:9 + | +LL | Err(foo!())?; + | ^^^^^^^^^^^^ help: try this: `return Err(foo!())` + +error: aborting due to 5 previous errors From 90a7b6041319085634666d1ca1a28d79bd7ba6cd Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 8 Aug 2019 19:33:34 +0700 Subject: [PATCH 125/133] Use snippet_with_macro_callsite suggested by flip1995 --- clippy_lints/src/try_err.rs | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/clippy_lints/src/try_err.rs b/clippy_lints/src/try_err.rs index 3734b6098..7eba331ae 100644 --- a/clippy_lints/src/try_err.rs +++ b/clippy_lints/src/try_err.rs @@ -1,11 +1,10 @@ -use crate::utils::{in_macro_or_desugar, match_qpath, paths, snippet, span_lint_and_sugg}; +use crate::utils::{in_macro_or_desugar, match_qpath, paths, snippet, snippet_with_macro_callsite, span_lint_and_sugg}; use if_chain::if_chain; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::ty::Ty; use rustc::{declare_lint_pass, declare_tool_lint}; use rustc_errors::Applicability; -use syntax::source_map::Span; declare_clippy_lint! { /// **What it does:** Checks for usages of `Err(x)?`. @@ -68,15 +67,15 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr { then { let err_type = cx.tables.expr_ty(err_arg); - let span = if in_macro_or_desugar(err_arg.span) { - span_to_outer_expn(err_arg.span) + let origin_snippet = if in_macro_or_desugar(err_arg.span) { + snippet_with_macro_callsite(cx, err_arg.span, "_") } else { - err_arg.span + snippet(cx, err_arg.span, "_") }; let suggestion = if err_type == return_type { - format!("return Err({})", snippet(cx, span, "_")) + format!("return Err({})", origin_snippet) } else { - format!("return Err({}.into())", snippet(cx, span, "_")) + format!("return Err({}.into())", origin_snippet) }; span_lint_and_sugg( @@ -93,14 +92,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TryErr { } } -fn span_to_outer_expn(span: Span) -> Span { - let mut span = span; - while let Some(expr) = span.ctxt().outer_expn_info() { - span = expr.call_site; - } - span -} - // In order to determine whether to suggest `.into()` or not, we need to find the error type the // function returns. To do that, we look for the From::from call (see tree above), and capture // its output type. From 59a35874c165b47c20de6c6e4325bb5afbabc469 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 8 Aug 2019 21:28:40 +0700 Subject: [PATCH 126/133] Use source_callsite() instead of recursive outer_expn_info() --- clippy_lints/src/implicit_return.rs | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/clippy_lints/src/implicit_return.rs b/clippy_lints/src/implicit_return.rs index 4df9789f3..ceda65781 100644 --- a/clippy_lints/src/implicit_return.rs +++ b/clippy_lints/src/implicit_return.rs @@ -46,8 +46,8 @@ static LINT_BREAK: &str = "change `break` to `return` as shown"; static LINT_RETURN: &str = "add `return` as shown"; fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) { - let outer_span = span_to_outer_expn(outer_span); - let inner_span = span_to_outer_expn(inner_span); + let outer_span = outer_span.source_callsite(); + let inner_span = inner_span.source_callsite(); span_lint_and_then(cx, IMPLICIT_RETURN, outer_span, "missing return statement", |db| { if let Some(snippet) = snippet_opt(cx, inner_span) { @@ -61,14 +61,6 @@ fn lint(cx: &LateContext<'_, '_>, outer_span: Span, inner_span: Span, msg: &str) }); } -fn span_to_outer_expn(span: Span) -> Span { - if let Some(expr) = span.ctxt().outer_expn_info() { - span_to_outer_expn(expr.call_site) - } else { - span - } -} - fn expr_match(cx: &LateContext<'_, '_>, expr: &Expr) { match &expr.node { // loops could be using `break` instead of `return` From 5cad46d15a23a23f3075cdd285f5578b2da57e43 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Thu, 8 Aug 2019 21:37:19 +0700 Subject: [PATCH 127/133] template: Update how to format source code with ./util/dev --- .github/PULL_REQUEST_TEMPLATE | 6 ++++-- doc/adding_lints.md | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 5567b84b3..e4a9381f5 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -16,9 +16,11 @@ checked during review or continuous integration. - [ ] Followed [lint naming conventions][lint_naming] - [ ] Added passing UI tests (including committed `.stderr` file) - [ ] `cargo test` passes locally -- [ ] Executed `util/dev update_lints` +- [ ] Executed `./util/dev update_lints` - [ ] Added lint documentation -- [ ] Run `cargo fmt` +- [ ] Run `./util/dev fmt` + +[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints Note that you can skip the above if you are just opening a WIP PR in order to get feedback. diff --git a/doc/adding_lints.md b/doc/adding_lints.md index 0e73bdba1..ef09c4230 100644 --- a/doc/adding_lints.md +++ b/doc/adding_lints.md @@ -368,10 +368,12 @@ output in the `stdout` part. Before submitting your PR make sure you followed all of the basic requirements: + + - [ ] Followed [lint naming conventions][lint_naming] - [ ] Added passing UI tests (including committed `.stderr` file) - [ ] `cargo test` passes locally -- [ ] Executed `util/dev update_lints` +- [ ] Executed `./util/dev update_lints` - [ ] Added lint documentation - [ ] Run `./util/dev fmt` From b1b2245e28ff6c01438cf5b617b350af9b56ba5f Mon Sep 17 00:00:00 2001 From: Alex Touchet Date: Thu, 8 Aug 2019 19:59:22 -0700 Subject: [PATCH 128/133] Fix HTTPS in links --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 15648b210..389fe316a 100644 --- a/README.md +++ b/README.md @@ -180,7 +180,7 @@ If you want to contribute to Clippy, you can find more information in [CONTRIBUT Copyright 2014-2019 The Rust Project Developers Licensed under the Apache License, Version 2.0 or the MIT license -, at your +[https://www.apache.org/licenses/LICENSE-2.0](https://www.apache.org/licenses/LICENSE-2.0)> or the MIT license +, at your option. All files in the project carrying such notice may not be copied, modified, or distributed except according to those terms. From 30cbdc7491bbf20958291c88cc1651409ee0eac4 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 9 Aug 2019 10:45:49 +0700 Subject: [PATCH 129/133] Fix lint_single_char_pattern on raw string literal --- clippy_lints/src/methods/mod.rs | 13 ++++++++++--- tests/ui/single_char_pattern.fixed | 4 ++++ tests/ui/single_char_pattern.rs | 4 ++++ tests/ui/single_char_pattern.stderr | 14 +++++++++++++- 4 files changed, 31 insertions(+), 4 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f40171aee..19151a414 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -2329,13 +2329,20 @@ fn lint_chars_last_cmp_with_unwrap<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, info: & fn lint_single_char_pattern<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, _expr: &'tcx hir::Expr, arg: &'tcx hir::Expr) { if_chain! { if let hir::ExprKind::Lit(lit) = &arg.node; - if let ast::LitKind::Str(r, _) = lit.node; + if let ast::LitKind::Str(r, style) = lit.node; if r.as_str().len() == 1; then { let mut applicability = Applicability::MachineApplicable; let snip = snippet_with_applicability(cx, arg.span, "..", &mut applicability); - let c = &snip[1..snip.len() - 1]; - let hint = format!("'{}'", if c == "'" { "\\'" } else { c }); + let ch = if let ast::StrStyle::Raw(nhash) = style { + let nhash = nhash as usize; + // for raw string: r##"a"## + &snip[(nhash + 2)..(snip.len() - 1 - nhash)] + } else { + // for regular string: "a" + &snip[1..(snip.len() - 1)] + }; + let hint = format!("'{}'", if ch == "'" { "\\'" } else { ch }); span_lint_and_sugg( cx, SINGLE_CHAR_PATTERN, diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index d5b6d81d0..efbcf9666 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -53,4 +53,8 @@ fn main() { // Issue #3204 const S: &str = "#"; x.find(S); + + // Raw string + x.split('a'); + x.split('a'); } diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index 73f364854..e71c47512 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -53,4 +53,8 @@ fn main() { // Issue #3204 const S: &str = "#"; x.find(S); + + // Raw string + x.split(r"a"); + x.split(r#"a"#); } diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index d394c989c..98d430fe0 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -132,5 +132,17 @@ error: single-character string constant used as pattern LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` -error: aborting due to 22 previous errors +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:58:13 + | +LL | x.split(r"a"); + | ^^^^ help: try using a char instead: `'a'` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:59:13 + | +LL | x.split(r#"a"#); + | ^^^^^^ help: try using a char instead: `'a'` + +error: aborting due to 24 previous errors From c23a5c586f521c320033712e7245a37a0a728999 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 9 Aug 2019 12:33:07 +0700 Subject: [PATCH 130/133] Fix lint_cstring_as_ptr for expect --- clippy_lints/src/methods/mod.rs | 4 +++- tests/ui/cstring.rs | 1 + tests/ui/cstring.stderr | 15 ++++++++++++++- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index f40171aee..59a32e285 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -937,7 +937,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods { ["is_some", "position"] => lint_search_is_some(cx, expr, "position", arg_lists[1], arg_lists[0]), ["is_some", "rposition"] => lint_search_is_some(cx, expr, "rposition", arg_lists[1], arg_lists[0]), ["extend", ..] => lint_extend(cx, expr, arg_lists[0]), - ["as_ptr", "unwrap"] => lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]), + ["as_ptr", "unwrap"] | ["as_ptr", "expect"] => { + lint_cstring_as_ptr(cx, expr, &arg_lists[1][0], &arg_lists[0][0]) + }, ["nth", "iter"] => lint_iter_nth(cx, expr, arg_lists[1], false), ["nth", "iter_mut"] => lint_iter_nth(cx, expr, arg_lists[1], true), ["next", "skip"] => lint_iter_skip_next(cx, expr), diff --git a/tests/ui/cstring.rs b/tests/ui/cstring.rs index 6cc36518e..0d775d406 100644 --- a/tests/ui/cstring.rs +++ b/tests/ui/cstring.rs @@ -5,4 +5,5 @@ fn temporary_cstring() { use std::ffi::CString; CString::new("foo").unwrap().as_ptr(); + CString::new("foo").expect("dummy").as_ptr(); } diff --git a/tests/ui/cstring.stderr b/tests/ui/cstring.stderr index 8c86249dc..83f64ff3b 100644 --- a/tests/ui/cstring.stderr +++ b/tests/ui/cstring.stderr @@ -12,5 +12,18 @@ help: assign the `CString` to a variable to extend its lifetime LL | CString::new("foo").unwrap().as_ptr(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to previous error +error: you are getting the inner pointer of a temporary `CString` + --> $DIR/cstring.rs:8:5 + | +LL | CString::new("foo").expect("dummy").as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: that pointer will be invalid outside this expression +help: assign the `CString` to a variable to extend its lifetime + --> $DIR/cstring.rs:8:5 + | +LL | CString::new("foo").expect("dummy").as_ptr(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors From b825cddb6d7b2ec7dc479f200047ddf43a01fea0 Mon Sep 17 00:00:00 2001 From: Lzu Tao Date: Fri, 9 Aug 2019 10:45:49 +0700 Subject: [PATCH 131/133] Add more tests for raw string literal --- tests/ui/single_char_pattern.fixed | 3 +++ tests/ui/single_char_pattern.rs | 3 +++ tests/ui/single_char_pattern.stderr | 20 +++++++++++++++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed index efbcf9666..3871c4f22 100644 --- a/tests/ui/single_char_pattern.fixed +++ b/tests/ui/single_char_pattern.fixed @@ -57,4 +57,7 @@ fn main() { // Raw string x.split('a'); x.split('a'); + x.split('a'); + x.split('\''); + x.split('#'); } diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index e71c47512..32afe339c 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -57,4 +57,7 @@ fn main() { // Raw string x.split(r"a"); x.split(r#"a"#); + x.split(r###"a"###); + x.split(r###"'"###); + x.split(r###"#"###); } diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 98d430fe0..464ed3759 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -144,5 +144,23 @@ error: single-character string constant used as pattern LL | x.split(r#"a"#); | ^^^^^^ help: try using a char instead: `'a'` -error: aborting due to 24 previous errors +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:60:13 + | +LL | x.split(r###"a"###); + | ^^^^^^^^^^ help: try using a char instead: `'a'` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:61:13 + | +LL | x.split(r###"'"###); + | ^^^^^^^^^^ help: try using a char instead: `'/''` + +error: single-character string constant used as pattern + --> $DIR/single_char_pattern.rs:62:13 + | +LL | x.split(r###"#"###); + | ^^^^^^^^^^ help: try using a char instead: `'#'` + +error: aborting due to 27 previous errors From 2dcce60fdce11aa6793fb45c6b45816c797f0375 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Aug 2019 09:30:20 +0200 Subject: [PATCH 132/133] deprecate invalid_ref lint --- clippy_lints/src/deprecated_lints.rs | 9 +++++ clippy_lints/src/invalid_ref.rs | 55 --------------------------- clippy_lints/src/lib.rs | 4 -- clippy_lints/src/utils/paths.rs | 4 -- tests/ui/invalid_ref.rs | 56 ---------------------------- tests/ui/invalid_ref.stderr | 43 --------------------- 6 files changed, 9 insertions(+), 162 deletions(-) delete mode 100644 clippy_lints/src/invalid_ref.rs delete mode 100644 tests/ui/invalid_ref.rs delete mode 100644 tests/ui/invalid_ref.stderr diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 62cef7789..0140cf861 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -113,3 +113,12 @@ declare_deprecated_lint! { pub UNSAFE_VECTOR_INITIALIZATION, "the replacement suggested by this lint had substantially different behavior" } + +/// **What it does:** Nothing. This lint has been deprecated. +/// +/// **Deprecation reason:** This lint has been superseded by the warn-by-default +/// `invalid_value` rustc lint. +declare_clippy_lint! { + pub INVALID_REF, + "superseded by rustc lint `invalid_value`" +} diff --git a/clippy_lints/src/invalid_ref.rs b/clippy_lints/src/invalid_ref.rs deleted file mode 100644 index 8f9ccaea2..000000000 --- a/clippy_lints/src/invalid_ref.rs +++ /dev/null @@ -1,55 +0,0 @@ -use crate::utils::{match_def_path, paths, span_help_and_lint}; -use if_chain::if_chain; -use rustc::hir::*; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; -use rustc::ty; -use rustc::{declare_lint_pass, declare_tool_lint}; - -declare_clippy_lint! { - /// **What it does:** Checks for creation of references to zeroed or uninitialized memory. - /// - /// **Why is this bad?** Creation of null references is undefined behavior. - /// - /// **Known problems:** None. - /// - /// **Example:** - /// ```no_run - /// let bad_ref: &usize = unsafe { std::mem::zeroed() }; - /// ``` - pub INVALID_REF, - correctness, - "creation of invalid reference" -} - -const ZERO_REF_SUMMARY: &str = "reference to zeroed memory"; -const UNINIT_REF_SUMMARY: &str = "reference to uninitialized memory"; -const HELP: &str = "Creation of a null reference is undefined behavior; \ - see https://doc.rust-lang.org/reference/behavior-considered-undefined.html"; - -declare_lint_pass!(InvalidRef => [INVALID_REF]); - -impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidRef { - fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if_chain! { - if let ExprKind::Call(ref path, ref args) = expr.node; - if let ExprKind::Path(ref qpath) = path.node; - if args.len() == 0; - if let ty::Ref(..) = cx.tables.expr_ty(expr).sty; - if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id(); - then { - let msg = if match_def_path(cx, def_id, &paths::MEM_ZEROED) | - match_def_path(cx, def_id, &paths::INIT) - { - ZERO_REF_SUMMARY - } else if match_def_path(cx, def_id, &paths::MEM_UNINIT) | - match_def_path(cx, def_id, &paths::UNINIT) - { - UNINIT_REF_SUMMARY - } else { - return; - }; - span_help_and_lint(cx, INVALID_REF, expr.span, msg, HELP); - } - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 258be38e4..1ab943c59 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -200,7 +200,6 @@ pub mod inherent_to_string; pub mod inline_fn_without_body; pub mod int_plus_one; pub mod integer_division; -pub mod invalid_ref; pub mod items_after_statements; pub mod large_enum_variant; pub mod len_zero; @@ -558,7 +557,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box bytecount::ByteCount); reg.register_late_lint_pass(box infinite_iter::InfiniteIter); reg.register_late_lint_pass(box inline_fn_without_body::InlineFnWithoutBody); - reg.register_late_lint_pass(box invalid_ref::InvalidRef); reg.register_late_lint_pass(box identity_conversion::IdentityConversion::default()); reg.register_late_lint_pass(box types::ImplicitHasher); reg.register_early_lint_pass(box redundant_static_lifetimes::RedundantStaticLifetimes); @@ -736,7 +734,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, int_plus_one::INT_PLUS_ONE, - invalid_ref::INVALID_REF, large_enum_variant::LARGE_ENUM_VARIANT, len_zero::LEN_WITHOUT_IS_EMPTY, len_zero::LEN_ZERO, @@ -1094,7 +1091,6 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { infinite_iter::INFINITE_ITER, inherent_to_string::INHERENT_TO_STRING_SHADOW_DISPLAY, inline_fn_without_body::INLINE_FN_WITHOUT_BODY, - invalid_ref::INVALID_REF, literal_representation::MISTYPED_LITERAL_SUFFIXES, loops::FOR_LOOP_OVER_OPTION, loops::FOR_LOOP_OVER_RESULT, diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index e08ff3e97..62b22afff 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -37,7 +37,6 @@ pub const HASHMAP_ENTRY: [&str; 5] = ["std", "collections", "hash", "map", "Entr pub const HASHSET: [&str; 5] = ["std", "collections", "hash", "set", "HashSet"]; pub const INDEX: [&str; 3] = ["core", "ops", "Index"]; pub const INDEX_MUT: [&str; 3] = ["core", "ops", "IndexMut"]; -pub const INIT: [&str; 4] = ["core", "intrinsics", "", "init"]; pub const INTO: [&str; 3] = ["core", "convert", "Into"]; pub const INTO_ITERATOR: [&str; 5] = ["core", "iter", "traits", "collect", "IntoIterator"]; pub const IO_READ: [&str; 3] = ["std", "io", "Read"]; @@ -50,8 +49,6 @@ pub const LINT_PASS: [&str; 3] = ["rustc", "lint", "LintPass"]; pub const MEM_DISCRIMINANT: [&str; 3] = ["core", "mem", "discriminant"]; pub const MEM_FORGET: [&str; 3] = ["core", "mem", "forget"]; pub const MEM_REPLACE: [&str; 3] = ["core", "mem", "replace"]; -pub const MEM_UNINIT: [&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 OPEN_OPTIONS: [&str; 3] = ["std", "fs", "OpenOptions"]; pub const OPS_MODULE: [&str; 2] = ["core", "ops"]; @@ -109,7 +106,6 @@ pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_stri pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"]; pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"]; pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"]; -pub const UNINIT: [&str; 4] = ["core", "intrinsics", "", "uninit"]; pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"]; pub const VEC_DEQUE: [&str; 4] = ["alloc", "collections", "vec_deque", "VecDeque"]; pub const VEC_FROM_ELEM: [&str; 3] = ["alloc", "vec", "from_elem"]; diff --git a/tests/ui/invalid_ref.rs b/tests/ui/invalid_ref.rs deleted file mode 100644 index d59bd51bb..000000000 --- a/tests/ui/invalid_ref.rs +++ /dev/null @@ -1,56 +0,0 @@ -#![allow(deprecated, unused)] -#![feature(core_intrinsics)] - -extern crate core; -use std::intrinsics::init; - -fn main() { - let x = 1; - unsafe { - ref_to_zeroed_std(&x); - ref_to_zeroed_core(&x); - ref_to_zeroed_intr(&x); - ref_to_uninit_std(&x); - ref_to_uninit_core(&x); - some_ref(); - std_zeroed_no_ref(); - core_zeroed_no_ref(); - intr_init_no_ref(); - } -} - -unsafe fn ref_to_zeroed_std(t: &T) { - let ref_zero: &T = std::mem::zeroed(); // warning -} - -unsafe fn ref_to_zeroed_core(t: &T) { - let ref_zero: &T = core::mem::zeroed(); // warning -} - -unsafe fn ref_to_zeroed_intr(t: &T) { - let ref_zero: &T = std::intrinsics::init(); // warning -} - -unsafe fn ref_to_uninit_std(t: &T) { - let ref_uninit: &T = std::mem::uninitialized(); // warning -} - -unsafe fn ref_to_uninit_core(t: &T) { - let ref_uninit: &T = core::mem::uninitialized(); // warning -} - -fn some_ref() { - let some_ref = &1; -} - -unsafe fn std_zeroed_no_ref() { - let mem_zero: usize = std::mem::zeroed(); // no warning -} - -unsafe fn core_zeroed_no_ref() { - let mem_zero: usize = core::mem::zeroed(); // no warning -} - -unsafe fn intr_init_no_ref() { - let mem_zero: usize = std::intrinsics::init(); // no warning -} diff --git a/tests/ui/invalid_ref.stderr b/tests/ui/invalid_ref.stderr deleted file mode 100644 index aeef3892d..000000000 --- a/tests/ui/invalid_ref.stderr +++ /dev/null @@ -1,43 +0,0 @@ -error: reference to zeroed memory - --> $DIR/invalid_ref.rs:23:24 - | -LL | let ref_zero: &T = std::mem::zeroed(); // warning - | ^^^^^^^^^^^^^^^^^^ - | - = note: `#[deny(clippy::invalid_ref)]` on by default - = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html - -error: reference to zeroed memory - --> $DIR/invalid_ref.rs:27:24 - | -LL | let ref_zero: &T = core::mem::zeroed(); // warning - | ^^^^^^^^^^^^^^^^^^^ - | - = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html - -error: reference to zeroed memory - --> $DIR/invalid_ref.rs:31:24 - | -LL | let ref_zero: &T = std::intrinsics::init(); // warning - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html - -error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:35:26 - | -LL | let ref_uninit: &T = std::mem::uninitialized(); // warning - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html - -error: reference to uninitialized memory - --> $DIR/invalid_ref.rs:39:26 - | -LL | let ref_uninit: &T = core::mem::uninitialized(); // warning - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: Creation of a null reference is undefined behavior; see https://doc.rust-lang.org/reference/behavior-considered-undefined.html - -error: aborting due to 5 previous errors - From 40fea7a9e0d35141ed7cfbee9a820c01c0ad0c6c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 11 Aug 2019 11:02:25 +0200 Subject: [PATCH 133/133] update_lints --- CHANGELOG.md | 1 - README.md | 2 +- src/lintlist/mod.rs | 9 +-------- 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e4a1a602c..db838a3e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -982,7 +982,6 @@ Released 2018-09-13 [`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref -[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons [`items_after_statements`]: https://rust-lang.github.io/rust-clippy/master/index.html#items_after_statements diff --git a/README.md b/README.md index 389fe316a..8bcfd8a84 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code. -[There are 310 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html) +[There are 309 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: diff --git a/src/lintlist/mod.rs b/src/lintlist/mod.rs index 93712e8eb..b41ed4a59 100644 --- a/src/lintlist/mod.rs +++ b/src/lintlist/mod.rs @@ -6,7 +6,7 @@ pub use lint::Lint; pub use lint::LINT_LEVELS; // begin lint list, do not remove this comment, it’s used in `update_lints` -pub const ALL_LINTS: [Lint; 310] = [ +pub const ALL_LINTS: [Lint; 309] = [ Lint { name: "absurd_extreme_comparisons", group: "correctness", @@ -791,13 +791,6 @@ pub const ALL_LINTS: [Lint; 310] = [ deprecation: None, module: "methods", }, - Lint { - name: "invalid_ref", - group: "correctness", - desc: "creation of invalid reference", - deprecation: None, - module: "invalid_ref", - }, Lint { name: "invalid_regex", group: "correctness",