From 209696dfd1ca5ce6c79fe60bec25dcd0028dcc5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matthias=20Kr=C3=BCger?= Date: Sat, 5 Jan 2019 15:40:10 +0100 Subject: [PATCH] submodules: update clippy from 39bd8449 to c63b6349 Changes: ```` Revert "tests: used_underscore_binding_macro: disable random_state lint." Revert "Auto merge of #3603 - xfix:random-state-lint, r=phansch" rustup https://github.com/rust-lang/rust/pull/56837 rustup (don't know the exact PR unfortunately) Add itertools to integration tests tests: used_underscore_binding_macro: disable random_state lint. Trigger `use_self` lint in local macros Add run-rustfix where it already passes rustup: https://github.com/rust-lang/rust/pull/55517 Make clippy work with parallel rustc Add ui/for_kv_map test for false positive in #1279 Update to latest compiletest-rs release add testcase for #3462 deps: bump rustc_tools_util version from 0.1.0 to 0.1.1 just in case... Use compiletest's aux-build header instead of include macro rustc_tool_utils: fix failure to create proper non-repo version string when used in crates on crates.io, bump version rustfmt UI test cleanup: Extract ifs_same_cond tests Extract IteratorFalsePositives into option_helpers.rs UI test cleanup: Extract for_kv_map lint tests UI test cleanup: Extract lint from methods.rs test Fix test for rust-lang/rust#57250 Limit infinite_iter collect() check to known types Some improvements to util documentation Use hashset for name blacklist Reformat random_state tests Use node_id_to_type_opt instead of node_it_to_type in random_state Check pattern equality while checking declaration equality random_state lint Move constant write checks to temporary_assignment lint Use an FxHashSet for valid idents in documentation lint Fix suggestion for unnecessary_ref lint Update CONTRIBUTING.md for rustfix tests Update .fixed files via update-references.sh Run rustfix on first UI test Use WIP branch for compiletest_rs ```` --- .travis.yml | 2 + CONTRIBUTING.md | 9 +++ Cargo.toml | 6 +- clippy_lints/src/blacklisted_name.rs | 7 +- clippy_lints/src/consts.rs | 8 +- clippy_lints/src/doc.rs | 13 +-- clippy_lints/src/enum_clike.rs | 2 +- clippy_lints/src/enum_variants.rs | 6 +- clippy_lints/src/infinite_iter.rs | 20 ++++- clippy_lints/src/len_zero.rs | 13 ++- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/no_effect.rs | 14 ---- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/reference.rs | 8 +- clippy_lints/src/temporary_assignment.rs | 24 ++++-- clippy_lints/src/use_self.rs | 6 +- clippy_lints/src/utils/hir_utils.rs | 4 +- clippy_lints/src/utils/mod.rs | 29 +++++-- rustc_tools_util/Cargo.toml | 2 +- rustc_tools_util/src/lib.rs | 21 ++--- tests/run-pass/ice-3462.rs | 30 +++++++ tests/ui/auxiliary/option_helpers.rs | 47 +++++++++++ tests/ui/builtin-type-shadow.stderr | 2 +- tests/ui/cast_lossless_float.fixed | 26 ++++++ tests/ui/cast_lossless_float.rs | 2 + tests/ui/cast_lossless_float.stderr | 20 ++--- tests/ui/cast_lossless_integer.fixed | 34 ++++++++ tests/ui/cast_lossless_integer.rs | 2 + tests/ui/cast_lossless_integer.stderr | 36 ++++----- tests/ui/copies.rs | 49 ++---------- tests/ui/copies.stderr | 39 +-------- tests/ui/double_comparison.fixed | 39 +++++++++ tests/ui/double_comparison.rs | 2 + tests/ui/double_comparison.stderr | 16 ++-- tests/ui/for_kv_map.rs | 59 ++++++++++++++ tests/ui/for_kv_map.stderr | 54 +++++++++++++ tests/ui/for_loop.rs | 42 ---------- tests/ui/for_loop.stderr | 76 +++--------------- tests/ui/ifs_same_cond.rs | 46 +++++++++++ tests/ui/ifs_same_cond.stderr | 39 +++++++++ tests/ui/infinite_iter.rs | 19 +++++ tests/ui/infinite_iter.stderr | 10 ++- tests/ui/iter_skip_next.rs | 38 +-------- tests/ui/iter_skip_next.stderr | 8 +- tests/ui/methods.rs | 73 ++--------------- tests/ui/methods.stderr | 98 ++++++++--------------- tests/ui/no_effect.rs | 27 ------- tests/ui/no_effect.stderr | 76 ++++++------------ tests/ui/println_empty_string.fixed | 19 +++++ tests/ui/println_empty_string.rs | 2 + tests/ui/println_empty_string.stderr | 4 +- tests/ui/ptr_offset_with_cast.fixed | 29 +++++++ tests/ui/ptr_offset_with_cast.rs | 2 + tests/ui/ptr_offset_with_cast.stderr | 4 +- tests/ui/result_map_unwrap_or_else.rs | 32 ++++++++ tests/ui/result_map_unwrap_or_else.stderr | 27 +++++++ tests/ui/single_char_pattern.fixed | 61 ++++++++++++++ tests/ui/single_char_pattern.rs | 2 + tests/ui/single_char_pattern.stderr | 40 ++++----- tests/ui/string_extend.fixed | 41 ++++++++++ tests/ui/string_extend.rs | 2 + tests/ui/string_extend.stderr | 6 +- tests/ui/temporary_assignment.rs | 38 +++++++++ tests/ui/temporary_assignment.stderr | 46 ++++++++++- tests/ui/unnecessary_ref.fixed | 23 ++++++ tests/ui/unnecessary_ref.rs | 4 +- tests/ui/unnecessary_ref.stderr | 6 +- tests/ui/unreadable_literal.fixed | 29 +++++++ tests/ui/unreadable_literal.rs | 2 + tests/ui/unreadable_literal.stderr | 10 +-- tests/ui/update-references.sh | 6 ++ tests/ui/use_self.rs | 16 ++++ tests/ui/use_self.stderr | 20 ++++- tests/ui/vec.fixed | 64 +++++++++++++++ tests/ui/vec.rs | 2 + tests/ui/vec.stderr | 12 +-- tests/ui/writeln_empty_string.fixed | 29 +++++++ tests/ui/writeln_empty_string.rs | 2 + tests/ui/writeln_empty_string.stderr | 4 +- 79 files changed, 1202 insertions(+), 593 deletions(-) create mode 100644 tests/run-pass/ice-3462.rs create mode 100644 tests/ui/auxiliary/option_helpers.rs create mode 100644 tests/ui/cast_lossless_float.fixed create mode 100644 tests/ui/cast_lossless_integer.fixed create mode 100644 tests/ui/double_comparison.fixed create mode 100644 tests/ui/for_kv_map.rs create mode 100644 tests/ui/for_kv_map.stderr create mode 100644 tests/ui/ifs_same_cond.rs create mode 100644 tests/ui/ifs_same_cond.stderr create mode 100644 tests/ui/println_empty_string.fixed create mode 100644 tests/ui/ptr_offset_with_cast.fixed create mode 100644 tests/ui/result_map_unwrap_or_else.rs create mode 100644 tests/ui/result_map_unwrap_or_else.stderr create mode 100644 tests/ui/single_char_pattern.fixed create mode 100644 tests/ui/string_extend.fixed create mode 100644 tests/ui/unnecessary_ref.fixed create mode 100644 tests/ui/unreadable_literal.fixed create mode 100644 tests/ui/vec.fixed create mode 100644 tests/ui/writeln_empty_string.fixed diff --git a/.travis.yml b/.travis.yml index eb66112213b0..d456497d9972 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,6 +71,8 @@ matrix: if: repo =~ /^rust-lang\/rust-clippy$/ - env: INTEGRATION=hyperium/hyper if: repo =~ /^rust-lang\/rust-clippy$/ + - env: INTEGRATION=bluss/rust-itertools + if: repo =~ /^rust-lang\/rust-clippy$/ allow_failures: - os: windows env: CARGO_INCREMENTAL=0 BASE_TESTS=true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 94120a3771a2..df216a8fbc95 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -156,6 +156,15 @@ Therefore you should use `tests/ui/update-all-references.sh` (after running `cargo test`) and check whether the output looks as you expect with `git diff`. Commit all `*.stderr` files, too. +If the lint you are working on is making use of structured suggestions, the +test file should include a `// run-rustfix` comment at the top. This will +additionally run [rustfix](https://github.com/rust-lang-nursery/rustfix) for +that test. Rustfix will apply the suggestions from the lint to the code of the +test file and compare that to the contents of a `.fixed` file. + +Use `tests/ui/update-all-references.sh` to automatically generate the +`.fixed` file after running `cargo test`. + ### Running rustfmt [Rustfmt](https://github.com/rust-lang/rustfmt) is a tool for formatting Rust code according diff --git a/Cargo.toml b/Cargo.toml index 359a6e43bdbb..ce609bb1adde 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,12 +43,12 @@ clippy_lints = { version = "0.0.212", path = "clippy_lints" } # end automatic update regex = "1" semver = "0.9" -rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} +rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [dev-dependencies] clippy_dev = { version = "0.0.1", path = "clippy_dev" } cargo_metadata = "0.6.2" -compiletest_rs = "0.3.16" +compiletest_rs = "0.3.18" lazy_static = "1.0" serde_derive = "1.0" clippy-mini-macro-test = { version = "0.2", path = "mini-macro" } @@ -61,7 +61,7 @@ derive-new = "0.5" rustc-workspace-hack = "1.0.0" [build-dependencies] -rustc_tools_util = { version = "0.1.0", path = "rustc_tools_util"} +rustc_tools_util = { version = "0.1.1", path = "rustc_tools_util"} [features] debugging = [] diff --git a/clippy_lints/src/blacklisted_name.rs b/clippy_lints/src/blacklisted_name.rs index ce7da4194971..ed7437e495b9 100644 --- a/clippy_lints/src/blacklisted_name.rs +++ b/clippy_lints/src/blacklisted_name.rs @@ -11,6 +11,7 @@ use crate::utils::span_lint; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; /// **What it does:** Checks for usage of blacklisted names for variables, such /// as `foo`. @@ -32,11 +33,11 @@ declare_clippy_lint! { #[derive(Clone, Debug)] pub struct BlackListedName { - blacklist: Vec, + blacklist: FxHashSet, } impl BlackListedName { - pub fn new(blacklist: Vec) -> Self { + pub fn new(blacklist: FxHashSet) -> Self { Self { blacklist } } } @@ -50,7 +51,7 @@ impl LintPass for BlackListedName { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BlackListedName { fn check_pat(&mut self, cx: &LateContext<'a, 'tcx>, pat: &'tcx Pat) { if let PatKind::Binding(_, _, ident, _) = pat.node { - if self.blacklist.iter().any(|s| ident.name == *s) { + if self.blacklist.contains(&ident.name.to_string()) { span_lint( cx, BLACKLISTED_NAME, diff --git a/clippy_lints/src/consts.rs b/clippy_lints/src/consts.rs index a1fe13e4962a..8102a416d82c 100644 --- a/clippy_lints/src/consts.rs +++ b/clippy_lints/src/consts.rs @@ -17,11 +17,11 @@ use rustc::lint::LateContext; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::{self, Instance, Ty, TyCtxt}; use rustc::{bug, span_bug}; +use rustc_data_structures::sync::Lrc; use std::cmp::Ordering::{self, Equal}; use std::cmp::PartialOrd; use std::convert::TryInto; use std::hash::{Hash, Hasher}; -use std::rc::Rc; use syntax::ast::{FloatTy, LitKind}; use syntax::ptr::P; @@ -31,7 +31,7 @@ pub enum Constant { /// a String "abc" Str(String), /// a Binary String b"abc" - Binary(Rc>), + Binary(Lrc>), /// a single char 'a' Char(char), /// an integer's bit representation @@ -156,7 +156,7 @@ pub fn lit_to_constant<'tcx>(lit: &LitKind, ty: Ty<'tcx>) -> Constant { match *lit { LitKind::Str(ref is, _) => Constant::Str(is.to_string()), LitKind::Byte(b) => Constant::Int(u128::from(b)), - LitKind::ByteStr(ref s) => Constant::Binary(Rc::clone(s)), + LitKind::ByteStr(ref s) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), LitKind::Int(n, _) => Constant::Int(n), LitKind::Float(ref is, _) | LitKind::FloatUnsuffixed(ref is) => match ty.sty { @@ -304,7 +304,7 @@ impl<'c, 'cc> ConstEvalLateContext<'c, 'cc> { }; let result = self.tcx.const_eval(self.param_env.and(gid)).ok()?; - let ret = miri_to_const(self.tcx, result); + let ret = miri_to_const(self.tcx, &result); if ret.is_some() { self.needed_resolution = true; } diff --git a/clippy_lints/src/doc.rs b/clippy_lints/src/doc.rs index 024907185e9e..a3504e7e3303 100644 --- a/clippy_lints/src/doc.rs +++ b/clippy_lints/src/doc.rs @@ -12,6 +12,7 @@ use itertools::Itertools; use pulldown_cmark; use rustc::lint::{EarlyContext, EarlyLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; +use rustc_data_structures::fx::FxHashSet; use syntax::ast; use syntax::source_map::{BytePos, Span}; use syntax_pos::Pos; @@ -43,11 +44,11 @@ declare_clippy_lint! { #[derive(Clone)] pub struct Doc { - valid_idents: Vec, + valid_idents: FxHashSet, } impl Doc { - pub fn new(valid_idents: Vec) -> Self { + pub fn new(valid_idents: FxHashSet) -> Self { Self { valid_idents } } } @@ -144,7 +145,7 @@ pub fn strip_doc_comment_decoration(comment: &str, span: Span) -> (String, Vec<( panic!("not a doc-comment: {}", comment); } -pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &'a [ast::Attribute]) { +pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &FxHashSet, attrs: &'a [ast::Attribute]) { let mut doc = String::new(); let mut spans = vec![]; @@ -192,7 +193,7 @@ pub fn check_attrs<'a>(cx: &EarlyContext<'_>, valid_idents: &[String], attrs: &' fn check_doc<'a, Events: Iterator)>>( cx: &EarlyContext<'_>, - valid_idents: &[String], + valid_idents: &FxHashSet, docs: Events, spans: &[(usize, Span)], ) { @@ -237,14 +238,14 @@ fn check_doc<'a, Events: Iterator)>>( } } -fn check_text(cx: &EarlyContext<'_>, valid_idents: &[String], text: &str, span: Span) { +fn check_text(cx: &EarlyContext<'_>, valid_idents: &FxHashSet, text: &str, span: Span) { for word in text.split(|c: char| c.is_whitespace() || c == '\'') { // Trim punctuation as in `some comment (see foo::bar).` // ^^ // Or even as in `_foo bar_` which is emphasized. let word = word.trim_matches(|c: char| !c.is_alphanumeric()); - if valid_idents.iter().any(|i| i == word) { + if valid_idents.contains(word) { continue; } diff --git a/clippy_lints/src/enum_clike.rs b/clippy_lints/src/enum_clike.rs index 29038cda869e..78cade1f2fb0 100644 --- a/clippy_lints/src/enum_clike.rs +++ b/clippy_lints/src/enum_clike.rs @@ -70,7 +70,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnportableVariant { promoted: None, }; let constant = cx.tcx.const_eval(param_env.and(c_id)).ok(); - if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, c)) { + if let Some(Constant::Int(val)) = constant.and_then(|c| miri_to_const(cx.tcx, &c)) { let mut ty = cx.tcx.type_of(def_id); if let ty::Adt(adt, _) = ty.sty { if adt.is_enum() { diff --git a/clippy_lints/src/enum_variants.rs b/clippy_lints/src/enum_variants.rs index c5d7094dcc1a..5466baae8860 100644 --- a/clippy_lints/src/enum_variants.rs +++ b/clippy_lints/src/enum_variants.rs @@ -15,7 +15,7 @@ use rustc::lint::{EarlyContext, EarlyLintPass, Lint, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; use syntax::ast::*; use syntax::source_map::Span; -use syntax::symbol::LocalInternedString; +use syntax::symbol::{InternedString, LocalInternedString}; /// **What it does:** Detects enumeration variants that are prefixed or suffixed /// by the same characters. @@ -111,7 +111,7 @@ declare_clippy_lint! { } pub struct EnumVariantNames { - modules: Vec<(LocalInternedString, String)>, + modules: Vec<(InternedString, String)>, threshold: u64, } @@ -308,6 +308,6 @@ impl EarlyLintPass for EnumVariantNames { }; check_variant(cx, self.threshold, def, &item_name, item_name_chars, item.span, lint); } - self.modules.push((item_name, item_camel)); + self.modules.push((item_name.as_interned_str(), item_camel)); } } diff --git a/clippy_lints/src/infinite_iter.rs b/clippy_lints/src/infinite_iter.rs index 2f7c5895af8d..e2da8461f411 100644 --- a/clippy_lints/src/infinite_iter.rs +++ b/clippy_lints/src/infinite_iter.rs @@ -7,7 +7,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, paths, span_lint}; +use crate::utils::{get_trait_def_id, higher, implements_trait, match_qpath, match_type, paths, span_lint}; use rustc::hir::*; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; @@ -200,7 +200,6 @@ static POSSIBLY_COMPLETING_METHODS: &[(&str, usize)] = &[ /// their iterators static COMPLETING_METHODS: &[(&str, usize)] = &[ ("count", 1), - ("collect", 1), ("fold", 3), ("for_each", 2), ("partition", 2), @@ -214,6 +213,18 @@ static COMPLETING_METHODS: &[(&str, usize)] = &[ ("product", 1), ]; +/// the paths of types that are known to be infinitely allocating +static INFINITE_COLLECTORS: &[&[&str]] = &[ + &paths::BINARY_HEAP, + &paths::BTREEMAP, + &paths::BTREESET, + &paths::HASHMAP, + &paths::HASHSET, + &paths::LINKED_LIST, + &paths::VEC, + &paths::VEC_DEQUE, +]; + fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { match expr.node { ExprKind::MethodCall(ref method, _, ref args) => { @@ -233,6 +244,11 @@ fn complete_infinite_iter(cx: &LateContext<'_, '_>, expr: &Expr) -> Finiteness { if not_double_ended { return is_infinite(cx, &args[0]); } + } else if method.ident.name == "collect" { + let ty = cx.tables.expr_ty(expr); + if INFINITE_COLLECTORS.iter().any(|path| match_type(cx, ty, path)) { + return is_infinite(cx, &args[0]); + } } }, ExprKind::Binary(op, ref l, ref r) => { diff --git a/clippy_lints/src/len_zero.rs b/clippy_lints/src/len_zero.rs index 61aa228729ce..233bea77e03b 100644 --- a/clippy_lints/src/len_zero.rs +++ b/clippy_lints/src/len_zero.rs @@ -302,10 +302,15 @@ fn has_is_empty(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { let ty = &walk_ptrs_ty(cx.tables.expr_ty(expr)); match ty.sty { - ty::Dynamic(ref tt, ..) => cx - .tcx - .associated_items(tt.principal().def_id()) - .any(|item| is_is_empty(cx, &item)), + ty::Dynamic(ref tt, ..) => { + if let Some(principal) = tt.principal() { + cx.tcx + .associated_items(principal.def_id()) + .any(|item| is_is_empty(cx, &item)) + } else { + false + } + }, ty::Projection(ref proj) => has_is_empty_impl(cx, proj.item_def_id), ty::Adt(id, _) => has_is_empty_impl(cx, id.did), ty::Array(..) | ty::Slice(..) | ty::Str => true, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 27905b917500..2e515cc8aea6 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -423,9 +423,11 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) { reg.register_late_lint_pass(box overflow_check_conditional::OverflowCheckConditional); reg.register_late_lint_pass(box unused_label::UnusedLabel); reg.register_late_lint_pass(box new_without_default::NewWithoutDefault::default()); - reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new(conf.blacklisted_names.clone())); + reg.register_late_lint_pass(box blacklisted_name::BlackListedName::new( + conf.blacklisted_names.iter().cloned().collect() + )); reg.register_late_lint_pass(box functions::Functions::new(conf.too_many_arguments_threshold)); - reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.clone())); + reg.register_early_lint_pass(box doc::Doc::new(conf.doc_valid_idents.iter().cloned().collect())); reg.register_late_lint_pass(box neg_multiply::NegMultiply); reg.register_early_lint_pass(box unsafe_removed_from_name::UnsafeNameRemoval); reg.register_late_lint_pass(box mem_discriminant::MemDiscriminant); diff --git a/clippy_lints/src/no_effect.rs b/clippy_lints/src/no_effect.rs index 02ca5ebedfa5..c2cffadf6c12 100644 --- a/clippy_lints/src/no_effect.rs +++ b/clippy_lints/src/no_effect.rs @@ -98,20 +98,6 @@ fn has_no_effect(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { false } }, - ExprKind::Assign(ref left, ref right) => { - if has_no_effect(cx, left) { - let mut left = left; - while let ExprKind::Field(f, _) | ExprKind::Index(f, _) = &left.node { - left = f; - } - if let ExprKind::Path(qpath) = &left.node { - if let Def::Const(..) = cx.tables.qpath_def(qpath, left.hir_id) { - return has_no_effect(cx, right); - } - } - } - false - }, _ => false, } } diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index 63a3a8313044..c1a76eed928b 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -113,7 +113,7 @@ impl Pass { fn moves_by_default(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { let expr_ty = cx.tables.expr_ty(expression); - expr_ty.moves_by_default(cx.tcx, cx.param_env, expression.span) + !expr_ty.is_copy_modulo_regions(cx.tcx, cx.param_env, expression.span) } fn is_option(cx: &LateContext<'_, '_>, expression: &Expr) -> bool { diff --git a/clippy_lints/src/reference.rs b/clippy_lints/src/reference.rs index d4145a2dd39c..54a9c0336f04 100644 --- a/clippy_lints/src/reference.rs +++ b/clippy_lints/src/reference.rs @@ -98,7 +98,7 @@ impl LintPass for DerefPass { impl EarlyLintPass for DerefPass { fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &Expr) { if_chain! { - if let ExprKind::Field(ref object, ref field_name) = e.node; + if let ExprKind::Field(ref object, _) = e.node; if let ExprKind::Paren(ref parened) = object.node; if let ExprKind::AddrOf(_, ref inner) = parened.node; then { @@ -109,11 +109,7 @@ impl EarlyLintPass for DerefPass { object.span, "Creating a reference that is immediately dereferenced.", "try this", - format!( - "{}.{}", - snippet_with_applicability(cx, inner.span, "_", &mut applicability), - snippet_with_applicability(cx, field_name.span, "_", &mut applicability) - ), + snippet_with_applicability(cx, inner.span, "_", &mut applicability).to_string(), applicability, ); } diff --git a/clippy_lints/src/temporary_assignment.rs b/clippy_lints/src/temporary_assignment.rs index a454b6fd997a..381efd571356 100644 --- a/clippy_lints/src/temporary_assignment.rs +++ b/clippy_lints/src/temporary_assignment.rs @@ -9,6 +9,7 @@ use crate::utils::is_adjusted; use crate::utils::span_lint; +use rustc::hir::def::Def; use rustc::hir::{Expr, ExprKind}; use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; use rustc::{declare_tool_lint, lint_array}; @@ -31,9 +32,16 @@ declare_clippy_lint! { "assignments to temporaries" } -fn is_temporary(expr: &Expr) -> bool { - match expr.node { +fn is_temporary(cx: &LateContext<'_, '_>, expr: &Expr) -> bool { + match &expr.node { ExprKind::Struct(..) | ExprKind::Tup(..) => true, + ExprKind::Path(qpath) => { + if let Def::Const(..) = cx.tables.qpath_def(qpath, expr.hir_id) { + true + } else { + false + } + }, _ => false, } } @@ -49,11 +57,13 @@ impl LintPass for Pass { impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass { fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr) { - if let ExprKind::Assign(ref target, _) = expr.node { - if let ExprKind::Field(ref base, _) = target.node { - if is_temporary(base) && !is_adjusted(cx, base) { - span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); - } + if let ExprKind::Assign(target, _) = &expr.node { + let mut base = target; + while let ExprKind::Field(f, _) | ExprKind::Index(f, _) = &base.node { + base = f; + } + if is_temporary(cx, base) && !is_adjusted(cx, base) { + span_lint(cx, TEMPORARY_ASSIGNMENT, expr.span, "assignment to temporary"); } } } diff --git a/clippy_lints/src/use_self.rs b/clippy_lints/src/use_self.rs index b031e8b1c444..aa4302e12a74 100644 --- a/clippy_lints/src/use_self.rs +++ b/clippy_lints/src/use_self.rs @@ -7,12 +7,12 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::utils::{in_macro, span_lint_and_sugg}; +use crate::utils::span_lint_and_sugg; use if_chain::if_chain; use rustc::hir::def::{CtorKind, Def}; use rustc::hir::intravisit::{walk_path, walk_ty, NestedVisitorMap, Visitor}; use rustc::hir::*; -use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass}; +use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass}; use rustc::ty; use rustc::{declare_tool_lint, lint_array}; use rustc_errors::Applicability; @@ -172,7 +172,7 @@ fn check_trait_method_impl_decl<'a, 'tcx: 'a>( impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UseSelf { fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx Item) { - if in_macro(item.span) { + if in_external_macro(cx.sess(), item.span) { return; } if_chain! { diff --git a/clippy_lints/src/utils/hir_utils.rs b/clippy_lints/src/utils/hir_utils.rs index 79c9de13571c..377e56ddcac9 100644 --- a/clippy_lints/src/utils/hir_utils.rs +++ b/clippy_lints/src/utils/hir_utils.rs @@ -54,7 +54,9 @@ impl<'a, 'tcx: 'a> SpanlessEq<'a, 'tcx> { match (&left.node, &right.node) { (&StmtKind::Decl(ref l, _), &StmtKind::Decl(ref r, _)) => { if let (&DeclKind::Local(ref l), &DeclKind::Local(ref r)) = (&l.node, &r.node) { - both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) + self.eq_pat(&l.pat, &r.pat) + && both(&l.ty, &r.ty, |l, r| self.eq_ty(l, r)) + && both(&l.init, &r.init, |l, r| self.eq_expr(l, r)) } else { false } diff --git a/clippy_lints/src/utils/mod.rs b/clippy_lints/src/utils/mod.rs index e92529dc0a25..9b5e18413a23 100644 --- a/clippy_lints/src/utils/mod.rs +++ b/clippy_lints/src/utils/mod.rs @@ -25,11 +25,11 @@ use rustc::ty::{ subst::Kind, Binder, Ty, TyCtxt, }; +use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, CodeSuggestion, Substitution, SubstitutionPart}; use std::borrow::Cow; use std::env; use std::mem; -use std::rc::Rc; use std::str::FromStr; use syntax::ast::{self, LitKind}; use syntax::attr; @@ -62,6 +62,15 @@ pub fn differing_macro_contexts(lhs: Span, rhs: Span) -> bool { rhs.ctxt() != lhs.ctxt() } +/// Returns `true` if the given `NodeId` is inside a constant context +/// +/// # Example +/// +/// ```rust,ignore +/// if in_constant(cx, expr.id) { +/// // Do something +/// } +/// ``` pub fn in_constant(cx: &LateContext<'_, '_>, id: NodeId) -> bool { let parent_id = cx.tcx.hir().get_parent(id); match cx.tcx.hir().body_owner_kind(parent_id) { @@ -214,7 +223,7 @@ pub fn path_to_def(cx: &LateContext<'_, '_>, path: &[&str]) -> Option None => return None, }; - for item in mem::replace(&mut items, Rc::new(vec![])).iter() { + for item in mem::replace(&mut items, Lrc::new(vec![])).iter() { if item.ident.name == *segment { if path_it.peek().is_none() { return Some(item.def); @@ -262,7 +271,7 @@ pub fn implements_trait<'a, 'tcx>( ); cx.tcx .infer_ctxt() - .enter(|infcx| infcx.predicate_must_hold(&obligation)) + .enter(|infcx| infcx.predicate_must_hold_modulo_regions(&obligation)) } /// Check whether this type implements Drop. @@ -377,6 +386,9 @@ pub fn contains_name(name: Name, expr: &Expr) -> bool { /// Convert a span to a code snippet if available, otherwise use default. /// +/// This is useful if you want to provide suggestions for your lint or more generally, if you want +/// to convert a given `Span` to a `str`. +/// /// # Example /// ```rust,ignore /// snippet(cx, expr.span, "..") @@ -430,7 +442,7 @@ pub fn snippet_opt<'a, T: LintContext<'a>>(cx: &T, span: Span) -> Option /// /// # Example /// ```rust,ignore -/// snippet(cx, expr.span, "..") +/// snippet_block(cx, expr.span, "..") /// ``` pub fn snippet_block<'a, 'b, T: LintContext<'b>>(cx: &T, span: Span, default: &'a str) -> Cow<'a, str> { let snip = snippet(cx, span, default); @@ -741,6 +753,13 @@ pub fn is_integer_literal(expr: &Expr, value: u128) -> bool { false } +/// Returns `true` if the given `Expr` has been coerced before. +/// +/// Examples of coercions can be found in the Nomicon at +/// . +/// +/// See `rustc::ty::adjustment::Adjustment` and `rustc_typeck::check::coercion` for more +/// information on adjustments and coercions. pub fn is_adjusted(cx: &LateContext<'_, '_>, e: &Expr) -> bool { cx.tables.adjustments().get(e.hir_id).is_some() } @@ -865,7 +884,7 @@ pub fn type_is_unsafe_function<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx } pub fn is_copy<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool { - !ty.moves_by_default(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP) + ty.is_copy_modulo_regions(cx.tcx.global_tcx(), cx.param_env, DUMMY_SP) } /// Return whether a pattern is refutable. diff --git a/rustc_tools_util/Cargo.toml b/rustc_tools_util/Cargo.toml index b73d7ca56060..70ff86c49afe 100644 --- a/rustc_tools_util/Cargo.toml +++ b/rustc_tools_util/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustc_tools_util" -version = "0.1.0" +version = "0.1.1" authors = ["Matthias Krüger "] description = "small helper to generate version information for git packages" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/rustc_tools_util/src/lib.rs b/rustc_tools_util/src/lib.rs index d1640c758bb3..49bfb7d8b599 100644 --- a/rustc_tools_util/src/lib.rs +++ b/rustc_tools_util/src/lib.rs @@ -46,16 +46,17 @@ pub struct VersionInfo { impl std::fmt::Display for VersionInfo { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - if self.commit_hash.is_some() { + let hash = self.commit_hash.clone().unwrap_or_default(); + let hash_trimmed = hash.trim(); + + let date = self.commit_date.clone().unwrap_or_default(); + let date_trimmed = date.trim(); + + if (hash_trimmed.len() + date_trimmed.len()) > 0 { write!( f, "{} {}.{}.{} ({} {})", - self.crate_name, - self.major, - self.minor, - self.patch, - self.commit_hash.clone().unwrap_or_default().trim(), - self.commit_date.clone().unwrap_or_default().trim(), + self.crate_name, self.major, self.minor, self.patch, hash_trimmed, date_trimmed, )?; } else { write!(f, "{} {}.{}.{}", self.crate_name, self.major, self.minor, self.patch)?; @@ -121,7 +122,7 @@ mod test { let vi = get_version_info!(); assert_eq!(vi.major, 0); assert_eq!(vi.minor, 1); - assert_eq!(vi.patch, 0); + assert_eq!(vi.patch, 1); assert_eq!(vi.crate_name, "rustc_tools_util"); // hard to make positive tests for these since they will always change assert!(vi.commit_hash.is_none()); @@ -131,7 +132,7 @@ mod test { #[test] fn test_display_local() { let vi = get_version_info!(); - assert_eq!(vi.to_string(), "rustc_tools_util 0.1.0"); + assert_eq!(vi.to_string(), "rustc_tools_util 0.1.1"); } #[test] @@ -140,7 +141,7 @@ mod test { let s = format!("{:?}", vi); assert_eq!( s, - "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 0 }" + "VersionInfo { crate_name: \"rustc_tools_util\", major: 0, minor: 1, patch: 1 }" ); } diff --git a/tests/run-pass/ice-3462.rs b/tests/run-pass/ice-3462.rs new file mode 100644 index 000000000000..8aea905cd806 --- /dev/null +++ b/tests/run-pass/ice-3462.rs @@ -0,0 +1,30 @@ +// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::all)] +#![allow(clippy::blacklisted_name)] +#![allow(unused)] + +enum Foo { + Bar, + Baz, +} + +fn bar(foo: Foo) { + macro_rules! baz { + () => { + if let Foo::Bar = foo {} + }; + } + + baz!(); + baz!(); +} + +fn main() {} diff --git a/tests/ui/auxiliary/option_helpers.rs b/tests/ui/auxiliary/option_helpers.rs new file mode 100644 index 000000000000..331952119689 --- /dev/null +++ b/tests/ui/auxiliary/option_helpers.rs @@ -0,0 +1,47 @@ +#![allow(dead_code, unused_variables)] + +/// Utility macro to test linting behavior in `option_methods()` +/// The lints included in `option_methods()` should not lint if the call to map is partially +/// within a macro +#[macro_export] +macro_rules! opt_map { + ($opt:expr, $map:expr) => { + ($opt).map($map) + }; +} + +/// Struct to generate false positive for Iterator-based lints +#[derive(Copy, Clone)] +pub struct IteratorFalsePositives { + pub foo: u32, +} + +impl IteratorFalsePositives { + pub fn filter(self) -> IteratorFalsePositives { + self + } + + pub fn next(self) -> IteratorFalsePositives { + self + } + + pub fn find(self) -> Option { + Some(self.foo) + } + + pub fn position(self) -> Option { + Some(self.foo) + } + + pub fn rposition(self) -> Option { + Some(self.foo) + } + + pub fn nth(self, n: usize) -> Option { + Some(self.foo) + } + + pub fn skip(self, _: usize) -> IteratorFalsePositives { + self + } +} diff --git a/tests/ui/builtin-type-shadow.stderr b/tests/ui/builtin-type-shadow.stderr index 9bfed9dbba87..940a6dc2bcc8 100644 --- a/tests/ui/builtin-type-shadow.stderr +++ b/tests/ui/builtin-type-shadow.stderr @@ -12,7 +12,7 @@ error[E0308]: mismatched types LL | fn foo(a: u32) -> u32 { | --- expected `u32` because of return type LL | 42 - | ^^ expected type parameter, found integral variable + | ^^ expected type parameter, found integer | = note: expected type `u32` found type `{integer}` diff --git a/tests/ui/cast_lossless_float.fixed b/tests/ui/cast_lossless_float.fixed new file mode 100644 index 000000000000..5f4e54eb565b --- /dev/null +++ b/tests/ui/cast_lossless_float.fixed @@ -0,0 +1,26 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[warn(clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] +fn main() { + // Test clippy::cast_lossless with casts to floating-point types + f32::from(1i8); + f64::from(1i8); + f32::from(1u8); + f64::from(1u8); + f32::from(1i16); + f64::from(1i16); + f32::from(1u16); + f64::from(1u16); + f64::from(1i32); + f64::from(1u32); +} diff --git a/tests/ui/cast_lossless_float.rs b/tests/ui/cast_lossless_float.rs index e52a756c003d..b818010feb20 100644 --- a/tests/ui/cast_lossless_float.rs +++ b/tests/ui/cast_lossless_float.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_lossless_float.stderr b/tests/ui/cast_lossless_float.stderr index 2164315c35e9..aa48bd4d1c7d 100644 --- a/tests/ui/cast_lossless_float.stderr +++ b/tests/ui/cast_lossless_float.stderr @@ -1,5 +1,5 @@ error: casting i8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:14:5 + --> $DIR/cast_lossless_float.rs:16:5 | LL | 1i8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1i8)` @@ -7,55 +7,55 @@ LL | 1i8 as f32; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:15:5 + --> $DIR/cast_lossless_float.rs:17:5 | LL | 1i8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1i8)` error: casting u8 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:16:5 + --> $DIR/cast_lossless_float.rs:18:5 | LL | 1u8 as f32; | ^^^^^^^^^^ help: try: `f32::from(1u8)` error: casting u8 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:17:5 + --> $DIR/cast_lossless_float.rs:19:5 | LL | 1u8 as f64; | ^^^^^^^^^^ help: try: `f64::from(1u8)` error: casting i16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:18:5 + --> $DIR/cast_lossless_float.rs:20:5 | LL | 1i16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1i16)` error: casting i16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:19:5 + --> $DIR/cast_lossless_float.rs:21:5 | LL | 1i16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i16)` error: casting u16 to f32 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:20:5 + --> $DIR/cast_lossless_float.rs:22:5 | LL | 1u16 as f32; | ^^^^^^^^^^^ help: try: `f32::from(1u16)` error: casting u16 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:21:5 + --> $DIR/cast_lossless_float.rs:23:5 | LL | 1u16 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u16)` error: casting i32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:22:5 + --> $DIR/cast_lossless_float.rs:24:5 | LL | 1i32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1i32)` error: casting u32 to f64 may become silently lossy if types change - --> $DIR/cast_lossless_float.rs:23:5 + --> $DIR/cast_lossless_float.rs:25:5 | LL | 1u32 as f64; | ^^^^^^^^^^^ help: try: `f64::from(1u32)` diff --git a/tests/ui/cast_lossless_integer.fixed b/tests/ui/cast_lossless_integer.fixed new file mode 100644 index 000000000000..83f3e0242099 --- /dev/null +++ b/tests/ui/cast_lossless_integer.fixed @@ -0,0 +1,34 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[warn(clippy::cast_lossless)] +#[allow(clippy::no_effect, clippy::unnecessary_operation)] +fn main() { + // Test clippy::cast_lossless with casts to integer types + i16::from(1i8); + i32::from(1i8); + i64::from(1i8); + i16::from(1u8); + i32::from(1u8); + i64::from(1u8); + u16::from(1u8); + u32::from(1u8); + u64::from(1u8); + i32::from(1i16); + i64::from(1i16); + i32::from(1u16); + i64::from(1u16); + u32::from(1u16); + u64::from(1u16); + i64::from(1i32); + i64::from(1u32); + u64::from(1u32); +} diff --git a/tests/ui/cast_lossless_integer.rs b/tests/ui/cast_lossless_integer.rs index 593ffdd27663..75c639570015 100644 --- a/tests/ui/cast_lossless_integer.rs +++ b/tests/ui/cast_lossless_integer.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[warn(clippy::cast_lossless)] #[allow(clippy::no_effect, clippy::unnecessary_operation)] fn main() { diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index d9eb1be57f7c..f49dc0d9eff9 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -1,5 +1,5 @@ error: casting i8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:14:5 + --> $DIR/cast_lossless_integer.rs:16:5 | LL | 1i8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1i8)` @@ -7,103 +7,103 @@ LL | 1i8 as i16; = note: `-D clippy::cast-lossless` implied by `-D warnings` error: casting i8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:15:5 + --> $DIR/cast_lossless_integer.rs:17:5 | LL | 1i8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1i8)` error: casting i8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:16:5 + --> $DIR/cast_lossless_integer.rs:18:5 | LL | 1i8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1i8)` error: casting u8 to i16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:17:5 + --> $DIR/cast_lossless_integer.rs:19:5 | LL | 1u8 as i16; | ^^^^^^^^^^ help: try: `i16::from(1u8)` error: casting u8 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:18:5 + --> $DIR/cast_lossless_integer.rs:20:5 | LL | 1u8 as i32; | ^^^^^^^^^^ help: try: `i32::from(1u8)` error: casting u8 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:19:5 + --> $DIR/cast_lossless_integer.rs:21:5 | LL | 1u8 as i64; | ^^^^^^^^^^ help: try: `i64::from(1u8)` error: casting u8 to u16 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:20:5 + --> $DIR/cast_lossless_integer.rs:22:5 | LL | 1u8 as u16; | ^^^^^^^^^^ help: try: `u16::from(1u8)` error: casting u8 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:21:5 + --> $DIR/cast_lossless_integer.rs:23:5 | LL | 1u8 as u32; | ^^^^^^^^^^ help: try: `u32::from(1u8)` error: casting u8 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:22:5 + --> $DIR/cast_lossless_integer.rs:24:5 | LL | 1u8 as u64; | ^^^^^^^^^^ help: try: `u64::from(1u8)` error: casting i16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:23:5 + --> $DIR/cast_lossless_integer.rs:25:5 | LL | 1i16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1i16)` error: casting i16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:24:5 + --> $DIR/cast_lossless_integer.rs:26:5 | LL | 1i16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i16)` error: casting u16 to i32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:25:5 + --> $DIR/cast_lossless_integer.rs:27:5 | LL | 1u16 as i32; | ^^^^^^^^^^^ help: try: `i32::from(1u16)` error: casting u16 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:26:5 + --> $DIR/cast_lossless_integer.rs:28:5 | LL | 1u16 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u16)` error: casting u16 to u32 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:27:5 + --> $DIR/cast_lossless_integer.rs:29:5 | LL | 1u16 as u32; | ^^^^^^^^^^^ help: try: `u32::from(1u16)` error: casting u16 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:28:5 + --> $DIR/cast_lossless_integer.rs:30:5 | LL | 1u16 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u16)` error: casting i32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:29:5 + --> $DIR/cast_lossless_integer.rs:31:5 | LL | 1i32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1i32)` error: casting u32 to i64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:30:5 + --> $DIR/cast_lossless_integer.rs:32:5 | LL | 1u32 as i64; | ^^^^^^^^^^^ help: try: `i64::from(1u32)` error: casting u32 to u64 may become silently lossy if types change - --> $DIR/cast_lossless_integer.rs:31:5 + --> $DIR/cast_lossless_integer.rs:33:5 | LL | 1u32 as u64; | ^^^^^^^^^^^ help: try: `u64::from(1u32)` diff --git a/tests/ui/copies.rs b/tests/ui/copies.rs index 00e1d726207a..5db82006deaa 100644 --- a/tests/ui/copies.rs +++ b/tests/ui/copies.rs @@ -335,49 +335,16 @@ fn if_same_then_else() -> Result<&'static str, ()> { let foo = ""; return Ok(&foo[0..]); } -} - -#[warn(clippy::ifs_same_cond)] -#[allow(clippy::if_same_then_else)] // all empty blocks -fn ifs_same_cond() { - let a = 0; - let b = false; - - if b { - } else if b { - //~ ERROR ifs same condition - } - - if a == 1 { - } else if a == 1 { - //~ ERROR ifs same condition - } - - if 2 * a == 1 { - } else if 2 * a == 2 { - } else if 2 * a == 1 { - //~ ERROR ifs same condition - } else if a == 1 { - } - // See #659 - if cfg!(feature = "feature1-659") { - 1 - } else if cfg!(feature = "feature2-659") { - 2 + // false positive if_same_then_else, let(x,y) vs let(y,x), see #3559 + if true { + let foo = ""; + let (x, y) = (1, 2); + return Ok(&foo[x..y]); } else { - 3 - }; - - let mut v = vec![1]; - if v.pop() == None { - // ok, functions - } else if v.pop() == None { - } - - if v.len() == 42 { - // ok, functions - } else if v.len() == 42 { + let foo = ""; + let (y, x) = (1, 2); + return Ok(&foo[x..y]); } } diff --git a/tests/ui/copies.stderr b/tests/ui/copies.stderr index 659abf6fa7e7..3fbc279b5374 100644 --- a/tests/ui/copies.stderr +++ b/tests/ui/copies.stderr @@ -351,42 +351,5 @@ LL | | try!(Ok("foo")); LL | | } else { | |_____^ -error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:347:15 - | -LL | } else if b { - | ^ - | - = note: `-D clippy::ifs-same-cond` implied by `-D warnings` -note: same as this - --> $DIR/copies.rs:346:8 - | -LL | if b { - | ^ - -error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:352:15 - | -LL | } else if a == 1 { - | ^^^^^^ - | -note: same as this - --> $DIR/copies.rs:351:8 - | -LL | if a == 1 { - | ^^^^^^ - -error: this `if` has the same condition as a previous if - --> $DIR/copies.rs:358:15 - | -LL | } else if 2 * a == 1 { - | ^^^^^^^^^^ - | -note: same as this - --> $DIR/copies.rs:356:8 - | -LL | if 2 * a == 1 { - | ^^^^^^^^^^ - -error: aborting due to 20 previous errors +error: aborting due to 17 previous errors diff --git a/tests/ui/double_comparison.fixed b/tests/ui/double_comparison.fixed new file mode 100644 index 000000000000..fd98edb75557 --- /dev/null +++ b/tests/ui/double_comparison.fixed @@ -0,0 +1,39 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + let x = 1; + let y = 2; + if x <= y { + // do something + } + if x <= y { + // do something + } + if x >= y { + // do something + } + if x >= y { + // do something + } + if x != y { + // do something + } + if x != y { + // do something + } + if x == y { + // do something + } + if x == y { + // do something + } +} diff --git a/tests/ui/double_comparison.rs b/tests/ui/double_comparison.rs index 70b837a75b68..5d201a13ff22 100644 --- a/tests/ui/double_comparison.rs +++ b/tests/ui/double_comparison.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { let x = 1; let y = 2; diff --git a/tests/ui/double_comparison.stderr b/tests/ui/double_comparison.stderr index f4ec229fbfdc..31bab8f01120 100644 --- a/tests/ui/double_comparison.stderr +++ b/tests/ui/double_comparison.stderr @@ -1,5 +1,5 @@ error: This binary expression can be simplified - --> $DIR/double_comparison.rs:13:8 + --> $DIR/double_comparison.rs:15:8 | LL | if x == y || x < y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` @@ -7,43 +7,43 @@ LL | if x == y || x < y { = note: `-D clippy::double-comparisons` implied by `-D warnings` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:16:8 + --> $DIR/double_comparison.rs:18:8 | LL | if x < y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x <= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:19:8 + --> $DIR/double_comparison.rs:21:8 | LL | if x == y || x > y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:22:8 + --> $DIR/double_comparison.rs:24:8 | LL | if x > y || x == y { | ^^^^^^^^^^^^^^^ help: try: `x >= y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:25:8 + --> $DIR/double_comparison.rs:27:8 | LL | if x < y || x > y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:28:8 + --> $DIR/double_comparison.rs:30:8 | LL | if x > y || x < y { | ^^^^^^^^^^^^^^ help: try: `x != y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:31:8 + --> $DIR/double_comparison.rs:33:8 | LL | if x <= y && x >= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` error: This binary expression can be simplified - --> $DIR/double_comparison.rs:34:8 + --> $DIR/double_comparison.rs:36:8 | LL | if x >= y && x <= y { | ^^^^^^^^^^^^^^^^ help: try: `x == y` diff --git a/tests/ui/for_kv_map.rs b/tests/ui/for_kv_map.rs new file mode 100644 index 000000000000..549187756abd --- /dev/null +++ b/tests/ui/for_kv_map.rs @@ -0,0 +1,59 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![warn(clippy::for_kv_map)] +#![allow(clippy::used_underscore_binding)] + +use std::collections::*; +use std::rc::Rc; + +fn main() { + let m: HashMap = HashMap::new(); + for (_, v) in &m { + let _v = v; + } + + let m: Rc> = Rc::new(HashMap::new()); + for (_, v) in &*m { + let _v = v; + // Here the `*` is not actually necessary, but the test tests that we don't + // suggest + // `in *m.values()` as we used to + } + + let mut m: HashMap = HashMap::new(); + for (_, v) in &mut m { + let _v = v; + } + + let m: &mut HashMap = &mut HashMap::new(); + for (_, v) in &mut *m { + let _v = v; + } + + let m: HashMap = HashMap::new(); + let rm = &m; + for (k, _value) in rm { + let _k = k; + } + + // The following should not produce warnings. + + let m: HashMap = HashMap::new(); + // No error, _value is actually used + for (k, _value) in &m { + let _ = _value; + let _k = k; + } + + let m: HashMap = Default::default(); + for (_, v) in m { + let _v = v; + } +} diff --git a/tests/ui/for_kv_map.stderr b/tests/ui/for_kv_map.stderr new file mode 100644 index 000000000000..7b65c58f58d5 --- /dev/null +++ b/tests/ui/for_kv_map.stderr @@ -0,0 +1,54 @@ +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:18:19 + | +LL | for (_, v) in &m { + | ^^ + | + = note: `-D clippy::for-kv-map` implied by `-D warnings` +help: use the corresponding method + | +LL | for v in m.values() { + | ^ ^^^^^^^^^^ + +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:23:19 + | +LL | for (_, v) in &*m { + | ^^^ +help: use the corresponding method + | +LL | for v in (*m).values() { + | ^ ^^^^^^^^^^^^^ + +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:31:19 + | +LL | for (_, v) in &mut m { + | ^^^^^^ +help: use the corresponding method + | +LL | for v in m.values_mut() { + | ^ ^^^^^^^^^^^^^^ + +error: you seem to want to iterate on a map's values + --> $DIR/for_kv_map.rs:36:19 + | +LL | for (_, v) in &mut *m { + | ^^^^^^^ +help: use the corresponding method + | +LL | for v in (*m).values_mut() { + | ^ ^^^^^^^^^^^^^^^^^ + +error: you seem to want to iterate on a map's keys + --> $DIR/for_kv_map.rs:42:24 + | +LL | for (k, _value) in rm { + | ^^ +help: use the corresponding method + | +LL | for k in rm.keys() { + | ^ ^^^^^^^^^ + +error: aborting due to 5 previous errors + diff --git a/tests/ui/for_loop.rs b/tests/ui/for_loop.rs index 4747269bccdd..c172b0b3b770 100644 --- a/tests/ui/for_loop.rs +++ b/tests/ui/for_loop.rs @@ -333,37 +333,6 @@ fn main() { } println!("index: {}", index); - let m: HashMap = HashMap::new(); - for (_, v) in &m { - let _v = v; - } - - let m: Rc> = Rc::new(HashMap::new()); - for (_, v) in &*m { - let _v = v; - // Here the `*` is not actually necessary, but the test tests that we don't - // suggest - // `in *m.values()` as we used to - } - - let mut m: HashMap = HashMap::new(); - for (_, v) in &mut m { - let _v = v; - } - - let m: &mut HashMap = &mut HashMap::new(); - for (_, v) in &mut *m { - let _v = v; - } - - let m: HashMap = HashMap::new(); - let rm = &m; - for (k, _value) in rm { - let _k = k; - } - - test_for_kv_map(); - fn f(_: &T, _: &T) -> bool { unimplemented!() } @@ -381,17 +350,6 @@ fn main() { } } -#[allow(clippy::used_underscore_binding)] -fn test_for_kv_map() { - let m: HashMap = HashMap::new(); - - // No error, _value is actually used - for (k, _value) in &m { - let _ = _value; - let _k = k; - } -} - #[allow(dead_code)] fn partition(v: &mut [T]) -> usize { let pivot = v.len() - 1; diff --git a/tests/ui/for_loop.stderr b/tests/ui/for_loop.stderr index 937bef9f8a6f..4ded425b3210 100644 --- a/tests/ui/for_loop.stderr +++ b/tests/ui/for_loop.stderr @@ -292,60 +292,8 @@ LL | vec.iter().cloned().map(|x| out.push(x)).collect::>(); | = note: `-D clippy::unused-collect` implied by `-D warnings` -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:337:19 - | -LL | for (_, v) in &m { - | ^^ - | - = note: `-D clippy::for-kv-map` implied by `-D warnings` -help: use the corresponding method - | -LL | for v in m.values() { - | ^ ^^^^^^^^^^ - -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:342:19 - | -LL | for (_, v) in &*m { - | ^^^ -help: use the corresponding method - | -LL | for v in (*m).values() { - | ^ ^^^^^^^^^^^^^ - -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:350:19 - | -LL | for (_, v) in &mut m { - | ^^^^^^ -help: use the corresponding method - | -LL | for v in m.values_mut() { - | ^ ^^^^^^^^^^^^^^ - -error: you seem to want to iterate on a map's values - --> $DIR/for_loop.rs:355:19 - | -LL | for (_, v) in &mut *m { - | ^^^^^^^ -help: use the corresponding method - | -LL | for v in (*m).values_mut() { - | ^ ^^^^^^^^^^^^^^^^^ - -error: you seem to want to iterate on a map's keys - --> $DIR/for_loop.rs:361:24 - | -LL | for (k, _value) in rm { - | ^^ -help: use the corresponding method - | -LL | for k in rm.keys() { - | ^ ^^^^^^^^^ - error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:414:14 + --> $DIR/for_loop.rs:372:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` @@ -353,31 +301,31 @@ LL | for i in 0..src.len() { = note: `-D clippy::manual-memcpy` implied by `-D warnings` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:419:14 + --> $DIR/for_loop.rs:377:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[10..(src.len() + 10)].clone_from_slice(&src[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:424:14 + --> $DIR/for_loop.rs:382:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[10..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:429:14 + --> $DIR/for_loop.rs:387:14 | LL | for i in 11..src.len() { | ^^^^^^^^^^^^^ help: try replacing the loop by: `dst[11..src.len()].clone_from_slice(&src[(11 - 10)..(src.len() - 10)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:434:14 + --> $DIR/for_loop.rs:392:14 | LL | for i in 0..dst.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst.clone_from_slice(&src[..dst.len()])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:447:14 + --> $DIR/for_loop.rs:405:14 | LL | for i in 10..256 { | ^^^^^^^ @@ -388,34 +336,34 @@ LL | dst2[(10 + 500)..(256 + 500)].clone_from_slice(&src[10..256]) { | error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:459:14 + --> $DIR/for_loop.rs:417:14 | LL | for i in 10..LOOP_OFFSET { | ^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[(10 + LOOP_OFFSET)..(LOOP_OFFSET + LOOP_OFFSET)].clone_from_slice(&src[(10 - some_var)..(LOOP_OFFSET - some_var)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:472:14 + --> $DIR/for_loop.rs:430:14 | LL | for i in 0..src_vec.len() { | ^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst_vec[..src_vec.len()].clone_from_slice(&src_vec[..])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:501:14 + --> $DIR/for_loop.rs:459:14 | LL | for i in from..from + src.len() { | ^^^^^^^^^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + src.len()].clone_from_slice(&src[0..(from + src.len() - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:505:14 + --> $DIR/for_loop.rs:463:14 | LL | for i in from..from + 3 { | ^^^^^^^^^^^^^^ help: try replacing the loop by: `dst[from..from + 3].clone_from_slice(&src[0..(from + 3 - from)])` error: it looks like you're manually copying between slices - --> $DIR/for_loop.rs:512:14 + --> $DIR/for_loop.rs:470:14 | LL | for i in 0..src.len() { | ^^^^^^^^^^^^ help: try replacing the loop by: `dst[..src.len()].clone_from_slice(&src[..])` -error: aborting due to 51 previous errors +error: aborting due to 46 previous errors diff --git a/tests/ui/ifs_same_cond.rs b/tests/ui/ifs_same_cond.rs new file mode 100644 index 000000000000..b67e730b9372 --- /dev/null +++ b/tests/ui/ifs_same_cond.rs @@ -0,0 +1,46 @@ +#![warn(clippy::ifs_same_cond)] +#![allow(clippy::if_same_then_else)] // all empty blocks + +fn ifs_same_cond() { + let a = 0; + let b = false; + + if b { + } else if b { + //~ ERROR ifs same condition + } + + if a == 1 { + } else if a == 1 { + //~ ERROR ifs same condition + } + + if 2 * a == 1 { + } else if 2 * a == 2 { + } else if 2 * a == 1 { + //~ ERROR ifs same condition + } else if a == 1 { + } + + // See #659 + if cfg!(feature = "feature1-659") { + 1 + } else if cfg!(feature = "feature2-659") { + 2 + } else { + 3 + }; + + let mut v = vec![1]; + if v.pop() == None { + // ok, functions + } else if v.pop() == None { + } + + if v.len() == 42 { + // ok, functions + } else if v.len() == 42 { + } +} + +fn main() {} diff --git a/tests/ui/ifs_same_cond.stderr b/tests/ui/ifs_same_cond.stderr new file mode 100644 index 000000000000..0b0dd24194ed --- /dev/null +++ b/tests/ui/ifs_same_cond.stderr @@ -0,0 +1,39 @@ +error: this `if` has the same condition as a previous if + --> $DIR/ifs_same_cond.rs:9:15 + | +LL | } else if b { + | ^ + | + = note: `-D clippy::ifs-same-cond` implied by `-D warnings` +note: same as this + --> $DIR/ifs_same_cond.rs:8:8 + | +LL | if b { + | ^ + +error: this `if` has the same condition as a previous if + --> $DIR/ifs_same_cond.rs:14:15 + | +LL | } else if a == 1 { + | ^^^^^^ + | +note: same as this + --> $DIR/ifs_same_cond.rs:13:8 + | +LL | if a == 1 { + | ^^^^^^ + +error: this `if` has the same condition as a previous if + --> $DIR/ifs_same_cond.rs:20:15 + | +LL | } else if 2 * a == 1 { + | ^^^^^^^^^^ + | +note: same as this + --> $DIR/ifs_same_cond.rs:18:8 + | +LL | if 2 * a == 1 { + | ^^^^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/infinite_iter.rs b/tests/ui/infinite_iter.rs index 8f41e3ae98d9..bd266368dc4b 100644 --- a/tests/ui/infinite_iter.rs +++ b/tests/ui/infinite_iter.rs @@ -58,3 +58,22 @@ fn main() { infinite_iters(); potential_infinite_iters(); } + +mod finite_collect { + use std::collections::HashSet; + use std::iter::FromIterator; + + struct C; + impl FromIterator for C { + fn from_iter>(iter: I) -> Self { + C + } + } + + fn check_collect() { + let _: HashSet = (0..).collect(); // Infinite iter + + // Some data structures don't collect infinitely, such as `ArrayVec` + let _: C = (0..).collect(); + } +} diff --git a/tests/ui/infinite_iter.stderr b/tests/ui/infinite_iter.stderr index c64b3918db46..288285d9aaeb 100644 --- a/tests/ui/infinite_iter.stderr +++ b/tests/ui/infinite_iter.stderr @@ -105,5 +105,13 @@ error: possible infinite iteration detected LL | (0..).all(|x| x == 24); // maybe infinite iter | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 14 previous errors +error: infinite iteration detected + --> $DIR/infinite_iter.rs:74:31 + | +LL | let _: HashSet = (0..).collect(); // Infinite iter + | ^^^^^^^^^^^^^^^ + | + = note: #[deny(clippy::infinite_iter)] on by default + +error: aborting due to 15 previous errors diff --git a/tests/ui/iter_skip_next.rs b/tests/ui/iter_skip_next.rs index 4628bfbf3018..0b9d2c368277 100644 --- a/tests/ui/iter_skip_next.rs +++ b/tests/ui/iter_skip_next.rs @@ -7,44 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:option_helpers.rs + #![warn(clippy::iter_skip_next)] #![allow(clippy::blacklisted_name)] -/// Struct to generate false positive for Iterator-based lints -#[derive(Copy, Clone)] -struct IteratorFalsePositives { - foo: u32, -} - -impl IteratorFalsePositives { - fn filter(self) -> IteratorFalsePositives { - self - } - - fn next(self) -> IteratorFalsePositives { - self - } - - fn find(self) -> Option { - Some(self.foo) - } +extern crate option_helpers; - fn position(self) -> Option { - Some(self.foo) - } - - fn rposition(self) -> Option { - Some(self.foo) - } - - fn nth(self, n: usize) -> Option { - Some(self.foo) - } - - fn skip(self, _: usize) -> IteratorFalsePositives { - self - } -} +use option_helpers::IteratorFalsePositives; /// Checks implementation of `ITER_SKIP_NEXT` lint fn iter_skip_next() { diff --git a/tests/ui/iter_skip_next.stderr b/tests/ui/iter_skip_next.stderr index 6b65c1e4a1e3..037c33fbc3df 100644 --- a/tests/ui/iter_skip_next.stderr +++ b/tests/ui/iter_skip_next.stderr @@ -1,5 +1,5 @@ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:52:13 + --> $DIR/iter_skip_next.rs:22:13 | LL | let _ = some_vec.iter().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,19 +7,19 @@ LL | let _ = some_vec.iter().skip(42).next(); = note: `-D clippy::iter-skip-next` implied by `-D warnings` error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:53:13 + --> $DIR/iter_skip_next.rs:23:13 | LL | let _ = some_vec.iter().cycle().skip(42).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:54:13 + --> $DIR/iter_skip_next.rs:24:13 | LL | let _ = (1..10).skip(10).next(); | ^^^^^^^^^^^^^^^^^^^^^^^ error: called `skip(x).next()` on an iterator. This is more succinctly expressed by calling `nth(x)` - --> $DIR/iter_skip_next.rs:55:14 + --> $DIR/iter_skip_next.rs:25:14 | LL | let _ = &some_vec[..].iter().skip(3).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/methods.rs b/tests/ui/methods.rs index b470a12f7a39..fa99205d69a6 100644 --- a/tests/ui/methods.rs +++ b/tests/ui/methods.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// aux-build:option_helpers.rs + #![warn(clippy::all, clippy::pedantic, clippy::option_unwrap_used)] #![allow( clippy::blacklisted_name, @@ -22,6 +24,9 @@ clippy::useless_format )] +#[macro_use] +extern crate option_helpers; + use std::collections::BTreeMap; use std::collections::HashMap; use std::collections::HashSet; @@ -31,6 +36,8 @@ use std::iter::FromIterator; use std::rc::{self, Rc}; use std::sync::{self, Arc}; +use option_helpers::IteratorFalsePositives; + pub struct T; impl T { @@ -101,13 +108,6 @@ impl Mul for T { fn mul(self, other: T) -> T { self } // no error, obviously } -/// Utility macro to test linting behavior in `option_methods()` -/// The lints included in `option_methods()` should not lint if the call to map is partially -/// within a macro -macro_rules! opt_map { - ($opt:expr, $map:expr) => {($opt).map($map)}; -} - /// Checks implementation of the following lints: /// * `OPTION_MAP_UNWRAP_OR` /// * `OPTION_MAP_UNWRAP_OR_ELSE` @@ -169,29 +169,6 @@ fn option_methods() { ); } -/// Checks implementation of the following lints: -/// * `RESULT_MAP_UNWRAP_OR_ELSE` -fn result_methods() { - let res: Result = Ok(1); - - // Check RESULT_MAP_UNWRAP_OR_ELSE - // single line case - let _ = res.map(|x| x + 1) - - .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - // multi line cases - let _ = res.map(|x| { - x + 1 - } - ).unwrap_or_else(|e| 0); - let _ = res.map(|x| x + 1) - .unwrap_or_else(|e| - 0 - ); - // macro case - let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint -} - /// Struct to generate false positives for things with .iter() #[derive(Copy, Clone)] struct HasIter; @@ -206,42 +183,6 @@ impl HasIter { } } -/// Struct to generate false positive for Iterator-based lints -#[derive(Copy, Clone)] -struct IteratorFalsePositives { - foo: u32, -} - -impl IteratorFalsePositives { - fn filter(self) -> IteratorFalsePositives { - self - } - - fn next(self) -> IteratorFalsePositives { - self - } - - fn find(self) -> Option { - Some(self.foo) - } - - fn position(self) -> Option { - Some(self.foo) - } - - fn rposition(self) -> Option { - Some(self.foo) - } - - fn nth(self, n: usize) -> Option { - Some(self.foo) - } - - fn skip(self, _: usize) -> IteratorFalsePositives { - self - } -} - /// Checks implementation of `FILTER_NEXT` lint fn filter_next() { let v = vec![3, 2, 1, 0, -1, -2, -3]; diff --git a/tests/ui/methods.stderr b/tests/ui/methods.stderr index e87e61fbe0e4..ef3a4e2a423b 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:37:5 + --> $DIR/methods.rs:44:5 | LL | pub fn add(self, other: T) -> T { self } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,7 +7,7 @@ LL | pub fn add(self, other: T) -> T { self } = 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:48:17 + --> $DIR/methods.rs:55:17 | LL | fn into_u16(&self) -> u16 { 0 } | ^^^^^ @@ -15,13 +15,13 @@ LL | fn into_u16(&self) -> u16 { 0 } = 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:50:21 + --> $DIR/methods.rs:57:21 | LL | fn to_something(self) -> u32 { 0 } | ^^^^ error: methods called `new` usually take no self; consider choosing a less ambiguous name - --> $DIR/methods.rs:52:12 + --> $DIR/methods.rs:59:12 | LL | fn new(self) -> Self { unimplemented!(); } | ^^^^ @@ -143,40 +143,8 @@ LL | Some(x + 1) LL | }); | -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:179:13 - | -LL | let _ = res.map(|x| x + 1) - | _____________^ -LL | | -LL | | .unwrap_or_else(|e| 0); // should lint even though this call is on a separate line - | |_____________________________________^ - | - = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` - = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` - -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:183:13 - | -LL | let _ = res.map(|x| { - | _____________^ -LL | | x + 1 -LL | | } -LL | | ).unwrap_or_else(|e| 0); - | |_____________________________________^ - -error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead - --> $DIR/methods.rs:187:13 - | -LL | let _ = res.map(|x| x + 1) - | _____________^ -LL | | .unwrap_or_else(|e| -LL | | 0 -LL | | ); - | |_________________^ - error: called `filter(p).next()` on an `Iterator`. This is more succinctly expressed by calling `.find(p)` instead. - --> $DIR/methods.rs:250:13 + --> $DIR/methods.rs:191:13 | LL | let _ = v.iter().filter(|&x| *x < 0).next(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -185,7 +153,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:253:13 + --> $DIR/methods.rs:194:13 | LL | let _ = v.iter().filter(|&x| { | _____________^ @@ -195,7 +163,7 @@ LL | | ).next(); | |___________________________^ error: called `is_some()` after searching an `Iterator` with find. This is more succinctly expressed by calling `any()`. - --> $DIR/methods.rs:268:13 + --> $DIR/methods.rs:209:13 | LL | let _ = v.iter().find(|&x| *x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -204,7 +172,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:271:13 + --> $DIR/methods.rs:212:13 | LL | let _ = v.iter().find(|&x| { | _____________^ @@ -214,7 +182,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:277:13 + --> $DIR/methods.rs:218:13 | LL | let _ = v.iter().position(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -222,7 +190,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:280:13 + --> $DIR/methods.rs:221:13 | LL | let _ = v.iter().position(|&x| { | _____________^ @@ -232,7 +200,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:286:13 + --> $DIR/methods.rs:227:13 | LL | let _ = v.iter().rposition(|&x| x < 0).is_some(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,7 +208,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:289:13 + --> $DIR/methods.rs:230:13 | LL | let _ = v.iter().rposition(|&x| { | _____________^ @@ -250,7 +218,7 @@ LL | | ).is_some(); | |______________________________^ error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:324:22 + --> $DIR/methods.rs:265:22 | LL | with_constructor.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(make)` @@ -258,73 +226,73 @@ LL | with_constructor.unwrap_or(make()); = note: `-D clippy::or-fun-call` implied by `-D warnings` error: use of `unwrap_or` followed by a call to `new` - --> $DIR/methods.rs:327:5 + --> $DIR/methods.rs:268:5 | LL | with_new.unwrap_or(Vec::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_new.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:330:21 + --> $DIR/methods.rs:271:21 | LL | with_const_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:333:14 + --> $DIR/methods.rs:274:14 | LL | with_err.unwrap_or(make()); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| make())` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:336:19 + --> $DIR/methods.rs:277:19 | LL | with_err_args.unwrap_or(Vec::with_capacity(12)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|_| Vec::with_capacity(12))` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:339:5 + --> $DIR/methods.rs:280:5 | LL | with_default_trait.unwrap_or(Default::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_trait.unwrap_or_default()` error: use of `unwrap_or` followed by a call to `default` - --> $DIR/methods.rs:342:5 + --> $DIR/methods.rs:283:5 | LL | with_default_type.unwrap_or(u64::default()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `with_default_type.unwrap_or_default()` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:345:14 + --> $DIR/methods.rs:286:14 | LL | with_vec.unwrap_or(vec![]); | ^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| vec![])` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:350:21 + --> $DIR/methods.rs:291:21 | LL | without_default.unwrap_or(Foo::new()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(Foo::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:353:19 + --> $DIR/methods.rs:294:19 | LL | map.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `or_insert` followed by a function call - --> $DIR/methods.rs:356:21 + --> $DIR/methods.rs:297:21 | LL | btree.entry(42).or_insert(String::new()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `or_insert_with(String::new)` error: use of `unwrap_or` followed by a function call - --> $DIR/methods.rs:359:21 + --> $DIR/methods.rs:300:21 | LL | let _ = stringy.unwrap_or("".to_owned()); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `unwrap_or_else(|| "".to_owned())` error: called `.iter().nth()` on a Vec. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:370:23 + --> $DIR/methods.rs:311:23 | LL | let bad_vec = some_vec.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^ @@ -332,48 +300,48 @@ LL | let bad_vec = some_vec.iter().nth(3); = note: `-D clippy::iter-nth` implied by `-D warnings` error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:371:26 + --> $DIR/methods.rs:312:26 | LL | let bad_slice = &some_vec[..].iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a slice. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:372:31 + --> $DIR/methods.rs:313:31 | LL | let bad_boxed_slice = boxed_slice.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter().nth()` on a VecDeque. Calling `.get()` is both faster and more readable - --> $DIR/methods.rs:373:29 + --> $DIR/methods.rs:314:29 | LL | let bad_vec_deque = some_vec_deque.iter().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a Vec. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:378:23 + --> $DIR/methods.rs:319:23 | LL | let bad_vec = some_vec.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a slice. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:381:26 + --> $DIR/methods.rs:322:26 | LL | let bad_slice = &some_vec[..].iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: called `.iter_mut().nth()` on a VecDeque. Calling `.get_mut()` is both faster and more readable - --> $DIR/methods.rs:384:29 + --> $DIR/methods.rs:325:29 | LL | let bad_vec_deque = some_vec_deque.iter_mut().nth(3); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 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:396:13 + --> $DIR/methods.rs:337:13 | LL | let _ = opt.unwrap(); | ^^^^^^^^^^^^ | = note: `-D clippy::option-unwrap-used` implied by `-D warnings` -error: aborting due to 46 previous errors +error: aborting due to 43 previous errors diff --git a/tests/ui/no_effect.rs b/tests/ui/no_effect.rs index 8431f00e445c..6b51c50dcde9 100644 --- a/tests/ui/no_effect.rs +++ b/tests/ui/no_effect.rs @@ -67,21 +67,6 @@ unsafe fn unsafe_fn() -> i32 { 0 } -struct A(i32); -struct B { - field: i32, -} -struct C { - b: B, -} -struct D { - arr: [i32; 1], -} -const A_CONST: A = A(1); -const B: B = B { field: 1 }; -const C: C = C { b: B { field: 1 } }; -const D: D = D { arr: [1] }; - fn main() { let s = get_struct(); let s2 = get_struct(); @@ -114,10 +99,6 @@ fn main() { || x += 5; let s: String = "foo".into(); FooString { s: s }; - A_CONST.0 = 2; - B.field = 2; - C.b.field = 2; - D.arr[0] = 2; // Do not warn get_number(); @@ -127,12 +108,4 @@ fn main() { DropTuple(0); DropEnum::Tuple(0); DropEnum::Struct { field: 0 }; - let mut a_mut = A(1); - a_mut.0 = 2; - let mut b_mut = B { field: 1 }; - b_mut.field = 2; - let mut c_mut = C { b: B { field: 1 } }; - c_mut.b.field = 2; - let mut d_mut = D { arr: [1] }; - d_mut.arr[0] = 2; } diff --git a/tests/ui/no_effect.stderr b/tests/ui/no_effect.stderr index b6aab53e50f8..cc3b069f0b52 100644 --- a/tests/ui/no_effect.stderr +++ b/tests/ui/no_effect.stderr @@ -1,5 +1,5 @@ error: statement with no effect - --> $DIR/no_effect.rs:89:5 + --> $DIR/no_effect.rs:74:5 | LL | 0; | ^^ @@ -7,172 +7,148 @@ LL | 0; = note: `-D clippy::no-effect` implied by `-D warnings` error: statement with no effect - --> $DIR/no_effect.rs:90:5 + --> $DIR/no_effect.rs:75:5 | LL | s2; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:91:5 + --> $DIR/no_effect.rs:76:5 | LL | Unit; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:92:5 + --> $DIR/no_effect.rs:77:5 | LL | Tuple(0); | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:93:5 + --> $DIR/no_effect.rs:78:5 | LL | Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:94:5 + --> $DIR/no_effect.rs:79:5 | LL | Struct { ..s }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:95:5 + --> $DIR/no_effect.rs:80:5 | LL | Union { a: 0 }; | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:96:5 + --> $DIR/no_effect.rs:81:5 | LL | Enum::Tuple(0); | ^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:97:5 + --> $DIR/no_effect.rs:82:5 | LL | Enum::Struct { field: 0 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:98:5 + --> $DIR/no_effect.rs:83:5 | LL | 5 + 6; | ^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:99:5 + --> $DIR/no_effect.rs:84:5 | LL | *&42; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:100:5 + --> $DIR/no_effect.rs:85:5 | LL | &6; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:101:5 + --> $DIR/no_effect.rs:86:5 | LL | (5, 6, 7); | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:102:5 + --> $DIR/no_effect.rs:87:5 | LL | box 42; | ^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:103:5 + --> $DIR/no_effect.rs:88:5 | LL | ..; | ^^^ error: statement with no effect - --> $DIR/no_effect.rs:104:5 + --> $DIR/no_effect.rs:89:5 | LL | 5..; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:105:5 + --> $DIR/no_effect.rs:90:5 | LL | ..5; | ^^^^ error: statement with no effect - --> $DIR/no_effect.rs:106:5 + --> $DIR/no_effect.rs:91:5 | LL | 5..6; | ^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:108:5 + --> $DIR/no_effect.rs:93:5 | LL | [42, 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:109:5 + --> $DIR/no_effect.rs:94:5 | LL | [42, 55][1]; | ^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:110:5 + --> $DIR/no_effect.rs:95:5 | LL | (42, 55).1; | ^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:111:5 + --> $DIR/no_effect.rs:96:5 | LL | [42; 55]; | ^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:112:5 + --> $DIR/no_effect.rs:97:5 | LL | [42; 55][13]; | ^^^^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:114:5 + --> $DIR/no_effect.rs:99:5 | LL | || x += 5; | ^^^^^^^^^^ error: statement with no effect - --> $DIR/no_effect.rs:116:5 + --> $DIR/no_effect.rs:101:5 | LL | FooString { s: s }; | ^^^^^^^^^^^^^^^^^^^ -error: statement with no effect - --> $DIR/no_effect.rs:117:5 - | -LL | A_CONST.0 = 2; - | ^^^^^^^^^^^^^^ - -error: statement with no effect - --> $DIR/no_effect.rs:118:5 - | -LL | B.field = 2; - | ^^^^^^^^^^^^ - -error: statement with no effect - --> $DIR/no_effect.rs:119:5 - | -LL | C.b.field = 2; - | ^^^^^^^^^^^^^^ - -error: statement with no effect - --> $DIR/no_effect.rs:120:5 - | -LL | D.arr[0] = 2; - | ^^^^^^^^^^^^^ - -error: aborting due to 29 previous errors +error: aborting due to 25 previous errors diff --git a/tests/ui/println_empty_string.fixed b/tests/ui/println_empty_string.fixed new file mode 100644 index 000000000000..4ca151453fe7 --- /dev/null +++ b/tests/ui/println_empty_string.fixed @@ -0,0 +1,19 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + println!(); + println!(); + + match "a" { + _ => println!(), + } +} diff --git a/tests/ui/println_empty_string.rs b/tests/ui/println_empty_string.rs index 19a0389762a6..21f944916dbc 100644 --- a/tests/ui/println_empty_string.rs +++ b/tests/ui/println_empty_string.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { println!(); println!(""); diff --git a/tests/ui/println_empty_string.stderr b/tests/ui/println_empty_string.stderr index 89447040a33c..2370a3f1e282 100644 --- a/tests/ui/println_empty_string.stderr +++ b/tests/ui/println_empty_string.stderr @@ -1,5 +1,5 @@ error: using `println!("")` - --> $DIR/println_empty_string.rs:12:5 + --> $DIR/println_empty_string.rs:14:5 | LL | println!(""); | ^^^^^^^^^^^^ help: replace it with: `println!()` @@ -7,7 +7,7 @@ LL | println!(""); = note: `-D clippy::println-empty-string` implied by `-D warnings` error: using `println!("")` - --> $DIR/println_empty_string.rs:15:14 + --> $DIR/println_empty_string.rs:17:14 | LL | _ => println!(""), | ^^^^^^^^^^^^ help: replace it with: `println!()` diff --git a/tests/ui/ptr_offset_with_cast.fixed b/tests/ui/ptr_offset_with_cast.fixed new file mode 100644 index 000000000000..c9f58896ae13 --- /dev/null +++ b/tests/ui/ptr_offset_with_cast.fixed @@ -0,0 +1,29 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +fn main() { + let vec = vec![b'a', b'b', b'c']; + let ptr = vec.as_ptr(); + + let offset_u8 = 1_u8; + let offset_usize = 1_usize; + let offset_isize = 1_isize; + + unsafe { + ptr.add(offset_usize); + ptr.offset(offset_isize as isize); + ptr.offset(offset_u8 as isize); + + ptr.wrapping_add(offset_usize); + ptr.wrapping_offset(offset_isize as isize); + ptr.wrapping_offset(offset_u8 as isize); + } +} diff --git a/tests/ui/ptr_offset_with_cast.rs b/tests/ui/ptr_offset_with_cast.rs index 2c9e47d3f328..23eb4c6ce8ac 100644 --- a/tests/ui/ptr_offset_with_cast.rs +++ b/tests/ui/ptr_offset_with_cast.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + fn main() { let vec = vec![b'a', b'b', b'c']; let ptr = vec.as_ptr(); diff --git a/tests/ui/ptr_offset_with_cast.stderr b/tests/ui/ptr_offset_with_cast.stderr index d1795f439b29..98e3ff92a6e9 100644 --- a/tests/ui/ptr_offset_with_cast.stderr +++ b/tests/ui/ptr_offset_with_cast.stderr @@ -1,5 +1,5 @@ error: use of `offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:19:9 + --> $DIR/ptr_offset_with_cast.rs:21:9 | LL | ptr.offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.add(offset_usize)` @@ -7,7 +7,7 @@ LL | ptr.offset(offset_usize as isize); = note: `-D clippy::ptr-offset-with-cast` implied by `-D warnings` error: use of `wrapping_offset` with a `usize` casted to an `isize` - --> $DIR/ptr_offset_with_cast.rs:23:9 + --> $DIR/ptr_offset_with_cast.rs:25:9 | LL | ptr.wrapping_offset(offset_usize as isize); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr.wrapping_add(offset_usize)` diff --git a/tests/ui/result_map_unwrap_or_else.rs b/tests/ui/result_map_unwrap_or_else.rs new file mode 100644 index 000000000000..0481e4ec1b07 --- /dev/null +++ b/tests/ui/result_map_unwrap_or_else.rs @@ -0,0 +1,32 @@ +// Copyright 2014-2019 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// aux-build:option_helpers.rs + +//! Checks implementation of `RESULT_MAP_UNWRAP_OR_ELSE` + +#![warn(clippy::result_map_unwrap_or_else)] + +#[macro_use] +extern crate option_helpers; + +fn result_methods() { + let res: Result = Ok(1); + + // Check RESULT_MAP_UNWRAP_OR_ELSE + // single line case + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + // multi line cases + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + // macro case + let _ = opt_map!(res, |x| x + 1).unwrap_or_else(|e| 0); // should not lint +} + +fn main() {} diff --git a/tests/ui/result_map_unwrap_or_else.stderr b/tests/ui/result_map_unwrap_or_else.stderr new file mode 100644 index 000000000000..9f03de669e4c --- /dev/null +++ b/tests/ui/result_map_unwrap_or_else.stderr @@ -0,0 +1,27 @@ +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/result_map_unwrap_or_else.rs:24:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); // should lint even though this call is on a separate line + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::result-map-unwrap-or-else` implied by `-D warnings` + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/result_map_unwrap_or_else.rs:26:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + +error: called `map(f).unwrap_or_else(g)` on a Result value. This can be done more directly by calling `ok().map_or_else(g, f)` instead + --> $DIR/result_map_unwrap_or_else.rs:27:13 + | +LL | let _ = res.map(|x| x + 1).unwrap_or_else(|e| 0); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: replace `map(|x| x + 1).unwrap_or_else(|e| 0)` with `ok().map_or_else(|e| 0, |x| x + 1)` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/single_char_pattern.fixed b/tests/ui/single_char_pattern.fixed new file mode 100644 index 000000000000..c3c399f0ce34 --- /dev/null +++ b/tests/ui/single_char_pattern.fixed @@ -0,0 +1,61 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +use std::collections::HashSet; + +fn main() { + let x = "foo"; + x.split('x'); + x.split("xx"); + x.split('x'); + + let y = "x"; + x.split(y); + // Not yet testing for multi-byte characters + // Changing `r.len() == 1` to `r.chars().count() == 1` in `lint_clippy::single_char_pattern` + // should have done this but produced an ICE + // + // We may not want to suggest changing these anyway + // See: https://github.com/rust-lang/rust-clippy/issues/650#issuecomment-184328984 + x.split("ß"); + x.split("ℝ"); + x.split("💣"); + // Can't use this lint for unicode code points which don't fit in a char + x.split("❤️"); + x.contains('x'); + x.starts_with('x'); + x.ends_with('x'); + x.find('x'); + x.rfind('x'); + x.rsplit('x'); + x.split_terminator('x'); + x.rsplit_terminator('x'); + x.splitn(0, 'x'); + x.rsplitn(0, 'x'); + x.matches('x'); + x.rmatches('x'); + x.match_indices('x'); + x.rmatch_indices('x'); + x.trim_start_matches('x'); + x.trim_end_matches('x'); + // Make sure we escape characters correctly. + x.split('\n'); + + let h = HashSet::::new(); + h.contains("X"); // should not warn + + x.replace(";", ",").split(','); // issue #2978 + x.starts_with('\x03'); // issue #2996 + + // Issue #3204 + const S: &str = "#"; + x.find(S); +} diff --git a/tests/ui/single_char_pattern.rs b/tests/ui/single_char_pattern.rs index eeee953ab844..cf2fe66236a5 100644 --- a/tests/ui/single_char_pattern.rs +++ b/tests/ui/single_char_pattern.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + use std::collections::HashSet; fn main() { diff --git a/tests/ui/single_char_pattern.stderr b/tests/ui/single_char_pattern.stderr index 7fa3211ab720..7bc92a965369 100644 --- a/tests/ui/single_char_pattern.stderr +++ b/tests/ui/single_char_pattern.stderr @@ -1,5 +1,5 @@ error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:14:13 + --> $DIR/single_char_pattern.rs:16:13 | LL | x.split("x"); | ^^^ help: try using a char instead: `'x'` @@ -7,115 +7,115 @@ LL | x.split("x"); = note: `-D clippy::single-char-pattern` implied by `-D warnings` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:31:16 + --> $DIR/single_char_pattern.rs:33:16 | LL | x.contains("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:32:19 + --> $DIR/single_char_pattern.rs:34:19 | LL | x.starts_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:33:17 + --> $DIR/single_char_pattern.rs:35:17 | LL | x.ends_with("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:34:12 + --> $DIR/single_char_pattern.rs:36:12 | LL | x.find("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:35:13 + --> $DIR/single_char_pattern.rs:37:13 | LL | x.rfind("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:36:14 + --> $DIR/single_char_pattern.rs:38:14 | LL | x.rsplit("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:37:24 + --> $DIR/single_char_pattern.rs:39:24 | LL | x.split_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:38:25 + --> $DIR/single_char_pattern.rs:40:25 | LL | x.rsplit_terminator("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:39:17 + --> $DIR/single_char_pattern.rs:41:17 | LL | x.splitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:40:18 + --> $DIR/single_char_pattern.rs:42:18 | LL | x.rsplitn(0, "x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:41:15 + --> $DIR/single_char_pattern.rs:43:15 | LL | x.matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:42:16 + --> $DIR/single_char_pattern.rs:44:16 | LL | x.rmatches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:43:21 + --> $DIR/single_char_pattern.rs:45:21 | LL | x.match_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:44:22 + --> $DIR/single_char_pattern.rs:46:22 | LL | x.rmatch_indices("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:45:26 + --> $DIR/single_char_pattern.rs:47:26 | LL | x.trim_start_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:46:24 + --> $DIR/single_char_pattern.rs:48:24 | LL | x.trim_end_matches("x"); | ^^^ help: try using a char instead: `'x'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:48:13 + --> $DIR/single_char_pattern.rs:50:13 | LL | x.split("/n"); | ^^^^ help: try using a char instead: `'/n'` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:53:31 + --> $DIR/single_char_pattern.rs:55:31 | LL | x.replace(";", ",").split(","); // issue #2978 | ^^^ help: try using a char instead: `','` error: single-character string constant used as pattern - --> $DIR/single_char_pattern.rs:54:19 + --> $DIR/single_char_pattern.rs:56:19 | LL | x.starts_with("/x03"); // issue #2996 | ^^^^^^ help: try using a char instead: `'/x03'` diff --git a/tests/ui/string_extend.fixed b/tests/ui/string_extend.fixed new file mode 100644 index 000000000000..7463baff2afa --- /dev/null +++ b/tests/ui/string_extend.fixed @@ -0,0 +1,41 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[derive(Copy, Clone)] +struct HasChars; + +impl HasChars { + fn chars(self) -> std::str::Chars<'static> { + "HasChars".chars() + } +} + +fn main() { + let abc = "abc"; + let def = String::from("def"); + let mut s = String::new(); + + s.push_str(abc); + s.push_str(abc); + + s.push_str("abc"); + s.push_str("abc"); + + s.push_str(&def); + s.push_str(&def); + + s.extend(abc.chars().skip(1)); + s.extend("abc".chars().skip(1)); + s.extend(['a', 'b', 'c'].iter()); + + let f = HasChars; + s.extend(f.chars()); +} diff --git a/tests/ui/string_extend.rs b/tests/ui/string_extend.rs index 56b466ede20a..3a2ad2695dec 100644 --- a/tests/ui/string_extend.rs +++ b/tests/ui/string_extend.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[derive(Copy, Clone)] struct HasChars; diff --git a/tests/ui/string_extend.stderr b/tests/ui/string_extend.stderr index 80a490b7884c..5638dd87ed19 100644 --- a/tests/ui/string_extend.stderr +++ b/tests/ui/string_extend.stderr @@ -1,5 +1,5 @@ error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:25:5 + --> $DIR/string_extend.rs:27:5 | LL | s.extend(abc.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(abc)` @@ -7,13 +7,13 @@ LL | s.extend(abc.chars()); = note: `-D clippy::string-extend-chars` implied by `-D warnings` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:28:5 + --> $DIR/string_extend.rs:30:5 | LL | s.extend("abc".chars()); | ^^^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str("abc")` error: calling `.extend(_.chars())` - --> $DIR/string_extend.rs:31:5 + --> $DIR/string_extend.rs:33:5 | LL | s.extend(def.chars()); | ^^^^^^^^^^^^^^^^^^^^^ help: try this: `s.push_str(&def)` diff --git a/tests/ui/temporary_assignment.rs b/tests/ui/temporary_assignment.rs index 79c090f05722..5581f5be766d 100644 --- a/tests/ui/temporary_assignment.rs +++ b/tests/ui/temporary_assignment.rs @@ -11,10 +11,16 @@ use std::ops::{Deref, DerefMut}; +struct TupleStruct(i32); + struct Struct { field: i32, } +struct MultiStruct { + structure: Struct, +} + struct Wrapper<'a> { inner: &'a mut Struct, } @@ -32,15 +38,47 @@ impl<'a> DerefMut for Wrapper<'a> { } } +struct ArrayStruct { + array: [i32; 1], +} + +const A: TupleStruct = TupleStruct(1); +const B: Struct = Struct { field: 1 }; +const C: MultiStruct = MultiStruct { + structure: Struct { field: 1 }, +}; +const D: ArrayStruct = ArrayStruct { array: [1] }; + fn main() { let mut s = Struct { field: 0 }; let mut t = (0, 0); Struct { field: 0 }.field = 1; + MultiStruct { + structure: Struct { field: 0 }, + } + .structure + .field = 1; + ArrayStruct { array: [0] }.array[0] = 1; (0, 0).0 = 1; + A.0 = 2; + B.field = 2; + C.structure.field = 2; + D.array[0] = 2; + // no error s.field = 1; t.0 = 1; Wrapper { inner: &mut s }.field = 1; + let mut a_mut = TupleStruct(1); + a_mut.0 = 2; + let mut b_mut = Struct { field: 1 }; + b_mut.field = 2; + let mut c_mut = MultiStruct { + structure: Struct { field: 1 }, + }; + c_mut.structure.field = 2; + let mut d_mut = ArrayStruct { array: [1] }; + d_mut.array[0] = 2; } diff --git a/tests/ui/temporary_assignment.stderr b/tests/ui/temporary_assignment.stderr index a97363850483..13ece2858b99 100644 --- a/tests/ui/temporary_assignment.stderr +++ b/tests/ui/temporary_assignment.stderr @@ -1,5 +1,5 @@ error: assignment to temporary - --> $DIR/temporary_assignment.rs:39:5 + --> $DIR/temporary_assignment.rs:56:5 | LL | Struct { field: 0 }.field = 1; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,10 +7,50 @@ LL | Struct { field: 0 }.field = 1; = note: `-D clippy::temporary-assignment` implied by `-D warnings` error: assignment to temporary - --> $DIR/temporary_assignment.rs:40:5 + --> $DIR/temporary_assignment.rs:57:5 + | +LL | / MultiStruct { +LL | | structure: Struct { field: 0 }, +LL | | } +LL | | .structure +LL | | .field = 1; + | |______________^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:62:5 + | +LL | ArrayStruct { array: [0] }.array[0] = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:63:5 | LL | (0, 0).0 = 1; | ^^^^^^^^^^^^ -error: aborting due to 2 previous errors +error: assignment to temporary + --> $DIR/temporary_assignment.rs:65:5 + | +LL | A.0 = 2; + | ^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:66:5 + | +LL | B.field = 2; + | ^^^^^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:67:5 + | +LL | C.structure.field = 2; + | ^^^^^^^^^^^^^^^^^^^^^ + +error: assignment to temporary + --> $DIR/temporary_assignment.rs:68:5 + | +LL | D.array[0] = 2; + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors diff --git a/tests/ui/unnecessary_ref.fixed b/tests/ui/unnecessary_ref.fixed new file mode 100644 index 000000000000..3617641a116c --- /dev/null +++ b/tests/ui/unnecessary_ref.fixed @@ -0,0 +1,23 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![feature(stmt_expr_attributes)] +#![allow(unused_variables)] + +struct Outer { + inner: u32, +} + +#[deny(clippy::ref_in_deref)] +fn main() { + let outer = Outer { inner: 0 }; + let inner = outer.inner; +} diff --git a/tests/ui/unnecessary_ref.rs b/tests/ui/unnecessary_ref.rs index 31aa367e5064..48101c87a54e 100644 --- a/tests/ui/unnecessary_ref.rs +++ b/tests/ui/unnecessary_ref.rs @@ -7,8 +7,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(tool_attributes)] +// run-rustfix + #![feature(stmt_expr_attributes)] +#![allow(unused_variables)] struct Outer { inner: u32, diff --git a/tests/ui/unnecessary_ref.stderr b/tests/ui/unnecessary_ref.stderr index 77503026bde6..863a6389e7fc 100644 --- a/tests/ui/unnecessary_ref.stderr +++ b/tests/ui/unnecessary_ref.stderr @@ -1,11 +1,11 @@ error: Creating a reference that is immediately dereferenced. - --> $DIR/unnecessary_ref.rs:20:17 + --> $DIR/unnecessary_ref.rs:22:17 | LL | let inner = (&outer).inner; - | ^^^^^^^^ help: try this: `outer.inner` + | ^^^^^^^^ help: try this: `outer` | note: lint level defined here - --> $DIR/unnecessary_ref.rs:17:8 + --> $DIR/unnecessary_ref.rs:19:8 | LL | #[deny(clippy::ref_in_deref)] | ^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/unreadable_literal.fixed b/tests/ui/unreadable_literal.fixed new file mode 100644 index 000000000000..4c466035a047 --- /dev/null +++ b/tests/ui/unreadable_literal.fixed @@ -0,0 +1,29 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#[warn(clippy::unreadable_literal)] +#[allow(unused_variables)] +fn main() { + let good = ( + 0b1011_i64, + 0o1_234_u32, + 0x1_234_567, + 65536, + 1_2345_6789, + 1234_f32, + 1_234.12_f32, + 1_234.123_f32, + 1.123_4_f32, + ); + let bad = (0b11_0110_i64, 0x0123_4567_8901_usize, 123_456_f32, 1.234_567_f32); + let good_sci = 1.1234e1; + let bad_sci = 1.123_456e1; +} diff --git a/tests/ui/unreadable_literal.rs b/tests/ui/unreadable_literal.rs index ad29fcf8fe41..8ade2f6a8630 100644 --- a/tests/ui/unreadable_literal.rs +++ b/tests/ui/unreadable_literal.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #[warn(clippy::unreadable_literal)] #[allow(unused_variables)] fn main() { diff --git a/tests/ui/unreadable_literal.stderr b/tests/ui/unreadable_literal.stderr index 6696f155fb86..685804858536 100644 --- a/tests/ui/unreadable_literal.stderr +++ b/tests/ui/unreadable_literal.stderr @@ -1,5 +1,5 @@ error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:16 + --> $DIR/unreadable_literal.rs:26:16 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `0b11_0110_i64` @@ -7,25 +7,25 @@ LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32) = note: `-D clippy::unreadable-literal` implied by `-D warnings` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:30 + --> $DIR/unreadable_literal.rs:26:30 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^^^^^^^^ help: consider: `0x0123_4567_8901_usize` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:51 + --> $DIR/unreadable_literal.rs:26:51 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^ help: consider: `123_456_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:24:63 + --> $DIR/unreadable_literal.rs:26:63 | LL | let bad = (0b110110_i64, 0x12345678901_usize, 123456_f32, 1.234567_f32); | ^^^^^^^^^^^^ help: consider: `1.234_567_f32` error: long literal lacking separators - --> $DIR/unreadable_literal.rs:26:19 + --> $DIR/unreadable_literal.rs:28:19 | LL | let bad_sci = 1.123456e1; | ^^^^^^^^^^ help: consider: `1.123_456e1` diff --git a/tests/ui/update-references.sh b/tests/ui/update-references.sh index aa99d35f7aa7..d6995985a3b1 100755 --- a/tests/ui/update-references.sh +++ b/tests/ui/update-references.sh @@ -34,6 +34,7 @@ shift while [[ "$1" != "" ]]; do STDERR_NAME="${1/%.rs/.stderr}" STDOUT_NAME="${1/%.rs/.stdout}" + FIXED_NAME="${1/%.rs/.fixed}" shift if [ -f $BUILD_DIR/$STDOUT_NAME ] && \ ! (diff $BUILD_DIR/$STDOUT_NAME $MYDIR/$STDOUT_NAME >& /dev/null); then @@ -45,6 +46,11 @@ while [[ "$1" != "" ]]; do echo updating $MYDIR/$STDERR_NAME cp $BUILD_DIR/$STDERR_NAME $MYDIR/$STDERR_NAME fi + if [ -f $BUILD_DIR/$FIXED_NAME ] && \ + ! (diff $BUILD_DIR/$FIXED_NAME $MYDIR/$FIXED_NAME >& /dev/null); then + echo updating $MYDIR/$FIXED_NAME + cp $BUILD_DIR/$FIXED_NAME $MYDIR/$FIXED_NAME + fi done diff --git a/tests/ui/use_self.rs b/tests/ui/use_self.rs index b201e160ebd9..a01cb3e7021d 100644 --- a/tests/ui/use_self.rs +++ b/tests/ui/use_self.rs @@ -226,6 +226,22 @@ mod tuple_structs { } } +mod macros { + macro_rules! use_self_expand { + () => { + fn new() -> Foo { + Foo {} + } + }; + } + + struct Foo {} + + impl Foo { + use_self_expand!(); // Should lint in local macros + } +} + mod issue3410 { struct A; diff --git a/tests/ui/use_self.stderr b/tests/ui/use_self.stderr index d52fce76de59..6c5dbf9111d6 100644 --- a/tests/ui/use_self.stderr +++ b/tests/ui/use_self.stderr @@ -132,5 +132,23 @@ error: unnecessary structure name repetition LL | TS(0) | ^^ help: use the applicable keyword: `Self` -error: aborting due to 22 previous errors +error: unnecessary structure name repetition + --> $DIR/use_self.rs:232:25 + | +LL | fn new() -> Foo { + | ^^^ help: use the applicable keyword: `Self` +... +LL | use_self_expand!(); // Should lint in local macros + | ------------------- in this macro invocation + +error: unnecessary structure name repetition + --> $DIR/use_self.rs:233:17 + | +LL | Foo {} + | ^^^ help: use the applicable keyword: `Self` +... +LL | use_self_expand!(); // Should lint in local macros + | ------------------- in this macro invocation + +error: aborting due to 24 previous errors diff --git a/tests/ui/vec.fixed b/tests/ui/vec.fixed new file mode 100644 index 000000000000..2eaba1c408a1 --- /dev/null +++ b/tests/ui/vec.fixed @@ -0,0 +1,64 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![warn(clippy::useless_vec)] + +#[derive(Debug)] +struct NonCopy; + +fn on_slice(_: &[u8]) {} +#[allow(clippy::ptr_arg)] +fn on_vec(_: &Vec) {} + +struct Line { + length: usize, +} + +impl Line { + fn length(&self) -> usize { + self.length + } +} + +fn main() { + on_slice(&[]); + on_slice(&[]); + + on_slice(&[1, 2]); + on_slice(&[1, 2]); + + on_slice(&[1, 2]); + on_slice(&[1, 2]); + #[rustfmt::skip] + on_slice(&[1, 2]); + on_slice(&[1, 2]); + + on_slice(&[1; 2]); + on_slice(&[1; 2]); + + on_vec(&vec![]); + on_vec(&vec![1, 2]); + on_vec(&vec![1; 2]); + + // Now with non-constant expressions + let line = Line { length: 2 }; + + on_slice(&vec![2; line.length]); + on_slice(&vec![2; line.length()]); + + for a in &[1, 2, 3] { + println!("{:?}", a); + } + + for a in vec![NonCopy, NonCopy] { + println!("{:?}", a); + } +} diff --git a/tests/ui/vec.rs b/tests/ui/vec.rs index f795c11ec5b1..1648215ed35c 100644 --- a/tests/ui/vec.rs +++ b/tests/ui/vec.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #![warn(clippy::useless_vec)] #[derive(Debug)] diff --git a/tests/ui/vec.stderr b/tests/ui/vec.stderr index 0afb95629d9c..96dd187ccc5a 100644 --- a/tests/ui/vec.stderr +++ b/tests/ui/vec.stderr @@ -1,5 +1,5 @@ error: useless use of `vec!` - --> $DIR/vec.rs:30:14 + --> $DIR/vec.rs:32:14 | LL | on_slice(&vec![]); | ^^^^^^^ help: you can use a slice directly: `&[]` @@ -7,31 +7,31 @@ LL | on_slice(&vec![]); = note: `-D clippy::useless-vec` implied by `-D warnings` error: useless use of `vec!` - --> $DIR/vec.rs:33:14 + --> $DIR/vec.rs:35:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:36:14 + --> $DIR/vec.rs:38:14 | LL | on_slice(&vec![1, 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:39:14 + --> $DIR/vec.rs:41:14 | LL | on_slice(&vec!(1, 2)); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2]` error: useless use of `vec!` - --> $DIR/vec.rs:42:14 + --> $DIR/vec.rs:44:14 | LL | on_slice(&vec![1; 2]); | ^^^^^^^^^^^ help: you can use a slice directly: `&[1; 2]` error: useless use of `vec!` - --> $DIR/vec.rs:55:14 + --> $DIR/vec.rs:57:14 | LL | for a in vec![1, 2, 3] { | ^^^^^^^^^^^^^ help: you can use a slice directly: `&[1, 2, 3]` diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed new file mode 100644 index 000000000000..68b8185083d3 --- /dev/null +++ b/tests/ui/writeln_empty_string.fixed @@ -0,0 +1,29 @@ +// Copyright 2014-2018 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// run-rustfix + +#![allow(unused_must_use)] +#![warn(clippy::writeln_empty_string)] +use std::io::Write; + +fn main() { + let mut v = Vec::new(); + + // These should fail + writeln!(&mut v); + + let mut suggestion = Vec::new(); + writeln!(&mut suggestion); + + // These should be fine + writeln!(&mut v); + writeln!(&mut v, " "); + write!(&mut v, ""); +} diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 71b5df48bfaa..ba43552af233 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -7,6 +7,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// run-rustfix + #![allow(unused_must_use)] #![warn(clippy::writeln_empty_string)] use std::io::Write; diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 9b4061f0fe4e..119710c0cdb1 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,5 +1,5 @@ error: using `writeln!(&mut v, "")` - --> $DIR/writeln_empty_string.rs:18:5 + --> $DIR/writeln_empty_string.rs:20:5 | LL | writeln!(&mut v, ""); | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` @@ -7,7 +7,7 @@ LL | writeln!(&mut v, ""); = note: `-D clippy::writeln-empty-string` implied by `-D warnings` error: using `writeln!(&mut suggestion, "")` - --> $DIR/writeln_empty_string.rs:21:5 + --> $DIR/writeln_empty_string.rs:23:5 | LL | writeln!(&mut suggestion, ""); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)`