diff --git a/.travis.yml b/.travis.yml index 03cd66749d5a..ff1fc1a3cedc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -65,9 +65,8 @@ matrix: if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=Geal/nom if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - # FIXME blocked on https://github.com/rust-lang/rust-clippy/issues/4727 - #- env: INTEGRATION=rust-lang/rustfmt - # if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) + - env: INTEGRATION=rust-lang/rustfmt + if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=hyperium/hyper if: repo =~ /^rust-lang\/rust-clippy$/ AND branch IN (auto, try) - env: INTEGRATION=bluss/rust-itertools @@ -125,7 +124,7 @@ before_script: script: - | if [[ -n ${INTEGRATION} ]]; then - ./ci/integration-tests.sh && sleep 5 + cargo test --test integration --features integration && sleep 5 else ./ci/base-tests.sh && sleep 5 fi diff --git a/Cargo.toml b/Cargo.toml index 300e40d4e358..52d73692f178 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,10 +38,13 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } regex = "1" semver = "0.9" rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} +git2 = { version = "0.10", optional = true } +tempfile = { version = "3.1.0", optional = true } [dev-dependencies] cargo_metadata = "0.9.0" -compiletest_rs = { version = "0.3.24", features = ["tmp"] } +compiletest_rs = { version = "0.4.0", features = ["tmp"] } +tester = "0.7" lazy_static = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } serde = { version = "1.0", features = ["derive"] } @@ -58,3 +61,4 @@ rustc_tools_util = { version = "0.2.0", path = "rustc_tools_util"} [features] deny-warnings = [] debugging = [] +integration = ["git2", "tempfile"] diff --git a/ci/integration-tests.sh b/ci/integration-tests.sh deleted file mode 100755 index f6540769bb03..000000000000 --- a/ci/integration-tests.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env bash -set -ex - -if [[ -z "$INTEGRATION" ]]; then - exit 0 -fi - -CARGO_TARGET_DIR=$(pwd)/target/ -export CARGO_TARGET_DIR - -rm ~/.cargo/bin/cargo-clippy -cargo install --force --debug --path . - -echo "Running integration test for crate ${INTEGRATION}" - -git clone --depth=1 "https://github.com/${INTEGRATION}.git" checkout -cd checkout - -# run clippy on a project, try to be verbose and trigger as many warnings -# as possible for greater coverage -# NOTE: we use `tee` to print any warnings and errors to stdout -# to avoid build timeout in Travis -RUST_BACKTRACE=full \ -cargo clippy \ - --all-targets \ - --all-features \ - -- \ - --cap-lints warn \ - -W clippy::pedantic \ - -W clippy::nursery \ - 2>&1 | tee clippy_output - -cargo uninstall clippy - -if grep -q "internal compiler error\|query stack during panic\|E0463" clippy_output; then - exit 1 -fi diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index c22693aee3b5..52aca5000c1c 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -2,7 +2,6 @@ #![feature(box_syntax)] #![feature(box_patterns)] -#![feature(never_type)] #![feature(rustc_private)] #![feature(slice_patterns)] #![feature(stmt_expr_attributes)] diff --git a/clippy_lints/src/loops.rs b/clippy_lints/src/loops.rs index 75d540b38e5d..31d97d790cba 100644 --- a/clippy_lints/src/loops.rs +++ b/clippy_lints/src/loops.rs @@ -720,7 +720,7 @@ fn never_loop_expr(expr: &Expr, main_loop_id: HirId) -> NeverLoopResult { ExprKind::Struct(_, _, None) | ExprKind::Yield(_, _) | ExprKind::Closure(_, _, _, _, _) - | ExprKind::InlineAsm(_, _, _) + | ExprKind::InlineAsm(_) | ExprKind::Path(_) | ExprKind::Lit(_) | ExprKind::Err => NeverLoopResult::Otherwise, diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index 71cf6c03e5ca..81a05e50d33b 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -458,8 +458,8 @@ impl<'tcx> Visitor<'tcx> for PrintVisitor { println!("Ret(None) = {};", current); } }, - ExprKind::InlineAsm(_, ref _input, ref _output) => { - println!("InlineAsm(_, ref input, ref output) = {};", current); + ExprKind::InlineAsm(_) => { + println!("InlineAsm(_) = {};", current); println!(" // unimplemented: `ExprKind::InlineAsm` is not further destructured at the moment"); }, ExprKind::Struct(ref path, ref fields, ref opt_base) => { diff --git a/clippy_lints/src/utils/inspector.rs b/clippy_lints/src/utils/inspector.rs index 846e47cee374..9376b923bd47 100644 --- a/clippy_lints/src/utils/inspector.rs +++ b/clippy_lints/src/utils/inspector.rs @@ -282,14 +282,16 @@ fn print_expr(cx: &LateContext<'_, '_>, expr: &hir::Expr, indent: usize) { print_expr(cx, e, indent + 1); } }, - hir::ExprKind::InlineAsm(_, ref input, ref output) => { + hir::ExprKind::InlineAsm(ref asm) => { + let inputs = &asm.inputs_exprs; + let outputs = &asm.outputs_exprs; println!("{}InlineAsm", ind); println!("{}inputs:", ind); - for e in input { + for e in inputs.iter() { print_expr(cx, e, indent + 1); } println!("{}outputs:", ind); - for e in output { + for e in outputs.iter() { print_expr(cx, e, indent + 1); } }, diff --git a/clippy_lints/src/write.rs b/clippy_lints/src/write.rs index b8773b47a99d..07e8fb34c72f 100644 --- a/clippy_lints/src/write.rs +++ b/clippy_lints/src/write.rs @@ -8,6 +8,7 @@ use rustc_errors::Applicability; use rustc_lexer::unescape::{self, EscapeError}; use rustc_parse::parser; use syntax::ast::*; +use syntax::symbol::Symbol; use syntax::token; use syntax::tokenstream::TokenStream; use syntax_pos::{BytePos, Span}; @@ -190,7 +191,7 @@ impl EarlyLintPass for Write { if mac.path == sym!(println) { span_lint(cx, PRINT_STDOUT, mac.span, "use of `println!`"); if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, false) { - if fmt_str.contents.is_empty() { + if fmt_str.symbol == Symbol::intern("") { span_lint_and_sugg( cx, PRINTLN_EMPTY_STRING, @@ -205,7 +206,7 @@ impl EarlyLintPass for Write { } else if mac.path == sym!(print) { span_lint(cx, PRINT_STDOUT, mac.span, "use of `print!`"); if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, false) { - if check_newlines(&fmt_str.contents, fmt_str.style) { + if check_newlines(&fmt_str) { span_lint_and_then( cx, PRINT_WITH_NEWLINE, @@ -216,7 +217,7 @@ impl EarlyLintPass for Write { "use `println!` instead", vec![ (mac.path.span, String::from("println")), - (fmt_str.newline_span(), String::new()), + (newline_span(&fmt_str), String::new()), ], Applicability::MachineApplicable, ); @@ -226,7 +227,7 @@ impl EarlyLintPass for Write { } } else if mac.path == sym!(write) { if let (Some(fmt_str), _) = check_tts(cx, &mac.tts, true) { - if check_newlines(&fmt_str.contents, fmt_str.style) { + if check_newlines(&fmt_str) { span_lint_and_then( cx, WRITE_WITH_NEWLINE, @@ -237,7 +238,7 @@ impl EarlyLintPass for Write { "use `writeln!()` instead", vec![ (mac.path.span, String::from("writeln")), - (fmt_str.newline_span(), String::new()), + (newline_span(&fmt_str), String::new()), ], Applicability::MachineApplicable, ); @@ -247,7 +248,7 @@ impl EarlyLintPass for Write { } } else if mac.path == sym!(writeln) { if let (Some(fmt_str), expr) = check_tts(cx, &mac.tts, true) { - if fmt_str.contents.is_empty() { + if fmt_str.symbol == Symbol::intern("") { let mut applicability = Applicability::MachineApplicable; let suggestion = expr.map_or_else( move || { @@ -272,37 +273,27 @@ impl EarlyLintPass for Write { } } -/// The arguments of a `print[ln]!` or `write[ln]!` invocation. -struct FmtStr { - /// The contents of the format string (inside the quotes). - contents: String, - style: StrStyle, - /// The span of the format string, including quotes, the raw marker, and any raw hashes. - span: Span, -} - -impl FmtStr { - /// Given a format string that ends in a newline and its span, calculates the span of the - /// newline. - fn newline_span(&self) -> Span { - let sp = self.span; +/// Given a format string that ends in a newline and its span, calculates the span of the +/// newline. +fn newline_span(fmtstr: &StrLit) -> Span { + let sp = fmtstr.span; + let contents = &fmtstr.symbol.as_str(); - let newline_sp_hi = sp.hi() - - match self.style { - StrStyle::Cooked => BytePos(1), - StrStyle::Raw(hashes) => BytePos((1 + hashes).into()), - }; - - let newline_sp_len = if self.contents.ends_with('\n') { - BytePos(1) - } else if self.contents.ends_with(r"\n") { - BytePos(2) - } else { - panic!("expected format string to contain a newline"); + let newline_sp_hi = sp.hi() + - match fmtstr.style { + StrStyle::Cooked => BytePos(1), + StrStyle::Raw(hashes) => BytePos((1 + hashes).into()), }; - sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi) - } + let newline_sp_len = if contents.ends_with('\n') { + BytePos(1) + } else if contents.ends_with(r"\n") { + BytePos(2) + } else { + panic!("expected format string to contain a newline"); + }; + + sp.with_lo(newline_sp_hi - newline_sp_len).with_hi(newline_sp_hi) } /// Checks the arguments of `print[ln]!` and `write[ln]!` calls. It will return a tuple of two @@ -325,7 +316,7 @@ impl FmtStr { /// (Some("string to write: {}"), Some(buf)) /// ``` #[allow(clippy::too_many_lines)] -fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option, Option) { +fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (Option, Option) { use fmt_macros::*; let tts = tts.clone(); @@ -342,12 +333,11 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O } } - let (fmtstr, fmtstyle) = match parser.parse_str().map_err(|mut err| err.cancel()) { - Ok((fmtstr, fmtstyle)) => (fmtstr.to_string(), fmtstyle), + let fmtstr = match parser.parse_str_lit() { + Ok(fmtstr) => fmtstr, Err(_) => return (None, expr), }; - let fmtspan = parser.prev_span; - let tmp = fmtstr.clone(); + let tmp = fmtstr.symbol.as_str(); let mut args = vec![]; let mut fmt_parser = Parser::new(&tmp, None, Vec::new(), false); while let Some(piece) = fmt_parser.next() { @@ -377,26 +367,12 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O ty_span: None, }; if !parser.eat(&token::Comma) { - return ( - Some(FmtStr { - contents: fmtstr, - style: fmtstyle, - span: fmtspan, - }), - expr, - ); + return (Some(fmtstr), expr); } let token_expr = if let Ok(expr) = parser.parse_expr().map_err(|mut err| err.cancel()) { expr } else { - return ( - Some(FmtStr { - contents: fmtstr, - style: fmtstyle, - span: fmtspan, - }), - None, - ); + return (Some(fmtstr), None); }; match &token_expr.kind { ExprKind::Lit(_) => { @@ -448,11 +424,13 @@ fn check_tts<'a>(cx: &EarlyContext<'a>, tts: &TokenStream, is_write: bool) -> (O /// Checks if the format string contains a single newline that terminates it. /// /// Literal and escaped newlines are both checked (only literal for raw strings). -fn check_newlines(contents: &str, style: StrStyle) -> bool { +fn check_newlines(fmtstr: &StrLit) -> bool { let mut has_internal_newline = false; let mut last_was_cr = false; let mut should_lint = false; + let contents = &fmtstr.symbol.as_str(); + let mut cb = |r: Range, c: Result| { let c = c.unwrap(); @@ -466,7 +444,7 @@ fn check_newlines(contents: &str, style: StrStyle) -> bool { } }; - match style { + match fmtstr.style { StrStyle::Cooked => unescape::unescape_str(contents, &mut cb), StrStyle::Raw(_) => unescape::unescape_raw_str(contents, &mut cb), } diff --git a/src/driver.rs b/src/driver.rs index 9995c3fb1cec..2a4448cc0ec4 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -75,6 +75,12 @@ impl rustc_driver::Callbacks for ClippyCallbacks { clippy_lints::register_pre_expansion_lints(&mut lint_store, &conf); clippy_lints::register_renamed(&mut lint_store); })); + + // FIXME: #4825; This is required, because Clippy lints that are based on MIR have to be + // run on the unoptimized MIR. On the other hand this results in some false negatives. If + // MIR passes can be enabled / disabled separately, we should figure out, what passes to + // use for Clippy. + config.opts.debugging_opts.mir_opt_level = 0; } } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 9c34d490b539..43139e95666e 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -1,7 +1,7 @@ #![feature(test)] use compiletest_rs as compiletest; -extern crate test; +extern crate tester as test; use std::env::{set_var, var}; use std::ffi::OsStr; diff --git a/tests/integration.rs b/tests/integration.rs new file mode 100644 index 000000000000..21098ffdf63c --- /dev/null +++ b/tests/integration.rs @@ -0,0 +1,70 @@ +#![cfg(feature = "integration")] + +use git2::Repository; +use tempfile; + +use std::env; +use std::process::Command; + +#[cfg_attr(feature = "integration", test)] +fn integration_test() { + let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set"); + let repo_url = format!("https://github.com/{}", repo_name); + let crate_name = repo_name + .split('/') + .nth(1) + .expect("repo name should have format `/`"); + + let repo_dir = tempfile::tempdir() + .expect("couldn't create temp dir") + .path() + .join(crate_name); + + Repository::clone(&repo_url, &repo_dir).expect("clone of repo failed"); + + let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let target_dir = std::path::Path::new(&root_dir).join("target"); + let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy"); + + let output = Command::new(clippy_binary) + .current_dir(repo_dir) + .env("RUST_BACKTRACE", "full") + .env("CARGO_TARGET_DIR", target_dir) + .args(&[ + "clippy", + "--all-targets", + "--all-features", + "--", + "--cap-lints", + "warn", + "-Wclippy::pedantic", + "-Wclippy::nursery", + ]) + .output() + .expect("unable to run clippy"); + + let stderr = String::from_utf8_lossy(&output.stderr); + if stderr.contains("internal compiler error") { + let backtrace_start = stderr + .find("thread 'rustc' panicked at") + .expect("start of backtrace not found"); + let backtrace_end = stderr + .rfind("error: internal compiler error") + .expect("end of backtrace not found"); + + panic!( + "internal compiler error\nBacktrace:\n\n{}", + &stderr[backtrace_start..backtrace_end] + ); + } else if stderr.contains("query stack during panic") { + panic!("query stack during panic in the output"); + } else if stderr.contains("E0463") { + panic!("error: E0463"); + } + + match output.status.code() { + Some(code) if code != 0 => eprintln!("Compilation failed. Exit code: {}", code), + Some(0) => eprintln!("Compilation successful"), + None => panic!("Process terminated by signal"), + } +} diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 42bde5e07f36..b6a4adde8488 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -16,8 +16,8 @@ LL | fn foo(a: u32) -> u32 { LL | 42 | ^^ expected type parameter `u32`, found integer | - = note: expected type `u32` - found type `{integer}` + = note: expected type parameter `u32` + found type `{integer}` = help: type parameters must be constrained to match other types = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters diff --git a/tests/ui/diverging_sub_expression.rs b/tests/ui/diverging_sub_expression.rs index 746afa475039..4df241c9fc39 100644 --- a/tests/ui/diverging_sub_expression.rs +++ b/tests/ui/diverging_sub_expression.rs @@ -1,4 +1,3 @@ -#![feature(never_type)] #![warn(clippy::diverging_sub_expression)] #![allow(clippy::match_same_arms, clippy::logic_bug)] diff --git a/tests/ui/diverging_sub_expression.stderr b/tests/ui/diverging_sub_expression.stderr index 70ff3cdd0462..170e7d92de4a 100644 --- a/tests/ui/diverging_sub_expression.stderr +++ b/tests/ui/diverging_sub_expression.stderr @@ -1,5 +1,5 @@ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:21:10 + --> $DIR/diverging_sub_expression.rs:20:10 | LL | b || diverge(); | ^^^^^^^^^ @@ -7,31 +7,31 @@ LL | b || diverge(); = note: `-D clippy::diverging-sub-expression` implied by `-D warnings` error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:22:10 + --> $DIR/diverging_sub_expression.rs:21:10 | LL | b || A.foo(); | ^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:31:26 + --> $DIR/diverging_sub_expression.rs:30:26 | LL | 6 => true || return, | ^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:32:26 + --> $DIR/diverging_sub_expression.rs:31:26 | LL | 7 => true || continue, | ^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:35:26 + --> $DIR/diverging_sub_expression.rs:34:26 | LL | 3 => true || diverge(), | ^^^^^^^^^ error: sub-expression diverges - --> $DIR/diverging_sub_expression.rs:40:26 + --> $DIR/diverging_sub_expression.rs:39:26 | LL | _ => true || break, | ^^^^^ diff --git a/tests/ui/indexing_slicing.stderr b/tests/ui/indexing_slicing.stderr index b2840f7b5ccc..0744676d1399 100644 --- a/tests/ui/indexing_slicing.stderr +++ b/tests/ui/indexing_slicing.stderr @@ -1,23 +1,3 @@ -error: index out of bounds: the len is 4 but the index is 4 - --> $DIR/indexing_slicing.rs:18:5 - | -LL | x[4]; // Ok, let rustc's `const_err` lint handle `usize` indexing on arrays. - | ^^^^ - | - = 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 - | -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: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:13:5 | @@ -209,5 +189,5 @@ LL | v[M]; | = help: Consider using `.get(n)` or `.get_mut(n)` instead -error: aborting due to 27 previous errors +error: aborting due to 24 previous errors diff --git a/tests/ui/infallible_destructuring_match.fixed b/tests/ui/infallible_destructuring_match.fixed index f16f0fd00197..a92063bf8071 100644 --- a/tests/ui/infallible_destructuring_match.fixed +++ b/tests/ui/infallible_destructuring_match.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![feature(exhaustive_patterns, never_type)] +#![feature(exhaustive_patterns)] #![allow(dead_code, unreachable_code, unused_variables)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/infallible_destructuring_match.rs b/tests/ui/infallible_destructuring_match.rs index a4823ad60ad3..4dd9e837b6d8 100644 --- a/tests/ui/infallible_destructuring_match.rs +++ b/tests/ui/infallible_destructuring_match.rs @@ -1,5 +1,5 @@ // run-rustfix -#![feature(exhaustive_patterns, never_type)] +#![feature(exhaustive_patterns)] #![allow(dead_code, unreachable_code, unused_variables)] #![allow(clippy::let_and_return)] diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index ff74857530fc..bac05c0931c1 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -1,5 +1,4 @@ // run-rustfix -#![feature(never_type)] #![allow(unused_mut)] #![warn(clippy::must_use_candidate)] use std::rc::Rc; diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 29c0752994af..df265b6eac9f 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -1,5 +1,4 @@ // run-rustfix -#![feature(never_type)] #![allow(unused_mut)] #![warn(clippy::must_use_candidate)] use std::rc::Rc; diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index 0fa3849d03bf..2f33f5df5f40 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -1,5 +1,5 @@ error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:12:1 + --> $DIR/must_use_candidates.rs:11:1 | LL | pub fn pure(i: u8) -> u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn pure(i: u8) -> u8` @@ -7,25 +7,25 @@ LL | pub fn pure(i: u8) -> u8 { = note: `-D clippy::must-use-candidate` implied by `-D warnings` error: this method could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:17:5 + --> $DIR/must_use_candidates.rs:16:5 | LL | pub fn inherent_pure(&self) -> u8 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn inherent_pure(&self) -> u8` error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:48:1 + --> $DIR/must_use_candidates.rs:47:1 | LL | pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn with_marker(_d: std::marker::PhantomData<&mut u32>) -> bool` error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:60:1 + --> $DIR/must_use_candidates.rs:59:1 | LL | pub fn rcd(_x: Rc) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn rcd(_x: Rc) -> bool` error: this function could have a `#[must_use]` attribute - --> $DIR/must_use_candidates.rs:68:1 + --> $DIR/must_use_candidates.rs:67:1 | LL | pub fn arcd(_x: Arc) -> bool { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add the attribute: `#[must_use] pub fn arcd(_x: Arc) -> bool` diff --git a/tests/ui/redundant_clone.fixed b/tests/ui/redundant_clone.fixed index 614a9bf4d900..e5e706e8483e 100644 --- a/tests/ui/redundant_clone.fixed +++ b/tests/ui/redundant_clone.fixed @@ -1,5 +1,6 @@ // run-rustfix // rustfix-only-machine-applicable + use std::ffi::OsString; use std::path::Path; @@ -17,11 +18,11 @@ fn main() { let _s = Path::new("/a/b/").join("c"); - let _s = Path::new("/a/b/").join("c"); + let _s = Path::new("/a/b/").join("c").to_path_buf(); let _s = OsString::new(); - let _s = OsString::new(); + let _s = OsString::new().to_os_string(); // Check that lint level works #[allow(clippy::redundant_clone)] @@ -46,6 +47,7 @@ fn main() { let _ = Some(String::new()).unwrap_or_else(|| x.0.clone()); // ok; closure borrows `x` with_branch(Alpha, true); + cannot_double_move(Alpha); cannot_move_from_type_with_drop(); borrower_propagation(); } @@ -60,6 +62,10 @@ fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) { } } +fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) { + (a.clone(), a) +} + struct TypeWithDrop { x: String, } diff --git a/tests/ui/redundant_clone.rs b/tests/ui/redundant_clone.rs index 48687c82c2fb..9ea2de9a3daa 100644 --- a/tests/ui/redundant_clone.rs +++ b/tests/ui/redundant_clone.rs @@ -1,5 +1,6 @@ // run-rustfix // rustfix-only-machine-applicable + use std::ffi::OsString; use std::path::Path; @@ -46,6 +47,7 @@ fn main() { let _ = Some(String::new()).unwrap_or_else(|| x.0.clone()); // ok; closure borrows `x` with_branch(Alpha, true); + cannot_double_move(Alpha); cannot_move_from_type_with_drop(); borrower_propagation(); } @@ -60,6 +62,10 @@ fn with_branch(a: Alpha, b: bool) -> (Alpha, Alpha) { } } +fn cannot_double_move(a: Alpha) -> (Alpha, Alpha) { + (a.clone(), a) +} + struct TypeWithDrop { x: String, } diff --git a/tests/ui/redundant_clone.stderr b/tests/ui/redundant_clone.stderr index feafbd78b4ea..62f4ce7645ed 100644 --- a/tests/ui/redundant_clone.stderr +++ b/tests/ui/redundant_clone.stderr @@ -1,159 +1,135 @@ error: redundant clone - --> $DIR/redundant_clone.rs:7:42 + --> $DIR/redundant_clone.rs:8:42 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^ help: remove this | = note: `-D clippy::redundant-clone` implied by `-D warnings` note: this value is dropped without further use - --> $DIR/redundant_clone.rs:7:14 + --> $DIR/redundant_clone.rs:8:14 | LL | let _s = ["lorem", "ipsum"].join(" ").to_string(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:10:15 + --> $DIR/redundant_clone.rs:11:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:10:14 + --> $DIR/redundant_clone.rs:11:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:13:15 + --> $DIR/redundant_clone.rs:14:15 | LL | let _s = s.to_string(); | ^^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:13:14 + --> $DIR/redundant_clone.rs:14:14 | LL | let _s = s.to_string(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:16:15 + --> $DIR/redundant_clone.rs:17:15 | LL | let _s = s.to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:16:14 + --> $DIR/redundant_clone.rs:17:14 | LL | let _s = s.to_owned(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:18:42 + --> $DIR/redundant_clone.rs:19:42 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:18:14 + --> $DIR/redundant_clone.rs:19:14 | LL | let _s = Path::new("/a/b/").join("c").to_owned(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:20:42 - | -LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); - | ^^^^^^^^^^^^^^ help: remove this - | -note: this value is dropped without further use - --> $DIR/redundant_clone.rs:20:14 - | -LL | let _s = Path::new("/a/b/").join("c").to_path_buf(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: redundant clone - --> $DIR/redundant_clone.rs:22:29 + --> $DIR/redundant_clone.rs:23:29 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:22:14 + --> $DIR/redundant_clone.rs:23:14 | LL | let _s = OsString::new().to_owned(); | ^^^^^^^^^^^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:24:29 - | -LL | let _s = OsString::new().to_os_string(); - | ^^^^^^^^^^^^^^^ help: remove this - | -note: this value is dropped without further use - --> $DIR/redundant_clone.rs:24:14 - | -LL | let _s = OsString::new().to_os_string(); - | ^^^^^^^^^^^^^^^ - -error: redundant clone - --> $DIR/redundant_clone.rs:31:19 + --> $DIR/redundant_clone.rs:32:19 | LL | let _t = tup.0.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:31:14 + --> $DIR/redundant_clone.rs:32:14 | LL | let _t = tup.0.clone(); | ^^^^^ error: redundant clone - --> $DIR/redundant_clone.rs:57:22 + --> $DIR/redundant_clone.rs:59:22 | LL | (a.clone(), a.clone()) | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:57:21 + --> $DIR/redundant_clone.rs:59:21 | LL | (a.clone(), a.clone()) | ^ error: redundant clone - --> $DIR/redundant_clone.rs:113:15 + --> $DIR/redundant_clone.rs:119:15 | LL | let _s = s.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:113:14 + --> $DIR/redundant_clone.rs:119:14 | LL | let _s = s.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:114:15 + --> $DIR/redundant_clone.rs:120:15 | LL | let _t = t.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:114:14 + --> $DIR/redundant_clone.rs:120:14 | LL | let _t = t.clone(); | ^ error: redundant clone - --> $DIR/redundant_clone.rs:124:19 + --> $DIR/redundant_clone.rs:130:19 | LL | let _f = f.clone(); | ^^^^^^^^ help: remove this | note: this value is dropped without further use - --> $DIR/redundant_clone.rs:124:18 + --> $DIR/redundant_clone.rs:130:18 | LL | let _f = f.clone(); | ^ -error: aborting due to 13 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/result_map_unit_fn_fixable.fixed b/tests/ui/result_map_unit_fn_fixable.fixed index 64d39516be71..1d0a3ecd0ff8 100644 --- a/tests/ui/result_map_unit_fn_fixable.fixed +++ b/tests/ui/result_map_unit_fn_fixable.fixed @@ -1,6 +1,5 @@ // run-rustfix -#![feature(never_type)] #![warn(clippy::result_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/result_map_unit_fn_fixable.rs b/tests/ui/result_map_unit_fn_fixable.rs index bf4aba8a7cc1..2fe18f923f08 100644 --- a/tests/ui/result_map_unit_fn_fixable.rs +++ b/tests/ui/result_map_unit_fn_fixable.rs @@ -1,6 +1,5 @@ // run-rustfix -#![feature(never_type)] #![warn(clippy::result_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/result_map_unit_fn_fixable.stderr b/tests/ui/result_map_unit_fn_fixable.stderr index db72c64d52e2..5f9bf2020b6e 100644 --- a/tests/ui/result_map_unit_fn_fixable.stderr +++ b/tests/ui/result_map_unit_fn_fixable.stderr @@ -1,5 +1,5 @@ error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn_fixable.rs:36:5 + --> $DIR/result_map_unit_fn_fixable.rs:35:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -9,7 +9,7 @@ LL | x.field.map(do_nothing); = note: `-D clippy::result-map-unit-fn` implied by `-D warnings` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn_fixable.rs:38:5 + --> $DIR/result_map_unit_fn_fixable.rs:37:5 | LL | x.field.map(do_nothing); | ^^^^^^^^^^^^^^^^^^^^^^^- @@ -17,7 +17,7 @@ LL | x.field.map(do_nothing); | help: try this: `if let Ok(x_field) = x.field { do_nothing(x_field) }` error: called `map(f)` on an Result value where `f` is a unit function - --> $DIR/result_map_unit_fn_fixable.rs:40:5 + --> $DIR/result_map_unit_fn_fixable.rs:39:5 | LL | x.field.map(diverge); | ^^^^^^^^^^^^^^^^^^^^- @@ -25,7 +25,7 @@ LL | x.field.map(diverge); | help: try this: `if let Ok(x_field) = x.field { diverge(x_field) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:46:5 + --> $DIR/result_map_unit_fn_fixable.rs:45:5 | LL | x.field.map(|value| x.do_result_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -33,7 +33,7 @@ LL | x.field.map(|value| x.do_result_nothing(value + captured)); | help: try this: `if let Ok(value) = x.field { x.do_result_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:48:5 + --> $DIR/result_map_unit_fn_fixable.rs:47:5 | LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -41,7 +41,7 @@ LL | x.field.map(|value| { x.do_result_plus_one(value + captured); }); | help: try this: `if let Ok(value) = x.field { x.do_result_plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:51:5 + --> $DIR/result_map_unit_fn_fixable.rs:50:5 | LL | x.field.map(|value| do_nothing(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -49,7 +49,7 @@ LL | x.field.map(|value| do_nothing(value + captured)); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:53:5 + --> $DIR/result_map_unit_fn_fixable.rs:52:5 | LL | x.field.map(|value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -57,7 +57,7 @@ LL | x.field.map(|value| { do_nothing(value + captured) }); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:55:5 + --> $DIR/result_map_unit_fn_fixable.rs:54:5 | LL | x.field.map(|value| { do_nothing(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -65,7 +65,7 @@ LL | x.field.map(|value| { do_nothing(value + captured); }); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:57:5 + --> $DIR/result_map_unit_fn_fixable.rs:56:5 | LL | x.field.map(|value| { { do_nothing(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -73,7 +73,7 @@ LL | x.field.map(|value| { { do_nothing(value + captured); } }); | help: try this: `if let Ok(value) = x.field { do_nothing(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:60:5 + --> $DIR/result_map_unit_fn_fixable.rs:59:5 | LL | x.field.map(|value| diverge(value + captured)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -81,7 +81,7 @@ LL | x.field.map(|value| diverge(value + captured)); | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:62:5 + --> $DIR/result_map_unit_fn_fixable.rs:61:5 | LL | x.field.map(|value| { diverge(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -89,7 +89,7 @@ LL | x.field.map(|value| { diverge(value + captured) }); | help: try this: `if let Ok(value) = x.field { diverge(value + captured) }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:64:5 + --> $DIR/result_map_unit_fn_fixable.rs:63:5 | LL | x.field.map(|value| { diverge(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -97,7 +97,7 @@ LL | x.field.map(|value| { diverge(value + captured); }); | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:66:5 + --> $DIR/result_map_unit_fn_fixable.rs:65:5 | LL | x.field.map(|value| { { diverge(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -105,7 +105,7 @@ LL | x.field.map(|value| { { diverge(value + captured); } }); | help: try this: `if let Ok(value) = x.field { diverge(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:71:5 + --> $DIR/result_map_unit_fn_fixable.rs:70:5 | LL | x.field.map(|value| { let y = plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -113,7 +113,7 @@ LL | x.field.map(|value| { let y = plus_one(value + captured); }); | help: try this: `if let Ok(value) = x.field { let y = plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:73:5 + --> $DIR/result_map_unit_fn_fixable.rs:72:5 | LL | x.field.map(|value| { plus_one(value + captured); }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -121,7 +121,7 @@ LL | x.field.map(|value| { plus_one(value + captured); }); | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:75:5 + --> $DIR/result_map_unit_fn_fixable.rs:74:5 | LL | x.field.map(|value| { { plus_one(value + captured); } }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- @@ -129,7 +129,7 @@ LL | x.field.map(|value| { { plus_one(value + captured); } }); | help: try this: `if let Ok(value) = x.field { plus_one(value + captured); }` error: called `map(f)` on an Result value where `f` is a unit closure - --> $DIR/result_map_unit_fn_fixable.rs:78:5 + --> $DIR/result_map_unit_fn_fixable.rs:77:5 | LL | x.field.map(|ref value| { do_nothing(value + captured) }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^- diff --git a/tests/ui/result_map_unit_fn_unfixable.rs b/tests/ui/result_map_unit_fn_unfixable.rs index 7d597332eafc..cc01976df995 100644 --- a/tests/ui/result_map_unit_fn_unfixable.rs +++ b/tests/ui/result_map_unit_fn_unfixable.rs @@ -1,4 +1,3 @@ -#![feature(never_type)] #![warn(clippy::result_map_unit_fn)] #![allow(unused)] diff --git a/tests/ui/result_map_unit_fn_unfixable.stderr b/tests/ui/result_map_unit_fn_unfixable.stderr index 949c22946793..16caac5828af 100644 --- a/tests/ui/result_map_unit_fn_unfixable.stderr +++ b/tests/ui/result_map_unit_fn_unfixable.stderr @@ -1,23 +1,23 @@ error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:17:5 + --> $DIR/result_map_unit_fn_unfixable.rs:16:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value) }); | ^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:19:5 + --> $DIR/result_map_unit_fn_unfixable.rs:18:5 | LL | x.field.map(|value| if value > 0 { do_nothing(value); do_nothing(value) }); | ^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:23:5 + --> $DIR/result_map_unit_fn_unfixable.rs:22:5 | LL | x.field.map(|value| { | ^ not found in this scope error[E0425]: cannot find value `x` in this scope - --> $DIR/result_map_unit_fn_unfixable.rs:27:5 + --> $DIR/result_map_unit_fn_unfixable.rs:26:5 | LL | x.field.map(|value| { do_nothing(value); do_nothing(value); }); | ^ not found in this scope